Reviewed-on: http://39.105.23.186:3000/develop/digimeta-MultiSaas/pulls/2tags/v0.8.5
| @@ -240,6 +240,13 @@ | |||
| <version>${xueyi.version}</version> | |||
| </dependency> | |||
| <!-- Mqtt服务 --> | |||
| <dependency> | |||
| <groupId>com.xueyi</groupId> | |||
| <artifactId>xueyi-common-mqtt</artifactId> | |||
| <version>${xueyi.version}</version> | |||
| </dependency> | |||
| <!-- 分布式事务 --> | |||
| <dependency> | |||
| <groupId>com.xueyi</groupId> | |||
| @@ -0,0 +1,11 @@ | |||
| package com.xueyi.file.api.domain; | |||
| import lombok.Data; | |||
| @Data | |||
| public class DigitalmanLogFile { | |||
| String devId; | |||
| String logType; | |||
| String timestamp; | |||
| } | |||
| @@ -3,6 +3,7 @@ package com.xueyi.system.api.digitalmans.domain.dto; | |||
| import com.xueyi.system.api.digitalmans.domain.po.DmManDevicePo; | |||
| import lombok.Data; | |||
| import lombok.EqualsAndHashCode; | |||
| import lombok.ToString; | |||
| import java.io.Serial; | |||
| @@ -12,6 +13,7 @@ import java.io.Serial; | |||
| * @author xueyi | |||
| */ | |||
| @Data | |||
| @ToString(callSuper = true) | |||
| @EqualsAndHashCode(callSuper = true) | |||
| public class DmManDeviceDto extends DmManDevicePo { | |||
| @@ -2,11 +2,10 @@ package com.xueyi.system.api.digitalmans.domain.dto; | |||
| import com.xueyi.system.api.digitalmans.domain.po.DmDigitalmanPo; | |||
| import com.xueyi.system.api.digitalmans.domain.po.DmDigitalmanWorktimePo; | |||
| import com.xueyi.system.api.digitalmans.domain.po.DmModelPo; | |||
| import com.xueyi.system.api.organize.domain.vo.SysDeptExt; | |||
| import com.xueyi.system.api.resource.domain.po.DmResourcesPo; | |||
| import lombok.Data; | |||
| import lombok.EqualsAndHashCode; | |||
| import lombok.NoArgsConstructor; | |||
| import java.io.Serial; | |||
| @@ -21,5 +20,7 @@ public class DmSyncDigitalmanDto extends DmDigitalmanPo { | |||
| protected DmResourcesPo icon; | |||
| protected DmResourcesPo screenOff; | |||
| protected DmDigitalmanWorktimePo worktime; | |||
| protected SysDeptExt workdayHour; | |||
| protected String iconPos; | |||
| } | |||
| @@ -26,16 +26,16 @@ public class DmDigitalmanExtPo extends TBaseEntity { | |||
| private static final long serialVersionUID = 1L; | |||
| /** 数字人id */ | |||
| @Excel(name = "会议室ID") | |||
| @Excel(name = "数字人扩展表ID") | |||
| protected Long id; | |||
| /** 访客电话 */ | |||
| @Excel(name = "访客电话") | |||
| @Excel(name = "snCode") | |||
| protected String snCode; | |||
| /** 技能信息 */ | |||
| @Excel(name = "技能信息") | |||
| @Excel(name = "ip地址") | |||
| protected String ipAddr; | |||
| /** 访客公司 */ | |||
| @@ -68,6 +68,15 @@ public class DmVisitRecordsPo extends TBaseEntity { | |||
| protected Long deptId; | |||
| protected String visitorCode; | |||
| private String receiverName; | |||
| private String receiverPhone; | |||
| public String toString(){ | |||
| return new StringBuilder("VisitorId: ").append(visitorId).append(", UserId: ").append(userId).append(", VisitDate: ").append(visitDate).append(", VisitTime: ").append(visitTime).append(", Duration: ").append(duration).append(", RecordStatus: ").append(recordStatus).append(", DeptId: ").append(deptId).append(", Num: ").append(num).toString(); | |||
| } | |||
| @@ -0,0 +1,22 @@ | |||
| package com.xueyi.system.api.digitalmans.domain.vo; | |||
| import lombok.Data; | |||
| import lombok.NoArgsConstructor; | |||
| import java.io.Serial; | |||
| import java.io.Serializable; | |||
| @Data | |||
| @NoArgsConstructor | |||
| public class DashboardVo implements Serializable { | |||
| @Serial | |||
| private static final long serialVersionUID = 1L; | |||
| /** | |||
| * 数字人数 | |||
| */ | |||
| private Integer digitalMans; | |||
| private Integer onlineDevices; | |||
| private Integer AlertNear7Days; | |||
| private Integer onProcessAlert; | |||
| } | |||
| @@ -0,0 +1,21 @@ | |||
| package com.xueyi.system.api.digitalmans.domain.vo; | |||
| import lombok.Data; | |||
| import lombok.NoArgsConstructor; | |||
| import java.io.Serial; | |||
| import java.io.Serializable; | |||
| @Data | |||
| @NoArgsConstructor | |||
| public class NumberOfAlertToChartVo implements Serializable { | |||
| @Serial | |||
| private static final long serialVersionUID = 1L; | |||
| private String numberOfAlert; | |||
| private String date; | |||
| } | |||
| @@ -0,0 +1,22 @@ | |||
| package com.xueyi.system.api.digitalmans.domain.vo; | |||
| import lombok.Data; | |||
| import lombok.NoArgsConstructor; | |||
| import java.io.Serial; | |||
| import java.io.Serializable; | |||
| @Data | |||
| @NoArgsConstructor | |||
| public class NumberOfOnlineToChartVo implements Serializable { | |||
| @Serial | |||
| private static final long serialVersionUID = 1L; | |||
| private String numberOfOnline; | |||
| private Integer total; | |||
| private String date; | |||
| } | |||
| @@ -0,0 +1,28 @@ | |||
| package com.xueyi.system.api.digitalmans.feign; | |||
| import com.xueyi.common.core.constant.basic.SecurityConstants; | |||
| import com.xueyi.common.core.constant.basic.ServiceConstants; | |||
| import com.xueyi.system.api.organize.feign.factory.RemoteUserFallbackFactory; | |||
| import org.springframework.cloud.openfeign.FeignClient; | |||
| import org.springframework.web.bind.annotation.PostMapping; | |||
| import org.springframework.web.bind.annotation.RequestBody; | |||
| import org.springframework.web.bind.annotation.RequestHeader; | |||
| /** | |||
| * 一体机mqtt服务 | |||
| * | |||
| * @author yk | |||
| */ | |||
| @FeignClient(contextId = "remoteDigitalmanMqttService", value = ServiceConstants.SYSTEM_SERVICE, fallbackFactory = RemoteUserFallbackFactory.class) | |||
| public interface RemoteDigitalmanMqttService { | |||
| @PostMapping("/man/api/mqtt/heartbeat") | |||
| public void heartbeat(@RequestBody(required = true) String message,@RequestHeader(SecurityConstants.ENTERPRISE_ID) Long enterpriseId, @RequestHeader(SecurityConstants.SOURCE_NAME) String sourceName, @RequestHeader(SecurityConstants.FROM_SOURCE) String source); | |||
| @PostMapping("/man/api/mqtt/log-upload") | |||
| public void logUpload(@RequestBody(required = true) String message,@RequestHeader(SecurityConstants.ENTERPRISE_ID) Long enterpriseId, @RequestHeader(SecurityConstants.SOURCE_NAME) String sourceName, @RequestHeader(SecurityConstants.FROM_SOURCE) String source); | |||
| } | |||
| @@ -3,14 +3,14 @@ package com.xueyi.system.api.digitalmans.feign; | |||
| import com.xueyi.common.core.constant.basic.SecurityConstants; | |||
| import com.xueyi.common.core.constant.basic.ServiceConstants; | |||
| import com.xueyi.common.core.web.result.R; | |||
| import com.xueyi.system.api.digitalmans.domain.dto.DmManDeviceDto; | |||
| import com.xueyi.system.api.digitalmans.domain.dto.DmSyncDigitalmanDto; | |||
| import com.xueyi.system.api.digitalmans.domain.po.DmDigitalmanExtPo; | |||
| import com.xueyi.system.api.organize.feign.factory.RemoteUserFallbackFactory; | |||
| import org.springframework.cloud.openfeign.FeignClient; | |||
| import org.springframework.web.bind.annotation.GetMapping; | |||
| import org.springframework.web.bind.annotation.PostMapping; | |||
| import org.springframework.web.bind.annotation.RequestHeader; | |||
| import org.springframework.web.bind.annotation.RequestParam; | |||
| import org.springframework.web.bind.annotation.*; | |||
| import java.util.List; | |||
| /** | |||
| * 用户服务 | |||
| @@ -35,6 +35,13 @@ public interface RemoteDigitalmanService { | |||
| public R<Integer> initInner(@RequestParam(value = "snCode") String snCode, | |||
| @RequestHeader(SecurityConstants.ENTERPRISE_ID) Long enterpriseId, @RequestHeader(SecurityConstants.SOURCE_NAME) String sourceName, @RequestHeader(SecurityConstants.FROM_SOURCE) String source); | |||
| @PostMapping("/man/inner/sync") | |||
| public R<Boolean> sync(@RequestHeader(SecurityConstants.ENTERPRISE_ID) Long enterpriseId, @RequestHeader(SecurityConstants.SOURCE_NAME) String sourceName, @RequestHeader(SecurityConstants.FROM_SOURCE) String source); | |||
| @PostMapping("/man/inner/update_device_online") | |||
| public R<Boolean> updateDeviceOnline(@RequestParam(value = "deviceId")String deviceId, @RequestHeader(SecurityConstants.ENTERPRISE_ID) Long enterpriseId, @RequestHeader(SecurityConstants.SOURCE_NAME) String sourceName, @RequestHeader(SecurityConstants.FROM_SOURCE) String source); | |||
| @PostMapping("/man/inner/sync_ext_isonline") | |||
| public R<Integer> syncExtIsonline(@RequestBody List<DmManDeviceDto> devices, @RequestHeader(SecurityConstants.ENTERPRISE_ID) Long enterpriseId, @RequestHeader(SecurityConstants.SOURCE_NAME) String sourceName, @RequestHeader(SecurityConstants.FROM_SOURCE) String source); | |||
| @GetMapping("/man/inner-api/devInfo/{devId}") | |||
| public R<DmDigitalmanExtPo> devInfo(@RequestParam(value = "devId") String devId, @RequestHeader(SecurityConstants.ENTERPRISE_ID) Long enterpriseId, @RequestHeader(SecurityConstants.SOURCE_NAME) String sourceName, @RequestHeader(SecurityConstants.FROM_SOURCE) String source); | |||
| } | |||
| @@ -35,4 +35,7 @@ public interface RemoteManDeviceService { | |||
| @PutMapping(value = "/manDevice/inner/info") | |||
| R<Integer> manDeviceInfoInnerUpdate(@RequestBody DmActiveVo vo); | |||
| @PostMapping(value = "/manDevice/inner/sync_numbers_of_online") | |||
| R<Integer> syncNumbersOfOnline(); | |||
| } | |||
| @@ -0,0 +1,11 @@ | |||
| package com.xueyi.system.api.exception.domain.merge; | |||
| public interface MergeGroup { | |||
| /** 设备日志关联 -》 日志 */ | |||
| String LOG_DmDevice_GROUP = "LOG_DmDevice_GROUP"; | |||
| /** 模块菜单关联 -》 菜单 */ | |||
| String MENU_SysModule_GROUP = "MENU_SysModule_GROUP"; | |||
| } | |||
| @@ -41,7 +41,13 @@ public interface RemoteMeetingService { | |||
| @PostMapping(value = "/meeting/inner-api/lists") | |||
| JSONObject listsInner(@RequestParam("dateStr") String dateStr, @RequestParam("spaceId") Long spaceId, @RequestHeader(SecurityConstants.ENTERPRISE_ID) Long enterpriseId, @RequestHeader(SecurityConstants.SOURCE_NAME) String sourceName, @RequestHeader(SecurityConstants.FROM_SOURCE) String source); | |||
| @GetMapping(value = "/meeting/inner-api/lists") | |||
| JSONObject listsAllInner(@RequestHeader(SecurityConstants.ENTERPRISE_ID) Long enterpriseId, @RequestHeader(SecurityConstants.SOURCE_NAME) String sourceName, @RequestHeader(SecurityConstants.FROM_SOURCE) String source); | |||
| @PostMapping(value = "/meeting/inner-api/date-lists") | |||
| JSONObject listsByDate(@RequestParam("dateStr") String dateStr, @RequestHeader(SecurityConstants.ENTERPRISE_ID) Long enterpriseId, @RequestHeader(SecurityConstants.SOURCE_NAME) String sourceName, @RequestHeader(SecurityConstants.FROM_SOURCE) String source); | |||
| @PostMapping(value = "/meeting/inner-api/lists-all") | |||
| JSONObject listAllInner(@RequestParam("dateStr") String dateStr, @RequestParam("spaceId") Long spaceId, @RequestHeader(SecurityConstants.ENTERPRISE_ID) Long enterpriseId, @RequestHeader(SecurityConstants.SOURCE_NAME) String sourceName, @RequestHeader(SecurityConstants.FROM_SOURCE) String source); | |||
| } | |||
| @@ -51,10 +51,20 @@ public class RemoteMeetingFallbackFactory implements FallbackFactory<RemoteMeeti | |||
| return R.fail("获取会议室预约列表失败:" + throwable.getMessage()).toJson(); | |||
| } | |||
| @Override | |||
| public JSONObject listsAllInner( Long enterpriseId, String sourceName, String source) { | |||
| return R.fail("获取会议室预约列表失败:" + throwable.getMessage()).toJson(); | |||
| } | |||
| @Override | |||
| public JSONObject listsByDate(String dateStr, Long enterpriseId, String sourceName, String source) { | |||
| return R.fail("获取会议室预约列表失败:" + throwable.getMessage()).toJson(); | |||
| } | |||
| @Override | |||
| public JSONObject listAllInner(String dateStr, Long spaceId, Long enterpriseId, String sourceName, String source) { | |||
| return R.fail("获取会议室预约列表失败:" + throwable.getMessage()).toJson(); | |||
| } | |||
| }; | |||
| } | |||
| } | |||
| @@ -0,0 +1,26 @@ | |||
| package com.xueyi.system.api.organize.domain.vo; | |||
| import lombok.Data; | |||
| import lombok.NoArgsConstructor; | |||
| @Data | |||
| @NoArgsConstructor | |||
| public class SysDeptExt { | |||
| /** Id */ | |||
| private Long deptId; | |||
| /** 上班打卡开始时间 */ | |||
| private String onDutyHourStart; | |||
| /** 上班打卡结束时间 */ | |||
| private String onDutyHourEnd; | |||
| /** 下班打卡开始时间 */ | |||
| private String offDutyHourStart; | |||
| /** 下班打卡结束时间 */ | |||
| private String offDutyHourEnd; | |||
| } | |||
| @@ -30,6 +30,8 @@ public class DmVisitCommonDto { | |||
| private String reason; | |||
| private Long recordId; | |||
| @Override | |||
| public String toString() { | |||
| @@ -1,8 +1,11 @@ | |||
| package com.xueyi.system.api.staff.domain.vo; | |||
| import cn.hutool.core.date.DateTime; | |||
| import lombok.Data; | |||
| import lombok.NoArgsConstructor; | |||
| import net.sf.jsqlparser.expression.DateTimeLiteralExpression; | |||
| import java.time.LocalDateTime; | |||
| import java.util.List; | |||
| @Data | |||
| @@ -14,6 +17,7 @@ public class DmStaffFeature { | |||
| private String typeId; | |||
| private String nickName; | |||
| private int isDel; | |||
| private LocalDateTime syncTime; | |||
| private String feature; | |||
| private List<Double> dFeatures; | |||
| @@ -1,15 +1,16 @@ | |||
| package com.xueyi.system.api.staff.feign; | |||
| import com.alibaba.fastjson2.JSONObject; | |||
| import com.xueyi.common.core.constant.basic.SecurityConstants; | |||
| import com.xueyi.common.core.constant.basic.ServiceConstants; | |||
| import com.xueyi.common.core.web.result.AjaxResult; | |||
| import com.xueyi.common.core.web.result.R; | |||
| import com.xueyi.system.api.organize.domain.dto.SysEnterpriseDto; | |||
| import com.xueyi.system.api.organize.feign.factory.RemoteUserFallbackFactory; | |||
| import com.xueyi.system.api.staff.domain.po.DmStaffPo; | |||
| import com.xueyi.system.api.staff.domain.vo.DmStaffFeature; | |||
| import org.springframework.cloud.openfeign.FeignClient; | |||
| import org.springframework.web.bind.annotation.*; | |||
| import org.springframework.web.bind.annotation.GetMapping; | |||
| import org.springframework.web.bind.annotation.RequestHeader; | |||
| import org.springframework.web.bind.annotation.RequestParam; | |||
| import java.util.List; | |||
| @@ -34,6 +35,10 @@ public interface RemoteStaffService { | |||
| R<List<DmStaffFeature>> listInner(@RequestParam(value = "devId") String devId, @RequestParam(value = "timestamp") String timestamp, | |||
| @RequestHeader(SecurityConstants.ENTERPRISE_ID) Long enterpriseId, @RequestHeader(SecurityConstants.SOURCE_NAME) String sourceName, @RequestHeader(SecurityConstants.FROM_SOURCE) String source); | |||
| @GetMapping("/staff/inner-api/selectOne/{staffId}") | |||
| JSONObject fetchStaff(@RequestParam(value = "staffId") String staffId, @RequestHeader(SecurityConstants.ENTERPRISE_ID) Long enterpriseId, @RequestHeader(SecurityConstants.SOURCE_NAME) String sourceName, @RequestHeader(SecurityConstants.FROM_SOURCE) String source); | |||
| @GetMapping("/staff/inner/tenantId/{enterpriseName}") | |||
| public R<SysEnterpriseDto> tenantIdInner(@RequestParam(value = "enterpriseName") String enterpriseName) ; | |||
| } | |||
| @@ -6,6 +6,7 @@ import com.xueyi.common.core.constant.basic.ServiceConstants; | |||
| import com.xueyi.system.api.organize.feign.factory.RemoteUserFallbackFactory; | |||
| import com.xueyi.system.api.staff.domain.dto.DmVisitCommonDto; | |||
| import org.springframework.cloud.openfeign.FeignClient; | |||
| import org.springframework.web.bind.annotation.DeleteMapping; | |||
| import org.springframework.web.bind.annotation.GetMapping; | |||
| import org.springframework.web.bind.annotation.PostMapping; | |||
| import org.springframework.web.bind.annotation.RequestBody; | |||
| @@ -13,7 +14,7 @@ import org.springframework.web.bind.annotation.RequestHeader; | |||
| import org.springframework.web.bind.annotation.RequestParam; | |||
| /** | |||
| * 用户服务 | |||
| * 访客服务 | |||
| * | |||
| * @author yrx | |||
| */ | |||
| @@ -29,10 +30,24 @@ public interface RemoteVisitorService { | |||
| public JSONObject newVisit(@RequestBody DmVisitCommonDto commonDto, | |||
| @RequestHeader(SecurityConstants.ENTERPRISE_ID) Long enterpriseId, @RequestHeader(SecurityConstants.SOURCE_NAME) String sourceName, @RequestHeader(SecurityConstants.FROM_SOURCE) String source); | |||
| @DeleteMapping(value = "/visit/inner-api/del-visitor") | |||
| public JSONObject delVisit(@RequestBody DmVisitCommonDto commonDto, | |||
| @RequestHeader(SecurityConstants.ENTERPRISE_ID) Long enterpriseId, @RequestHeader(SecurityConstants.SOURCE_NAME) String sourceName, @RequestHeader(SecurityConstants.FROM_SOURCE) String source); | |||
| @GetMapping(value = "/visit/inner-api/sms-config") | |||
| public JSONObject smsConfig(@RequestHeader(SecurityConstants.ENTERPRISE_ID) Long enterpriseId, @RequestHeader(SecurityConstants.SOURCE_NAME) String sourceName, @RequestHeader(SecurityConstants.FROM_SOURCE) String source); | |||
| @GetMapping(value = "/visit/inner-api/list") | |||
| public JSONObject visitList(@RequestParam(value = "empId") Long empId, | |||
| @RequestHeader(SecurityConstants.ENTERPRISE_ID) Long enterpriseId, @RequestHeader(SecurityConstants.SOURCE_NAME) String sourceName, @RequestHeader(SecurityConstants.FROM_SOURCE) String source); | |||
| @GetMapping(value = "/visit/inner-api/list-all") | |||
| public JSONObject visitListAll(@RequestHeader(SecurityConstants.ENTERPRISE_ID) Long enterpriseId, @RequestHeader(SecurityConstants.SOURCE_NAME) String sourceName, @RequestHeader(SecurityConstants.FROM_SOURCE) String source); | |||
| @PostMapping(value = "/visit/inner-api/send-sms") | |||
| public JSONObject sendSms(@RequestParam(value = "type") Integer type, @RequestHeader(SecurityConstants.ENTERPRISE_ID) Long enterpriseId, @RequestHeader(SecurityConstants.SOURCE_NAME) String sourceName, @RequestHeader(SecurityConstants.FROM_SOURCE) String source); | |||
| @GetMapping(value = "/visit/inner-api/sms-users") | |||
| public JSONObject smsUserConfig(@RequestHeader(SecurityConstants.ENTERPRISE_ID) Long enterpriseId, @RequestHeader(SecurityConstants.SOURCE_NAME) String sourceName, @RequestHeader(SecurityConstants.FROM_SOURCE) String source); | |||
| } | |||
| @@ -0,0 +1,18 @@ | |||
| package com.xueyi.system.api.version.domain.vo; | |||
| import com.fasterxml.jackson.annotation.JsonFormat; | |||
| import lombok.Data; | |||
| import lombok.NoArgsConstructor; | |||
| import java.time.LocalDateTime; | |||
| @Data | |||
| @NoArgsConstructor | |||
| public class ApkReleaseVo { | |||
| private String apkVersionName; | |||
| private String CodeVersionName; | |||
| @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") | |||
| private LocalDateTime releaseTime; | |||
| private String path; | |||
| } | |||
| @@ -0,0 +1,7 @@ | |||
| package com.xueyi.common.core.constant.digitalman; | |||
| public class RedisDefinitionConstants { | |||
| /** 通用-当前在线数(List) */ | |||
| public static final String GENERAL_CURRENT_NUMBER_OF_ONLINE = "general:current_number_of_online"; | |||
| } | |||
| @@ -0,0 +1,135 @@ | |||
| package com.xueyi.common.core.utils.core; | |||
| import org.springframework.aop.framework.AopContext; | |||
| import org.springframework.beans.BeansException; | |||
| import org.springframework.beans.factory.NoSuchBeanDefinitionException; | |||
| import org.springframework.beans.factory.config.BeanFactoryPostProcessor; | |||
| import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; | |||
| import org.springframework.context.ApplicationContext; | |||
| import org.springframework.context.ApplicationContextAware; | |||
| import org.springframework.stereotype.Component; | |||
| import java.util.Map; | |||
| @Component | |||
| public class SpringUtils implements BeanFactoryPostProcessor, ApplicationContextAware { | |||
| /** Spring应用上下文环境 */ | |||
| private static ConfigurableListableBeanFactory beanFactory; | |||
| private static ApplicationContext applicationContext; | |||
| public static Map<String, Object> getBeansByAnnotation(Class clsName) throws BeansException{ | |||
| return beanFactory.getBeansWithAnnotation(clsName); | |||
| } | |||
| @Override | |||
| public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { | |||
| SpringUtils.beanFactory = beanFactory; | |||
| } | |||
| @Override | |||
| public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { | |||
| SpringUtils.applicationContext = applicationContext; | |||
| } | |||
| /** | |||
| * 获取对象 | |||
| * | |||
| * @param name | |||
| * @return Object 一个以所给名字注册的bean的实例 | |||
| * @throws org.springframework.beans.BeansException | |||
| * | |||
| */ | |||
| @SuppressWarnings("unchecked") | |||
| public static <T> T getBean(String name) throws BeansException | |||
| { | |||
| return (T) beanFactory.getBean(name); | |||
| } | |||
| /** | |||
| * 获取类型为requiredType的对象 | |||
| * | |||
| * @param clz | |||
| * @return | |||
| * @throws org.springframework.beans.BeansException | |||
| * | |||
| */ | |||
| public static <T> T getBean(Class<T> clz) throws BeansException | |||
| { | |||
| T result = (T) beanFactory.getBean(clz); | |||
| return result; | |||
| } | |||
| /** | |||
| * 如果BeanFactory包含一个与所给名称匹配的bean定义,则返回true | |||
| * | |||
| * @param name | |||
| * @return boolean | |||
| */ | |||
| public static boolean containsBean(String name) | |||
| { | |||
| return beanFactory.containsBean(name); | |||
| } | |||
| /** | |||
| * 判断以给定名字注册的bean定义是一个singleton还是一个prototype。 如果与给定名字相应的bean定义没有被找到,将会抛出一个异常(NoSuchBeanDefinitionException) | |||
| * | |||
| * @param name | |||
| * @return boolean | |||
| * @throws org.springframework.beans.factory.NoSuchBeanDefinitionException | |||
| * | |||
| */ | |||
| public static boolean isSingleton(String name) throws NoSuchBeanDefinitionException | |||
| { | |||
| return beanFactory.isSingleton(name); | |||
| } | |||
| /** | |||
| * @param name | |||
| * @return Class 注册对象的类型 | |||
| * @throws org.springframework.beans.factory.NoSuchBeanDefinitionException | |||
| * | |||
| */ | |||
| public static Class<?> getType(String name) throws NoSuchBeanDefinitionException | |||
| { | |||
| return beanFactory.getType(name); | |||
| } | |||
| /** | |||
| * 如果给定的bean名字在bean定义中有别名,则返回这些别名 | |||
| * | |||
| * @param name | |||
| * @return | |||
| * @throws org.springframework.beans.factory.NoSuchBeanDefinitionException | |||
| * | |||
| */ | |||
| public static String[] getAliases(String name) throws NoSuchBeanDefinitionException | |||
| { | |||
| return beanFactory.getAliases(name); | |||
| } | |||
| /** | |||
| * 获取aop代理对象 | |||
| * | |||
| * @param invoker | |||
| * @return | |||
| */ | |||
| @SuppressWarnings("unchecked") | |||
| public static <T> T getAopProxy(T invoker) | |||
| { | |||
| return (T) AopContext.currentProxy(); | |||
| } | |||
| /** | |||
| * 获取当前的环境配置,无配置返回null | |||
| * | |||
| * @return 当前的环境配置 | |||
| */ | |||
| public static String[] getActiveProfiles() | |||
| { | |||
| return applicationContext.getEnvironment().getActiveProfiles(); | |||
| } | |||
| } | |||
| @@ -1 +1,2 @@ | |||
| com.xueyi.common.core.utils.core.SpringUtil | |||
| com.xueyi.common.core.utils.core.SpringUtil | |||
| com.xueyi.common.core.utils.core.SpringUtils | |||
| @@ -23,12 +23,25 @@ | |||
| <artifactId>org.eclipse.paho.client.mqttv3</artifactId> | |||
| <version>1.2.5</version> | |||
| </dependency> | |||
| <dependency> | |||
| <groupId>org.springframework.integration</groupId> | |||
| <artifactId>spring-integration-mqtt</artifactId> | |||
| <version>6.1.0</version> | |||
| </dependency> | |||
| <!-- XueYi Common Core--> | |||
| <dependency> | |||
| <groupId>com.xueyi</groupId> | |||
| <artifactId>xueyi-common-core</artifactId> | |||
| </dependency> | |||
| <!-- SpringBoot Mqtt --> | |||
| <dependency> | |||
| <groupId>org.springframework.integration</groupId> | |||
| <artifactId>spring-integration-mqtt</artifactId> | |||
| <version>5.5.14</version> | |||
| </dependency> | |||
| </dependencies> | |||
| </project> | |||
| @@ -0,0 +1,18 @@ | |||
| package com.xueyi.common.mqtt.annotation; | |||
| import org.springframework.core.annotation.AliasFor; | |||
| import org.springframework.stereotype.Component; | |||
| import java.lang.annotation.ElementType; | |||
| import java.lang.annotation.Retention; | |||
| import java.lang.annotation.RetentionPolicy; | |||
| import java.lang.annotation.Target; | |||
| @Target({ElementType.TYPE}) | |||
| @Retention(RetentionPolicy.RUNTIME) | |||
| @Component | |||
| public @interface MqttService { | |||
| @AliasFor(annotation = Component.class) | |||
| String value() default ""; | |||
| } | |||
| @@ -0,0 +1,17 @@ | |||
| package com.xueyi.common.mqtt.annotation; | |||
| import org.springframework.stereotype.Component; | |||
| import java.lang.annotation.ElementType; | |||
| import java.lang.annotation.Retention; | |||
| import java.lang.annotation.RetentionPolicy; | |||
| import java.lang.annotation.Target; | |||
| @Target(ElementType.METHOD) | |||
| @Retention(RetentionPolicy.RUNTIME) | |||
| public @interface MqttTopic { | |||
| /** | |||
| * 主题名称 | |||
| */ | |||
| String value() default ""; | |||
| } | |||
| @@ -4,17 +4,15 @@ import lombok.Data; | |||
| import org.eclipse.paho.client.mqttv3.MqttClient; | |||
| import org.eclipse.paho.client.mqttv3.MqttConnectOptions; | |||
| import org.springframework.beans.factory.annotation.Value; | |||
| import org.springframework.cache.annotation.EnableCaching; | |||
| import org.springframework.context.annotation.Bean; | |||
| import org.springframework.context.annotation.Configuration; | |||
| /** | |||
| * mqtt配置 | |||
| * | |||
| * @author xueyi | |||
| */ | |||
| @Configuration | |||
| @EnableCaching | |||
| //@Configuration | |||
| //@EnableCaching | |||
| @Data | |||
| public class MqttConfig { | |||
| @Value("${emqx.brokerUrl}") | |||
| @@ -33,13 +31,20 @@ public class MqttConfig { | |||
| @Value("${emqx.topics}") | |||
| private String topics; | |||
| @Value("${emqx.prefix}") | |||
| private String prefix; | |||
| @Value("${emqx.fetchLogTopic}") | |||
| private String fetchLogTopic; | |||
| @Bean | |||
| public MqttClient mqttClient() throws Exception { | |||
| MqttConnectOptions options = new MqttConnectOptions(); | |||
| // options.setCleanSession(true); | |||
| options.setCleanSession(true); | |||
| options.setConnectionTimeout(10); // 设置连接超时时间为10秒 | |||
| options.setMaxReconnectDelay(5000); // 设置最大重连延迟为5秒 | |||
| options.setAutomaticReconnect(true); | |||
| options.setUserName(username); | |||
| options.setPassword(password.toCharArray()); | |||
| MqttClient client = new MqttClient(brokerUrl, clientId); | |||
| @@ -0,0 +1,81 @@ | |||
| package com.xueyi.common.mqtt.configure; | |||
| import com.xueyi.common.mqtt.service.IMqttMessageHandler; | |||
| import org.eclipse.paho.client.mqttv3.MqttConnectOptions; | |||
| import org.springframework.beans.factory.annotation.Autowired; | |||
| import org.springframework.context.annotation.Bean; | |||
| import org.springframework.context.annotation.Configuration; | |||
| import org.springframework.integration.annotation.IntegrationComponentScan; | |||
| import org.springframework.integration.annotation.ServiceActivator; | |||
| import org.springframework.integration.channel.DirectChannel; | |||
| import org.springframework.integration.channel.ExecutorChannel; | |||
| import org.springframework.integration.config.EnableIntegration; | |||
| import org.springframework.integration.dsl.IntegrationFlow; | |||
| import org.springframework.integration.dsl.IntegrationFlows; | |||
| import org.springframework.integration.mqtt.core.DefaultMqttPahoClientFactory; | |||
| import org.springframework.integration.mqtt.core.MqttPahoClientFactory; | |||
| import org.springframework.integration.mqtt.inbound.MqttPahoMessageDrivenChannelAdapter; | |||
| import org.springframework.integration.mqtt.outbound.MqttPahoMessageHandler; | |||
| import org.springframework.integration.mqtt.support.DefaultPahoMessageConverter; | |||
| import org.springframework.messaging.MessageChannel; | |||
| import org.springframework.messaging.MessageHandler; | |||
| import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; | |||
| import java.util.concurrent.ThreadPoolExecutor; | |||
| /** | |||
| * mqtt config | |||
| */ | |||
| @Configuration | |||
| @IntegrationComponentScan("com.xueyi.common.mqtt.connection") | |||
| public class MqttConfigV2 { | |||
| @Autowired | |||
| private MqttProperties mqttProperties; | |||
| //Mqtt 客户端工厂 | |||
| @Bean | |||
| public MqttPahoClientFactory mqttPahoClientFactory(){ | |||
| DefaultMqttPahoClientFactory factory = new DefaultMqttPahoClientFactory(); | |||
| MqttConnectOptions options = new MqttConnectOptions(); | |||
| options.setServerURIs(mqttProperties.getHostUrl().split(",")); | |||
| options.setUserName(mqttProperties.getUsername()); | |||
| options.setPassword(mqttProperties.getPassword().toCharArray()); | |||
| factory.setConnectionOptions(options); | |||
| return factory; | |||
| } | |||
| // 消息生产者 | |||
| // @Bean | |||
| // public IntegrationFlow mqttInbound(MqttPahoMessageDrivenChannelAdapter adapter){ | |||
| // adapter.setCompletionTimeout(5000); | |||
| // adapter.setConverter(new DefaultPahoMessageConverter()); | |||
| // //入站投递的通道 | |||
| // adapter.setOutputChannel(mqttInboundChannel()); | |||
| // adapter.setQos(1); | |||
| // return IntegrationFlows.from(adapter) | |||
| //// .channel(new ExecutorChannel(mqttThreadPoolTaskExecutor())) | |||
| //// .handle(mqttMessageHandler) | |||
| // .get(); | |||
| // } | |||
| //出站消息管道, | |||
| @Bean | |||
| public MessageChannel mqttOutboundChannel(){ | |||
| return new DirectChannel(); | |||
| } | |||
| // 出站处理器 (向 mqtt 发送消息 生产者) | |||
| @Bean | |||
| public IntegrationFlow mqttOutboundFlow(MqttPahoClientFactory factory) { | |||
| MqttPahoMessageHandler handler = new MqttPahoMessageHandler(mqttProperties.getOutClientId(),factory); | |||
| handler.setAsync(true); | |||
| handler.setConverter(new DefaultPahoMessageConverter()); | |||
| handler.setDefaultTopic(mqttProperties.getDefaultTopic().split(",")[0]); | |||
| return IntegrationFlows.from( "mqttOutboundChannel").handle(handler).get(); | |||
| } | |||
| } | |||
| @@ -0,0 +1,68 @@ | |||
| package com.xueyi.common.mqtt.configure; | |||
| import lombok.Data; | |||
| import org.springframework.beans.factory.annotation.Value; | |||
| import org.springframework.stereotype.Component; | |||
| @Data | |||
| @Component | |||
| public class MqttProperties { | |||
| /** | |||
| * 用户名 | |||
| */ | |||
| @Value("${mqtt.username}") | |||
| private String username; | |||
| /** | |||
| * 密码 | |||
| */ | |||
| @Value("${mqtt.password}") | |||
| private String password; | |||
| /** | |||
| * 连接地址 | |||
| */ | |||
| @Value("${mqtt.host-url}") | |||
| private String hostUrl; | |||
| /** | |||
| * 进-客户Id | |||
| */ | |||
| @Value("${mqtt.in-client-id}") | |||
| private String inClientId; | |||
| /** | |||
| * 出-客户Id | |||
| */ | |||
| @Value("${mqtt.out-client-id}") | |||
| private String outClientId; | |||
| /** | |||
| * 客户Id | |||
| */ | |||
| @Value("${mqtt.client-id}") | |||
| private String clientId; | |||
| /** | |||
| * 默认连接话题 | |||
| */ | |||
| @Value("${mqtt.default-topic}") | |||
| private String defaultTopic; | |||
| /** | |||
| * 超时时间 | |||
| */ | |||
| @Value("${mqtt.timeout}") | |||
| private int timeout; | |||
| /** | |||
| * 保持连接数 | |||
| */ | |||
| @Value("${mqtt.keepalive}") | |||
| private int keepalive; | |||
| /**是否清除session*/ | |||
| @Value("${mqtt.clearSession}") | |||
| private boolean clearSession; | |||
| } | |||
| @@ -0,0 +1,22 @@ | |||
| package com.xueyi.common.mqtt.connection; | |||
| import org.springframework.integration.annotation.MessagingGateway; | |||
| import org.springframework.integration.mqtt.support.MqttHeaders; | |||
| import org.springframework.messaging.handler.annotation.Header; | |||
| import org.springframework.stereotype.Component; | |||
| /** | |||
| * MqttGateway | |||
| * | |||
| * @author yinruoxi | |||
| * @date 2022/8/23 | |||
| */ | |||
| @Component | |||
| @MessagingGateway(defaultRequestChannel = "mqttOutboundChannel") | |||
| public interface MqttTemplate { | |||
| void sendToMqtt(@Header(MqttHeaders.TOPIC) String topic, String data); | |||
| void sendToMqtt(@Header(MqttHeaders.TOPIC) String topic, @Header(MqttHeaders.QOS) Integer Qos, String data); | |||
| } | |||
| @@ -0,0 +1,11 @@ | |||
| package com.xueyi.common.mqtt.service; | |||
| import org.springframework.messaging.MessageHandler; | |||
| /** | |||
| * @author yk | |||
| * @description | |||
| * @date 2023-05-10 19:05 | |||
| */ | |||
| public interface IMqttMessageHandler extends MessageHandler { | |||
| } | |||
| @@ -6,5 +6,5 @@ package com.xueyi.common.mqtt.service; | |||
| * @date 2023-05-10 19:05 | |||
| */ | |||
| public interface MqttMessageHandler { | |||
| void handleMessage(String topic, String message); | |||
| void handleMessage(String topic, String message) throws Exception; | |||
| } | |||
| @@ -10,7 +10,6 @@ import org.eclipse.paho.client.mqttv3.MqttMessage; | |||
| import org.springframework.beans.factory.annotation.Autowired; | |||
| import org.springframework.stereotype.Component; | |||
| import javax.annotation.PostConstruct; | |||
| import java.nio.charset.StandardCharsets; | |||
| import java.util.ArrayList; | |||
| import java.util.Arrays; | |||
| @@ -46,35 +45,60 @@ public class MqttService implements MqttCallback{ | |||
| * @param topic 消息主题 | |||
| * @param message 消息内容 | |||
| */ | |||
| public void sendMessage(String topic, Object message) throws MqttException { | |||
| MqttMessage msg = new MqttMessage(); | |||
| msg.setPayload(message.toString().getBytes()); | |||
| mqttClient.publish(topic, msg); | |||
| public void sendMessage(String topic, Object message) { | |||
| System.out.println("发送消息到 topic: " + topic); | |||
| System.out.println("消息内容: " + message); | |||
| MqttMessage msg = new MqttMessage(); | |||
| msg.setPayload(message.toString().getBytes()); | |||
| try { | |||
| mqttClient.publish(topic, msg); | |||
| } catch (MqttException e) { | |||
| e.printStackTrace(); | |||
| System.err.println(e.getMessage()); | |||
| } | |||
| } | |||
| @PostConstruct | |||
| public void subscribe() throws MqttException { | |||
| // @PostConstruct | |||
| public void subscribe() { | |||
| mqttClient.setCallback(this); | |||
| for (String topic : Arrays.stream(mqttConfig.getTopics().split(",")).toList()) { | |||
| if (StringUtils.isNotEmpty(topic)) { | |||
| mqttClient.subscribe(topic, 0); | |||
| try { | |||
| mqttClient.subscribe(topic, 0); | |||
| } catch (MqttException e) { | |||
| e.printStackTrace(); | |||
| System.err.println(e.getMessage()); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| @Override | |||
| public void connectionLost(Throwable throwable) { | |||
| throwable.printStackTrace(); | |||
| System.out.println("Connection lost: " + throwable.getMessage()); | |||
| try { | |||
| mqttClient.reconnect(); | |||
| subscribe(); | |||
| System.out.println("Reconnected to MQTT broker"); | |||
| } catch (MqttException e) { | |||
| System.out.println("Reconnect failed: " + e.getMessage()); | |||
| } | |||
| } | |||
| @Override | |||
| public void messageArrived(String s, MqttMessage mqttMessage) throws Exception { | |||
| for (MqttMessageHandler observer : observers) { | |||
| observer.handleMessage(s, new String(mqttMessage.getPayload(), StandardCharsets.UTF_8)); | |||
| public void messageArrived(String s, MqttMessage mqttMessage) { | |||
| try{ | |||
| for (MqttMessageHandler observer : observers) { | |||
| observer.handleMessage(s, new String(mqttMessage.getPayload(), StandardCharsets.UTF_8)); | |||
| } | |||
| } catch (Exception e) { | |||
| e.printStackTrace(); | |||
| System.err.println(e.getMessage()); | |||
| } | |||
| } | |||
| @Override | |||
| @@ -1,2 +1,5 @@ | |||
| com.xueyi.common.mqtt.configure.MqttConfig | |||
| com.xueyi.common.mqtt.service.MqttService | |||
| com.xueyi.common.mqtt.configure.MqttProperties | |||
| com.xueyi.common.mqtt.configure.MqttConfigV2 | |||
| #com.xueyi.common.mqtt.connection.MqttGateway | |||
| @@ -328,6 +328,7 @@ public class BaseTokenService<User, LoginUser extends BaseLoginUser<User>> { | |||
| * 刷新令牌有效期 | |||
| */ | |||
| public void refreshToken(HttpServletRequest request) { | |||
| String token = SecurityUtils.getToken(request); | |||
| refreshToken(SecurityUtils.getToken(request)); | |||
| } | |||
| @@ -337,8 +338,10 @@ public class BaseTokenService<User, LoginUser extends BaseLoginUser<User>> { | |||
| * @param token token | |||
| */ | |||
| public void refreshToken(String token) { | |||
| LoginUser loginUser = getLoginUser(token); | |||
| long loginTime = System.currentTimeMillis(); | |||
| String userKey = getTokenKey(token); | |||
| loginUser.setLoginTime(loginTime); | |||
| String userKey = getTokenKey(loginUser.getToken()); | |||
| redisService.setCacheMapValue(userKey, SecurityConstants.BaseSecurity.EXPIRE_TIME.getCode(), getExpireTime(loginTime)); | |||
| redisService.expire(userKey, getTacitExpireTime(), TimeUnit.MINUTES); | |||
| } | |||
| @@ -2,7 +2,6 @@ package com.xueyi.common.sms.configure; | |||
| import lombok.Data; | |||
| import org.springframework.boot.context.properties.ConfigurationProperties; | |||
| import org.springframework.cloud.context.config.annotation.RefreshScope; | |||
| import org.springframework.stereotype.Component; | |||
| /** | |||
| @@ -27,6 +26,7 @@ public class SmsProperties { | |||
| private String meetingQuitTemplate; | |||
| private String meetingRemindTemplate; | |||
| private String defaultRemindTemplate; | |||
| private String visitorTemplate; | |||
| private String robotName; | |||
| private String receptionPhones; | |||
| private String receptionPhones; | |||
| } | |||
| @@ -3,6 +3,7 @@ package com.xueyi.common.web.utils; | |||
| import com.google.common.collect.Lists; | |||
| import java.math.BigDecimal; | |||
| import java.text.DecimalFormat; | |||
| import java.text.ParseException; | |||
| import java.text.ParsePosition; | |||
| import java.text.SimpleDateFormat; | |||
| @@ -236,15 +237,19 @@ public class DateUtils extends org.apache.commons.lang.time.DateUtils { | |||
| } | |||
| public static Date parseLongToDate(String dateLong) throws ParseException { | |||
| return parseLongToDate(Double.parseDouble(dateLong)); | |||
| BigDecimal number = new BigDecimal(dateLong); | |||
| return parseLongToDate(number.doubleValue()); | |||
| } | |||
| public static Date parseLongToDate(Double dateLong) throws ParseException { | |||
| Calendar calendar = Calendar.getInstance(); | |||
| String str = Double.toString(dateLong); | |||
| DecimalFormat df = new DecimalFormat("#"); // 创建DecimalFormat对象 | |||
| String str = df.format(dateLong); | |||
| if (str.indexOf(".")>-1) { | |||
| str = str.replace(".",""); | |||
| } | |||
| calendar.setTimeInMillis(Long.getLong(str.substring(0,13))); | |||
| str = str.substring(0,13); | |||
| BigDecimal number = new BigDecimal(str); | |||
| calendar.setTimeInMillis(number.longValue()); | |||
| return calendar.getTime(); | |||
| } | |||
| @@ -37,7 +37,7 @@ public class AuthFilter implements GlobalFilter, Ordered { | |||
| @Autowired | |||
| private RedisService redisService; | |||
| private static final String[] whitePrefix = {"/message/api", "/pass/api", "/meeting/api", "/visit/api"}; | |||
| private static final String[] whitePrefix = {"/message/api", "/pass/api", "/meeting/api", "/visit/api", "/file/api","/staff/api","/apkversion/api","/man/api"}; | |||
| @Override | |||
| public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { | |||
| @@ -1,20 +1,25 @@ | |||
| package com.xueyi.file.controller; | |||
| import com.alibaba.fastjson.JSONObject; | |||
| import com.xueyi.common.core.constant.basic.SecurityConstants; | |||
| import com.xueyi.common.core.utils.core.IdUtil; | |||
| import com.xueyi.common.core.utils.file.FileUtil; | |||
| import com.xueyi.common.core.web.result.AjaxResult; | |||
| import com.xueyi.common.core.web.result.R; | |||
| import com.xueyi.file.api.domain.DigitalmanLogFile; | |||
| import com.xueyi.file.api.domain.SysFile; | |||
| import com.xueyi.file.api.feign.RemoteFileManageService; | |||
| import com.xueyi.file.config.MinioConfig; | |||
| import com.xueyi.file.service.ISysFileService; | |||
| import lombok.extern.slf4j.Slf4j; | |||
| import org.springframework.beans.factory.annotation.Autowired; | |||
| import org.springframework.web.bind.annotation.DeleteMapping; | |||
| import org.springframework.web.bind.annotation.PathVariable; | |||
| import org.springframework.web.bind.annotation.PostMapping; | |||
| import org.springframework.web.bind.annotation.RestController; | |||
| import org.springframework.web.bind.annotation.*; | |||
| import org.springframework.web.multipart.MultipartFile; | |||
| import java.time.LocalDate; | |||
| import java.time.format.DateTimeFormatter; | |||
| /** | |||
| * 文件请求处理 | |||
| * | |||
| @@ -30,6 +35,9 @@ public class SysFileController { | |||
| @Autowired | |||
| private RemoteFileManageService remoteFileManageService; | |||
| @Autowired | |||
| private MinioConfig minioConfig; | |||
| /** | |||
| * 文件上传 | 内部调用 | |||
| */ | |||
| @@ -65,6 +73,22 @@ public class SysFileController { | |||
| return R.fail(e.getMessage()); | |||
| } | |||
| } | |||
| /** | |||
| * 文件上传请求 | |||
| */ | |||
| @PostMapping("/api/getLogUploadPath") | |||
| public AjaxResult getLogUploadPath(@RequestBody DigitalmanLogFile file) { | |||
| // 根据当前时间,获取路径 | |||
| LocalDate currentDate = LocalDate.now(); | |||
| DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy/MM/dd"); | |||
| String path = currentDate.format(formatter); | |||
| JSONObject jsonObject = new JSONObject(); | |||
| jsonObject.put("hosts",minioConfig.getUrl()); | |||
| jsonObject.put("bucket",minioConfig.getBucketName()); | |||
| jsonObject.put("filepath","/" + file.getDevId() + "/" + path); | |||
| jsonObject.put("uuid", IdUtil.simpleUUID()); | |||
| return AjaxResult.success(jsonObject); | |||
| } | |||
| /** | |||
| * 文件上传请求 | |||
| @@ -14,7 +14,6 @@ import java.io.File; | |||
| * @author xueyi | |||
| */ | |||
| @Primary | |||
| @Service | |||
| public class LocalSysFileServiceImpl implements ISysFileService { | |||
| @@ -14,6 +14,7 @@ import org.springframework.web.multipart.MultipartFile; | |||
| * | |||
| * @author xueyi | |||
| */ | |||
| @Primary | |||
| @Service | |||
| public class MinioSysFileServiceImpl implements ISysFileService { | |||
| @@ -45,4 +45,12 @@ public class DgmanTask { | |||
| }); | |||
| System.out.println("监控心跳执行完成"); | |||
| } | |||
| /** | |||
| * 触发条件:0 0 10 * * * | |||
| * 每日十点触发,收集当前在线数 | |||
| */ | |||
| public void dgmanDeviceOnlineState() { | |||
| remoteManDeviceService.syncNumbersOfOnline(); | |||
| } | |||
| } | |||
| @@ -41,6 +41,14 @@ | |||
| <artifactId>spring-boot-starter-actuator</artifactId> | |||
| </dependency> | |||
| <!-- SpringBoot Mqtt --> | |||
| <dependency> | |||
| <groupId>org.springframework.integration</groupId> | |||
| <artifactId>spring-integration-mqtt</artifactId> | |||
| <version>5.5.14</version> | |||
| </dependency> | |||
| <!-- XueYi Common Log --> | |||
| <dependency> | |||
| <groupId>com.xueyi</groupId> | |||
| @@ -53,18 +61,35 @@ | |||
| <artifactId>xueyi-common-web</artifactId> | |||
| </dependency> | |||
| <dependency> | |||
| <groupId>com.xueyi</groupId> | |||
| <artifactId>xueyi-common-mqtt</artifactId> | |||
| <version>2.5.0</version> | |||
| </dependency> | |||
| <!-- XueYi Common Swagger --> | |||
| <dependency> | |||
| <groupId>com.xueyi</groupId> | |||
| <artifactId>xueyi-common-swagger</artifactId> | |||
| </dependency> | |||
| <!-- XueYi Common mqtt --> | |||
| <dependency> | |||
| <groupId>com.xueyi</groupId> | |||
| <artifactId>xueyi-common-mqtt</artifactId> | |||
| </dependency> | |||
| <!-- XueYi Api File --> | |||
| <dependency> | |||
| <groupId>com.xueyi</groupId> | |||
| <artifactId>xueyi-api-file</artifactId> | |||
| </dependency> | |||
| <dependency> | |||
| <groupId>com.xueyi</groupId> | |||
| <artifactId>xueyi-api-system</artifactId> | |||
| </dependency> | |||
| </dependencies> | |||
| <build> | |||
| @@ -0,0 +1,75 @@ | |||
| package com.xueyi.message.comfiguration; | |||
| import com.xueyi.common.mqtt.configure.MqttProperties; | |||
| import com.xueyi.common.mqtt.service.IMqttMessageHandler; | |||
| import org.springframework.beans.factory.annotation.Autowired; | |||
| import org.springframework.context.annotation.Bean; | |||
| import org.springframework.context.annotation.Configuration; | |||
| import org.springframework.integration.channel.DirectChannel; | |||
| import org.springframework.integration.channel.ExecutorChannel; | |||
| import org.springframework.integration.dsl.IntegrationFlow; | |||
| import org.springframework.integration.dsl.IntegrationFlows; | |||
| import org.springframework.integration.mqtt.core.MqttPahoClientFactory; | |||
| import org.springframework.integration.mqtt.inbound.MqttPahoMessageDrivenChannelAdapter; | |||
| import org.springframework.integration.mqtt.support.DefaultPahoMessageConverter; | |||
| import org.springframework.messaging.MessageChannel; | |||
| import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; | |||
| import org.springframework.stereotype.Component; | |||
| import java.util.concurrent.ThreadPoolExecutor; | |||
| @Configuration | |||
| public class MqttReceiveConfig { | |||
| @Autowired | |||
| private MqttProperties mqttProperties; | |||
| @Autowired | |||
| private IMqttMessageHandler mqttMessageHandler; | |||
| // 入站消息管道 | |||
| @Bean | |||
| public MessageChannel mqttInboundChannel(){ | |||
| return new DirectChannel(); | |||
| } | |||
| // Mqtt 管道适配器 | |||
| @Bean | |||
| public MqttPahoMessageDrivenChannelAdapter adapter(MqttPahoClientFactory factory){ | |||
| return new MqttPahoMessageDrivenChannelAdapter(mqttProperties.getInClientId(),factory,mqttProperties.getDefaultTopic().split(",")); | |||
| } | |||
| @Bean | |||
| public IntegrationFlow mqttMessageInbound(MqttPahoMessageDrivenChannelAdapter adapter){ | |||
| adapter.setCompletionTimeout(5000); | |||
| adapter.setConverter(new DefaultPahoMessageConverter()); | |||
| //入站投递的通道 | |||
| adapter.setOutputChannel(mqttInboundChannel()); | |||
| adapter.setQos(1); | |||
| return IntegrationFlows.from(adapter) | |||
| .channel(new ExecutorChannel(mqttThreadPoolTaskExecutor())) | |||
| .handle(mqttMessageHandler) | |||
| .get(); | |||
| } | |||
| @Bean | |||
| public ThreadPoolTaskExecutor mqttThreadPoolTaskExecutor() | |||
| { | |||
| ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); | |||
| // 最大可创建的线程数 | |||
| int maxPoolSize = 200; | |||
| executor.setMaxPoolSize(maxPoolSize); | |||
| // 核心线程池大小 | |||
| int corePoolSize = 50; | |||
| executor.setCorePoolSize(corePoolSize); | |||
| // 队列最大长度 | |||
| int queueCapacity = 1000; | |||
| executor.setQueueCapacity(queueCapacity); | |||
| // 线程池维护线程所允许的空闲时间 | |||
| int keepAliveSeconds = 300; | |||
| executor.setKeepAliveSeconds(keepAliveSeconds); | |||
| // 线程池对拒绝任务(无线程可用)的处理策略 | |||
| executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); | |||
| return executor; | |||
| } | |||
| } | |||
| @@ -0,0 +1,133 @@ | |||
| package com.xueyi.message.handler; | |||
| import com.xueyi.common.core.utils.core.SpringUtils; | |||
| import com.xueyi.common.mqtt.annotation.MqttService; | |||
| import com.xueyi.common.mqtt.annotation.MqttTopic; | |||
| import com.xueyi.common.mqtt.service.IMqttMessageHandler; | |||
| import org.slf4j.Logger; | |||
| import org.slf4j.LoggerFactory; | |||
| import org.springframework.messaging.Message; | |||
| import org.springframework.messaging.MessageHandler; | |||
| import org.springframework.messaging.MessagingException; | |||
| import org.springframework.stereotype.Component; | |||
| import java.lang.reflect.InvocationTargetException; | |||
| import java.lang.reflect.Method; | |||
| import java.util.Map; | |||
| /** | |||
| * mqtt消息处理类 | |||
| * 这里的代码是在spring-integration-mqtt的基础上修改的 | |||
| * 他的代码是在接收到消息后 直接调用了方法 | |||
| * 我这里是把消息放到线程池里面去处理 | |||
| * 这样就不会阻塞mqtt的消息接收 | |||
| */ | |||
| @Component | |||
| public class MqttMessageHandle implements IMqttMessageHandler { | |||
| private static final Logger log = LoggerFactory.getLogger(MqttMessageHandle.class); | |||
| // 包含 @MqttService注解 的类(Component) | |||
| public static Map<String, Object> mqttServices; | |||
| /** | |||
| * 所有mqtt到达的消息都会在这里处理 | |||
| * 要注意这个方法是在线程池里面运行的 | |||
| * @param message message | |||
| */ | |||
| @Override | |||
| public void handleMessage(Message<?> message) throws MessagingException { | |||
| getMqttTopicService(message); | |||
| } | |||
| public Map<String, Object> getMqttServices(){ | |||
| if(mqttServices==null){ | |||
| mqttServices = SpringUtils.getBeansByAnnotation(MqttService.class); | |||
| } | |||
| return mqttServices; | |||
| } | |||
| public void getMqttTopicService(Message<?> message){ | |||
| // 在这里 我们根据不同的 主题 分发不同的消息 | |||
| String receivedTopic = message.getHeaders().get("mqtt_receivedTopic",String.class); | |||
| if(receivedTopic==null || "".equals(receivedTopic)){ | |||
| return; | |||
| } | |||
| for(Map.Entry<String, Object> entry : getMqttServices().entrySet()){ | |||
| // 把所有带有 @MqttService 的类遍历 | |||
| Class<?> clazz = entry.getValue().getClass(); | |||
| // 获取他所有方法 | |||
| Method[] methods = clazz.getDeclaredMethods(); | |||
| for ( Method method: methods ){ | |||
| if (method.isAnnotationPresent(MqttTopic.class)){ | |||
| // 如果这个方法有 这个注解 | |||
| MqttTopic handleTopic = method.getAnnotation(MqttTopic.class); | |||
| if(isMatch(receivedTopic,handleTopic.value())){ | |||
| // 并且 这个 topic 匹配成功 | |||
| try { | |||
| method.invoke(SpringUtils.getBean(clazz),message); | |||
| return; | |||
| } catch (IllegalAccessException e) { | |||
| e.printStackTrace(); | |||
| log.error("代理发生问题"); | |||
| } catch (InvocationTargetException e) { | |||
| log.error("执行 {} 方法出现错误",handleTopic.value(),e); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| } | |||
| } | |||
| /** | |||
| * mqtt 订阅的主题与我实际的主题是否匹配 | |||
| * @param topic 是实际的主题 | |||
| * @param pattern 是我订阅的主题 可以是通配符模式 | |||
| * @return 是否匹配 | |||
| */ | |||
| public static boolean isMatch(String topic, String pattern){ | |||
| if((topic==null) || (pattern==null) ){ | |||
| return false; | |||
| } | |||
| if(topic.equals(pattern)){ | |||
| // 完全相等是肯定匹配的 | |||
| return true; | |||
| } | |||
| if("#".equals(pattern)){ | |||
| // # 号代表所有主题 肯定匹配的 | |||
| return true; | |||
| } | |||
| String[] splitTopic = topic.split("/"); | |||
| String[] splitPattern = pattern.split("/"); | |||
| boolean match = true; | |||
| // 如果包含 # 则只需要判断 # 前面的 | |||
| for (int i = 0; i < splitPattern.length; i++) { | |||
| if(!"#".equals(splitPattern[i])){ | |||
| // 不是# 号 正常判断 | |||
| if(i>=splitTopic.length){ | |||
| // 此时长度不相等 不匹配 | |||
| match = false; | |||
| break; | |||
| } | |||
| if(!splitTopic[i].equals(splitPattern[i]) && !"+".equals(splitPattern[i])){ | |||
| // 不相等 且不等于 + | |||
| match = false; | |||
| break; | |||
| } | |||
| } | |||
| else { | |||
| // 是# 号 肯定匹配的 | |||
| break; | |||
| } | |||
| } | |||
| return match; | |||
| } | |||
| } | |||
| @@ -0,0 +1,74 @@ | |||
| package com.xueyi.message.handler; | |||
| import com.alibaba.fastjson2.JSONObject; | |||
| import com.xueyi.common.core.constant.basic.SecurityConstants; | |||
| import com.xueyi.common.mqtt.annotation.MqttService; | |||
| import com.xueyi.common.mqtt.annotation.MqttTopic; | |||
| import com.xueyi.system.api.device.domain.vo.DeviceTenantSourceMergeVo; | |||
| import com.xueyi.system.api.device.feign.RemoteDeviceTenantMergeService; | |||
| import com.xueyi.system.api.digitalmans.feign.RemoteDigitalmanMqttService; | |||
| import org.slf4j.Logger; | |||
| import org.slf4j.LoggerFactory; | |||
| import org.springframework.beans.factory.annotation.Autowired; | |||
| import org.springframework.messaging.Message; | |||
| @MqttService | |||
| public class MqttTopicHandle { | |||
| @Autowired | |||
| private RemoteDeviceTenantMergeService remoteDeviceTenantMergeService; | |||
| @Autowired | |||
| private RemoteDigitalmanMqttService remoteDigitalmanMqttService; | |||
| private static final Logger log = LoggerFactory.getLogger(MqttTopicHandle.class); | |||
| /** | |||
| * 以下内容是使用范例 | |||
| // 这里的 # 号是通配符 | |||
| @MqttTopic("test/#") | |||
| public void test(Message<?> message){ | |||
| log.info("test="+message.getPayload()); | |||
| } | |||
| // 这里的 + 号是通配符 | |||
| @MqttTopic("topic/+/+/up") | |||
| public void up(Message<?> message){ | |||
| log.info("up="+message.getPayload()); | |||
| } | |||
| // 注意 你必须先订阅 | |||
| @MqttTopic("topic/1/2/down") | |||
| public void down(Message<?> message){ | |||
| log.info("down="+message.getPayload()); | |||
| } | |||
| */ | |||
| @MqttTopic("digital_man/+/reply/setup") | |||
| public void setup(Message message){ | |||
| log.info("down="+message.getPayload()); | |||
| } | |||
| @MqttTopic("/digital_man/heart_beat") | |||
| //@TenantIgnore(tenantLine = true) | |||
| public void heartbeat(Message message){ | |||
| System.err.println("rev heartbeat mqtt msg:"+message.getPayload().toString()); | |||
| String messageStr = message.getPayload().toString(); | |||
| JSONObject heartBeatObj = JSONObject.parseObject(messageStr); | |||
| String devId = heartBeatObj.getString("devId"); | |||
| DeviceTenantSourceMergeVo vo = remoteDeviceTenantMergeService.selectDeviceTenantSourceMerge(devId); | |||
| remoteDigitalmanMqttService.heartbeat(messageStr, vo.getTenantId(), vo.getSourceSlave(), SecurityConstants.INNER); | |||
| } | |||
| @MqttTopic("/digital_man/log_upload_notification") | |||
| public void logUpload(Message message){ | |||
| System.err.println("rev logUpload mqtt msg:"+message.getPayload().toString()); | |||
| String messageStr = message.getPayload().toString(); | |||
| JSONObject heartBeatObj = JSONObject.parseObject(messageStr); | |||
| String devId = heartBeatObj.getString("devId"); | |||
| DeviceTenantSourceMergeVo vo = remoteDeviceTenantMergeService.selectDeviceTenantSourceMerge(devId); | |||
| remoteDigitalmanMqttService.logUpload(messageStr, vo.getTenantId(), vo.getSourceSlave(), SecurityConstants.INNER); | |||
| } | |||
| } | |||
| @@ -177,9 +177,9 @@ public class ApiController { | |||
| vo.setActivateTime(new Date()); | |||
| // 设备是否已绑定其他账号 | |||
| R<DmManDeviceDto> manDeviceDtoR = manDeviceService.manDeviceInfoInner(vo.getSncode()); | |||
| if (manDeviceDtoR.getData() != null) { | |||
| return AjaxResult.warn("设备号已绑定其他账号"); | |||
| } | |||
| // if (manDeviceDtoR.getData() != null) { | |||
| // return AjaxResult.warn("设备号已绑定其他账号"); | |||
| // } | |||
| R<Integer> regR = manDeviceService.manDeviceInfoInnerUpdate(vo); | |||
| if (regR.getData() == 0) { | |||
| return AjaxResult.warn("更新设备信息失败,请查询log"); | |||
| @@ -1,8 +1,12 @@ | |||
| package com.xueyi.system.digitalmans.controller; | |||
| import com.alibaba.fastjson2.JSONObject; | |||
| import com.baomidou.mybatisplus.core.toolkit.StringUtils; | |||
| import com.baomidou.mybatisplus.core.toolkit.Wrappers; | |||
| import com.xueyi.common.core.constant.basic.BaseConstants; | |||
| import com.xueyi.common.core.constant.basic.SecurityConstants; | |||
| import com.xueyi.common.core.constant.digitalman.InitConstants; | |||
| import com.xueyi.common.core.constant.basic.SqlConstants; | |||
| import com.xueyi.common.core.constant.digitalman.MessageConstants; | |||
| import com.xueyi.common.core.web.result.AjaxResult; | |||
| import com.xueyi.common.core.web.result.R; | |||
| import com.xueyi.common.core.web.validate.V_A; | |||
| @@ -12,26 +16,52 @@ import com.xueyi.common.log.enums.BusinessType; | |||
| import com.xueyi.common.security.annotation.InnerAuth; | |||
| import com.xueyi.common.security.annotation.RequiresPermissions; | |||
| import com.xueyi.common.web.entity.controller.BaseController; | |||
| import com.xueyi.system.api.device.domain.po.DmDeviceTenantMergePo; | |||
| import com.xueyi.common.web.utils.DateUtils; | |||
| import com.xueyi.message.api.transfer.feign.RemoteTransferService; | |||
| import com.xueyi.system.api.device.domain.vo.DeviceTenantSourceMergeVo; | |||
| import com.xueyi.system.api.device.feign.RemoteDeviceTenantMergeService; | |||
| import com.xueyi.system.api.digitalmans.domain.dto.DmDigitalmanWorktimeDto; | |||
| import com.xueyi.system.api.digitalmans.domain.dto.DmModelDto; | |||
| import com.xueyi.system.api.digitalmans.domain.dto.DmManDeviceDto; | |||
| import com.xueyi.system.api.digitalmans.domain.dto.DmSyncDigitalmanDto; | |||
| import com.xueyi.system.api.digitalmans.domain.po.DmDigitalmanExtPo; | |||
| import com.xueyi.system.api.digitalmans.domain.po.DmDigitalmanPo; | |||
| import com.xueyi.system.api.digitalmans.domain.po.DmDigitalmanPo; | |||
| import com.xueyi.system.api.digitalmans.domain.po.DmManDevicePo; | |||
| import com.xueyi.system.api.digitalmans.feign.RemoteDigitalmanService; | |||
| import com.xueyi.system.device.service.impl.DmDeviceTenantMergeServiceImpl; | |||
| import com.xueyi.system.digitalmans.domain.dto.DmDigitalmanDto; | |||
| import com.xueyi.system.digitalmans.domain.dto.DmDigitalmanExtDto; | |||
| import com.xueyi.system.digitalmans.domain.model.DmDigitalmanExtConverter; | |||
| import com.xueyi.system.digitalmans.domain.query.DmDigitalmanExtQuery; | |||
| import com.xueyi.system.digitalmans.domain.query.DmDigitalmanQuery; | |||
| import com.xueyi.system.digitalmans.mapper.DmManDeviceMapper; | |||
| import com.xueyi.system.digitalmans.service.IDmDigitalmanExtService; | |||
| import com.xueyi.system.digitalmans.service.IDmDigitalmanService; | |||
| import com.xueyi.system.digitalmans.service.IDmModelService; | |||
| import com.xueyi.system.digitalmans.service.IDmSkillService; | |||
| import com.xueyi.system.emcs.constant.EmcsUploadType; | |||
| import com.xueyi.system.emcs.domain.dto.DmDeviceLogFileDto; | |||
| import com.xueyi.system.emcs.domain.dto.DmExceptionLogDto; | |||
| import com.xueyi.system.emcs.domain.dto.RedisBaseDto; | |||
| import com.xueyi.system.emcs.mapper.DmDeviceLogFileMapper; | |||
| import com.xueyi.system.emcs.mapper.DmExceptionLogMapper; | |||
| import com.xueyi.system.emcs.service.BaseRedisListDataCache; | |||
| import org.slf4j.Logger; | |||
| import org.slf4j.LoggerFactory; | |||
| import org.springframework.beans.factory.annotation.Autowired; | |||
| import org.springframework.data.redis.core.RedisTemplate; | |||
| import org.springframework.validation.annotation.Validated; | |||
| import org.springframework.web.bind.annotation.*; | |||
| import org.springframework.web.bind.annotation.DeleteMapping; | |||
| import org.springframework.web.bind.annotation.GetMapping; | |||
| import org.springframework.web.bind.annotation.PathVariable; | |||
| import org.springframework.web.bind.annotation.PostMapping; | |||
| import org.springframework.web.bind.annotation.PutMapping; | |||
| 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.io.Serializable; | |||
| import java.text.ParseException; | |||
| import java.time.Duration; | |||
| import java.util.List; | |||
| /** | |||
| @@ -43,18 +73,54 @@ import java.util.List; | |||
| @RequestMapping("/man") | |||
| public class DmDigitalmanController extends BaseController<DmDigitalmanQuery, DmDigitalmanDto, IDmDigitalmanService> { | |||
| private final static String HEART_MQTT_PREFIX = "digital-man"; | |||
| private final static Integer REDIS_LIST_SIZE = 60; | |||
| @Autowired | |||
| private BaseRedisListDataCache baseRedisListDataCache; | |||
| @Autowired | |||
| private DmManDeviceMapper manDeviceMapper; | |||
| @Autowired | |||
| private DmExceptionLogMapper exceptionLogMapper; | |||
| @Autowired | |||
| private DmDeviceLogFileMapper deviceLogFileMapper; | |||
| @Autowired | |||
| private RemoteDeviceTenantMergeService remoteDeviceTenantMergeService; | |||
| private static final Logger log = LoggerFactory.getLogger(DmDigitalmanController.class); | |||
| @Autowired | |||
| private DmDeviceTenantMergeServiceImpl deviceTenantMergeService; | |||
| @Autowired | |||
| private IDmDigitalmanExtService dmDigitalmanExtService; | |||
| @Autowired | |||
| private IDmDigitalmanService dmDigitalmanService; | |||
| @Autowired | |||
| private IDmSkillService dmSkillService; | |||
| @Autowired | |||
| private IDmModelService dmModelService; | |||
| @Autowired | |||
| private DmDigitalmanExtConverter dmDigitalmanExtConverter; | |||
| @Autowired | |||
| private RemoteTransferService remoteTransferService; | |||
| @Autowired | |||
| private RemoteDigitalmanService remoteDigitalmanService; | |||
| @Autowired | |||
| private RedisTemplate<String, Serializable> redisTemplate; | |||
| /** 定义节点名称 */ | |||
| @Override | |||
| protected String getNodeName() { | |||
| @@ -75,16 +141,34 @@ public class DmDigitalmanController extends BaseController<DmDigitalmanQuery, Dm | |||
| return R.ok(super.baseService.selectExt(devId)); | |||
| } | |||
| @PostMapping("/inner/sync") | |||
| public R<Boolean> sync() { | |||
| // 获取账号绑定的设备号 | |||
| List<String> devices = super.baseService.selectRegisteredDevices(); | |||
| @InnerAuth | |||
| @PostMapping("/inner/sync_ext_isonline") | |||
| public R<Integer> syncExtIsonline(@RequestBody List<DmManDeviceDto> devices) { | |||
| devices.forEach(item->{ | |||
| // 获取并更新在线状态 | |||
| super.baseService.syncRegisteredDevice(item); | |||
| // 数字人预警机制 | |||
| //根据设备与租户信息更新在线状态 | |||
| AjaxResult ar = remoteTransferService.getDeviceOnlineStatus(item.getDeviceId()); | |||
| DmDigitalmanExtQuery query1 = new DmDigitalmanExtQuery(); | |||
| query1.setDeviceId(item.getDeviceId()); | |||
| List<DmDigitalmanExtDto> extList = dmDigitalmanExtService.selectListByDeviceId(query1); | |||
| if (extList != null && extList.size() > 0) { | |||
| extList.get(0).setIsOnline(Integer.parseInt(ar.get("msg").toString())); | |||
| dmDigitalmanExtService.update(extList.get(0)); | |||
| // 更新缓存 | |||
| DmManDeviceDto redisDto = (DmManDeviceDto)redisTemplate.opsForHash().get(MessageConstants.REDIS_GROUP_DEVICE_HEADER,item.getDeviceId()); | |||
| redisDto.setOnlineStatus(ar.get("msg").toString()); | |||
| log.info("更新缓存:{}",redisDto); | |||
| // 删除缓存 | |||
| redisTemplate.opsForHash().delete(MessageConstants.REDIS_GROUP_DEVICE_HEADER, item.getDeviceId()); | |||
| // 插入缓存 | |||
| redisTemplate.opsForHash().putIfAbsent(MessageConstants.REDIS_GROUP_DEVICE_HEADER,item.getDeviceId(),redisDto); | |||
| } | |||
| }); | |||
| return R.ok(); | |||
| } | |||
| @PostMapping("/inner/update_device_online") | |||
| public R<Boolean> updateDeviceOnline(String deviceId) { | |||
| super.baseService.syncRegisteredDevice(deviceId); | |||
| // 数字人预警机制 | |||
| return null; | |||
| } | |||
| /** | |||
| @@ -190,4 +274,121 @@ public class DmDigitalmanController extends BaseController<DmDigitalmanQuery, Dm | |||
| /** 系统 - 数字人基础管理 - 删除 */ | |||
| String DM_DIGITALMAN_DEL = "man:man:delete"; | |||
| } | |||
| @PostMapping("/api/mqtt/heartbeat") | |||
| public void heartbeat(@RequestBody(required = true) String message) { | |||
| JSONObject heartBeatObj = JSONObject.parseObject(message); | |||
| String devId = heartBeatObj.getString("devId"); | |||
| String timestamp = heartBeatObj.getString("timestamp"); | |||
| String network = heartBeatObj.getString("wifi_rssi"); | |||
| String cpu_max = heartBeatObj.getString("cpuinfo_max_freq"); | |||
| String cpu_scaling = heartBeatObj.getString("scaling_cur_freq"); | |||
| String ipAddr = heartBeatObj.getString("ip"); | |||
| String cpu = Double.valueOf(cpu_scaling) / Double.valueOf(cpu_max) * 100 + ""; | |||
| String memoryTotal = heartBeatObj.getString("memory_total"); | |||
| Double memoryFree = Double.valueOf(heartBeatObj.getString("memory_free")); | |||
| String memory = (Double.valueOf(memoryTotal) - memoryFree) / Double.valueOf(memoryTotal) * 100 + ""; | |||
| String occurTime = ""; | |||
| DmDigitalmanExtPo extPo = dmDigitalmanService.selectExt(devId); | |||
| if (StringUtils.isNotEmpty(ipAddr)) { | |||
| extPo.setIpAddr(ipAddr); | |||
| dmDigitalmanExtService.update(dmDigitalmanExtConverter.mapperDto(extPo)); | |||
| } | |||
| try { | |||
| occurTime = DateUtils.formatDate(DateUtils.parseLongToDate(timestamp),"HH:mm"); | |||
| } catch (ParseException e) { | |||
| throw new RuntimeException(e); | |||
| } | |||
| if (StringUtils.isNotEmpty(devId)) { | |||
| if (StringUtils.isNotEmpty(network)){ | |||
| baseRedisListDataCache.init (REDIS_LIST_SIZE).addToList(HEART_MQTT_PREFIX+":"+devId+":network", new RedisBaseDto(occurTime, network)); | |||
| baseRedisListDataCache.setListExpiration(HEART_MQTT_PREFIX+":"+devId+":network", Duration.ofHours(1)); | |||
| } | |||
| if (StringUtils.isNotEmpty(cpu)) { | |||
| baseRedisListDataCache.init(REDIS_LIST_SIZE).addToList(HEART_MQTT_PREFIX + ":" + devId + ":cpu", new RedisBaseDto(occurTime, cpu)); | |||
| baseRedisListDataCache.setListExpiration(HEART_MQTT_PREFIX+":"+devId+":cpu", Duration.ofHours(1)); | |||
| } | |||
| if (StringUtils.isNotEmpty(memory)) { | |||
| baseRedisListDataCache.init(REDIS_LIST_SIZE).addToList(HEART_MQTT_PREFIX + ":" + devId + ":memory", new RedisBaseDto(occurTime, memory)); | |||
| baseRedisListDataCache.setListExpiration(HEART_MQTT_PREFIX+":"+devId+":memory", Duration.ofHours(1)); | |||
| } | |||
| } | |||
| System.err.println(heartBeatObj.toJSONString()); | |||
| } | |||
| @PostMapping("/api/mqtt/log-upload") | |||
| public void logUpload(@RequestBody(required = true) String message) { | |||
| JSONObject uploadObj = JSONObject.parseObject(message); | |||
| String devId = uploadObj.getString("devId"); | |||
| String timestamp = uploadObj.getString("timestamp"); | |||
| String fileName = uploadObj.getString("file_name"); | |||
| String path = uploadObj.getString("path"); | |||
| String type = uploadObj.getString("type"); | |||
| Integer level = uploadObj.getInteger("level"); | |||
| Integer uploadType = uploadObj.getInteger("upload_type"); | |||
| DmExceptionLogDto exceptionLogDto = new DmExceptionLogDto(); | |||
| exceptionLogDto.setType(type); | |||
| exceptionLogDto.setLevel(level); | |||
| exceptionLogDto.setDevId(devId); | |||
| DmManDevicePo devicePo = manDeviceMapper.selectOne(Wrappers.<DmManDevicePo>lambdaQuery().eq(DmManDevicePo::getDeviceId, devId).last(SqlConstants.LIMIT_ONE)); | |||
| try { | |||
| if (null!= devicePo) { | |||
| exceptionLogDto.setManCode(devicePo.getManCode()); | |||
| exceptionLogDto.setTId(devicePo.getTId()); | |||
| exceptionLogDto.setOccurTime(DateUtils.dateToLocalDateTime(DateUtils.parseLongToDate(timestamp))); | |||
| // 上传类型为崩溃上传时,插入异常日志 | |||
| if (uploadType == EmcsUploadType.getTypeCrackUpload()) { | |||
| exceptionLogMapper.insert(exceptionLogDto); | |||
| } | |||
| //DmExceptionLogDto 持久化 | |||
| DmDeviceLogFileDto deviceLogFileDto = new DmDeviceLogFileDto(); | |||
| deviceLogFileDto.setManDeviceId(devicePo.getId()); | |||
| deviceLogFileDto.setUrl(path); | |||
| deviceLogFileDto.setType(uploadType); | |||
| deviceLogFileDto.setName(fileName); | |||
| deviceLogFileMapper.insert(deviceLogFileDto); | |||
| } else { | |||
| return; | |||
| } | |||
| } catch (ParseException e) { | |||
| throw new RuntimeException(e); | |||
| } | |||
| } | |||
| @GetMapping("/inner-api/devInfo/{devId}") | |||
| public R<DmDigitalmanExtPo> devInnerInfo(@PathVariable(required = true) String devId) { | |||
| if (StringUtils.isNotEmpty(devId)) { | |||
| DmDigitalmanExtPo po = dmDigitalmanService.selectExt(devId); | |||
| return R.ok(po); | |||
| } | |||
| return R.fail("请检查请求参数"); | |||
| } | |||
| @GetMapping("/api/devInfo/{devId}") | |||
| public R<DmDigitalmanExtPo> devInfo(@PathVariable(required = true) String devId) { | |||
| if (StringUtils.isNotEmpty(devId)){ | |||
| DeviceTenantSourceMergeVo vo = remoteDeviceTenantMergeService.selectDeviceTenantSourceMerge(devId); | |||
| if (null!= vo){ | |||
| return remoteDigitalmanService.devInfo(devId, vo.getTenantId(), vo.getSourceSlave(), SecurityConstants.INNER); | |||
| } else { | |||
| return R.fail("devId可能不存在"); | |||
| } | |||
| } | |||
| return R.fail("请检查请求参数"); | |||
| } | |||
| } | |||
| @@ -1,8 +1,10 @@ | |||
| package com.xueyi.system.digitalmans.controller; | |||
| import com.alibaba.fastjson.JSONObject; | |||
| import com.xueyi.common.cache.utils.SourceUtil; | |||
| import com.xueyi.common.core.constant.basic.SecurityConstants; | |||
| import com.xueyi.common.core.constant.digitalman.InitConstants; | |||
| import com.xueyi.common.core.constant.digitalman.MessageConstants; | |||
| import com.xueyi.common.core.utils.core.IdUtil; | |||
| import com.xueyi.common.core.web.result.AjaxResult; | |||
| import com.xueyi.common.core.web.result.R; | |||
| @@ -17,19 +19,24 @@ import com.xueyi.message.api.transfer.domain.vo.DmActiveVo; | |||
| import com.xueyi.message.api.transfer.feign.RemoteTransferService; | |||
| import com.xueyi.system.api.device.domain.dto.DmDeviceTenantMergeDto; | |||
| import com.xueyi.system.api.digitalmans.domain.dto.DmManDeviceDto; | |||
| import com.xueyi.system.api.digitalmans.domain.vo.NumberOfOnlineToChartVo; | |||
| import com.xueyi.system.api.digitalmans.feign.RemoteDigitalmanService; | |||
| import com.xueyi.system.api.model.Source; | |||
| import com.xueyi.system.api.organize.domain.dto.SysEnterpriseDto; | |||
| import com.xueyi.system.device.service.IDmDeviceTenantMergeService; | |||
| import com.xueyi.system.dict.service.ISysDictDataService; | |||
| import com.xueyi.system.digitalmans.domain.dto.DmDigitalmanExtDto; | |||
| import com.xueyi.system.digitalmans.domain.query.DmDigitalmanExtQuery; | |||
| import com.xueyi.system.digitalmans.domain.query.DmManDeviceQuery; | |||
| import com.xueyi.system.digitalmans.service.IDmDigitalmanExtService; | |||
| import com.xueyi.system.digitalmans.service.IDmDigitalmanService; | |||
| import com.xueyi.system.digitalmans.service.IDmManDeviceService; | |||
| import com.xueyi.system.emcs.domain.dto.DmExceptionLogDto; | |||
| import com.xueyi.system.emcs.domain.query.DmExceptionLogQuery; | |||
| import com.xueyi.system.emcs.service.IDmExceptionLogService; | |||
| import com.xueyi.system.organize.service.ISysEnterpriseService; | |||
| import org.slf4j.Logger; | |||
| import org.slf4j.LoggerFactory; | |||
| import org.springframework.beans.factory.annotation.Autowired; | |||
| import org.springframework.data.redis.core.RedisTemplate; | |||
| import org.springframework.validation.annotation.Validated; | |||
| import org.springframework.web.bind.annotation.DeleteMapping; | |||
| import org.springframework.web.bind.annotation.GetMapping; | |||
| @@ -42,7 +49,15 @@ import org.springframework.web.bind.annotation.RequestParam; | |||
| import org.springframework.web.bind.annotation.RestController; | |||
| import java.io.Serializable; | |||
| import java.time.LocalDate; | |||
| import java.time.LocalDateTime; | |||
| import java.time.format.DateTimeFormatter; | |||
| import java.util.ArrayList; | |||
| import java.util.List; | |||
| import java.util.concurrent.TimeUnit; | |||
| import static com.xueyi.common.core.constant.digitalman.InitConstants.DEVICE_ACTIVATE_STATUS_OFFLINE; | |||
| import static com.xueyi.common.core.constant.digitalman.RedisDefinitionConstants.GENERAL_CURRENT_NUMBER_OF_ONLINE; | |||
| /** | |||
| * 数字人设备管理管理 业务处理 | |||
| @@ -53,6 +68,7 @@ import java.util.List; | |||
| @RequestMapping("/manDevice") | |||
| public class DmManDeviceController extends BaseController<DmManDeviceQuery, DmManDeviceDto, IDmManDeviceService> { | |||
| private static final Logger log = LoggerFactory.getLogger(DmManDeviceController.class); | |||
| @Autowired | |||
| IDmDigitalmanService digitalmanService; | |||
| @@ -74,6 +90,13 @@ public class DmManDeviceController extends BaseController<DmManDeviceQuery, DmMa | |||
| @Autowired | |||
| RemoteTransferService remoteTransferService; | |||
| @Autowired | |||
| RedisTemplate<String,Serializable> redisTemplate; | |||
| @Autowired | |||
| IDmExceptionLogService dmExceptionLogService; | |||
| /** 定义节点名称 */ | |||
| @Override | |||
| @@ -99,24 +122,65 @@ public class DmManDeviceController extends BaseController<DmManDeviceQuery, DmMa | |||
| DmManDeviceQuery query = new DmManDeviceQuery(); | |||
| query.setTId(tenantId); | |||
| //根据租户id获取设备列表 | |||
| List<DmManDeviceDto> list = super.baseService.manDeviceListNotNull(); | |||
| list.forEach(item->{ | |||
| AjaxResult ar = remoteTransferService.getDeviceOnlineStatus(item.getDeviceId()); | |||
| DmDigitalmanExtQuery query1 = new DmDigitalmanExtQuery(); | |||
| query1.setDeviceId(item.getDeviceId()); | |||
| List<DmDigitalmanExtDto> extList = digitalmanExtService.selectListByDeviceId(query1); | |||
| if (extList != null && extList.size() > 0) { | |||
| extList.get(0).setIsOnline(Integer.parseInt(ar.get("msg").toString())); | |||
| digitalmanExtService.update(extList.get(0)); | |||
| List<DmManDeviceDto> list = super.baseService.manDeviceListNotNullByTenantId(tenantId); | |||
| SysEnterpriseDto dto = enterpriseService.selectById(tenantId); | |||
| Source source = SourceUtil.getSourceCache(dto.getStrategyId()); | |||
| // 同步总体设备信息 | |||
| list.stream().filter(item->!item.getOnlineStatus().equalsIgnoreCase("0")).forEach(item->{ | |||
| log.info("同步设备信息:{}",item); | |||
| DmManDeviceDto tempDto = (DmManDeviceDto) redisTemplate.opsForHash().get(MessageConstants.REDIS_GROUP_DEVICE_HEADER,item.getDeviceId()); | |||
| if (!item.getOnlineStatus().equalsIgnoreCase(tempDto.getOnlineStatus())) { | |||
| item.setOnlineStatus(tempDto.getOnlineStatus()); | |||
| super.baseService.update(item); | |||
| } | |||
| if (tempDto.getOnlineStatus().equalsIgnoreCase(DEVICE_ACTIVATE_STATUS_OFFLINE)) { | |||
| // query if the device is in the exception log | |||
| DmExceptionLogQuery logQuery = new DmExceptionLogQuery(); | |||
| logQuery.setDevId(tempDto.getDeviceId()); | |||
| logQuery.setTId(tenantId); | |||
| logQuery.setAlertStatus(0); | |||
| logQuery.setType("heartbeat_status"); | |||
| List<DmExceptionLogDto> logDtos = dmExceptionLogService.selectList(logQuery); | |||
| // if logDtos is not empty, then add a record to the exception log | |||
| if (logDtos != null && logDtos.size() == 0) { | |||
| DmExceptionLogDto logDto = new DmExceptionLogDto(); | |||
| logDto.setDevId(item.getDeviceId()); | |||
| logDto.setTId(tenantId); | |||
| logDto.setAlertStatus(0); | |||
| logDto.setManCode(item.getManCode()); | |||
| logDto.setLevel(3); | |||
| logDto.setType("heartbeat_status"); | |||
| logDto.setOccurTime(LocalDateTime.now()); | |||
| dmExceptionLogService.insert(logDto); | |||
| } | |||
| } | |||
| }); | |||
| return R.ok(); | |||
| return remoteDigitalmanService.syncExtIsonline(list,tenantId,source.getMaster(), SecurityConstants.INNER); | |||
| } | |||
| @PutMapping(value = "/inner/info") | |||
| R<Integer> manDeviceInfoInnerUpdate(@RequestBody DmActiveVo vo) { | |||
| return R.ok(super.baseService.manDeviceInfoInnerUpdate(vo)); | |||
| } | |||
| @PostMapping(value = "/inner/sync_numbers_of_online") | |||
| R<Integer> syncNumbersOfOnline() { | |||
| LocalDate currentDate = LocalDate.now(); | |||
| DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MM/dd"); | |||
| List<Object> manDeviceDtos = (List<Object>)redisTemplate.opsForHash().values(MessageConstants.REDIS_GROUP_DEVICE_HEADER); | |||
| Long total = manDeviceDtos.stream().filter(item->(!((DmManDeviceDto)item).getOnlineStatus().isEmpty()) && | |||
| ((DmManDeviceDto)item).getOnlineStatus().equalsIgnoreCase("1")).count(); | |||
| NumberOfOnlineToChartVo vo = new NumberOfOnlineToChartVo(); | |||
| vo.setNumberOfOnline(total.toString()); | |||
| vo.setDate(currentDate.format(formatter)); | |||
| vo.setTotal(manDeviceDtos.size()); | |||
| // 获取当前日期并将数据同步到redis | |||
| redisTemplate.opsForList().leftPush(GENERAL_CURRENT_NUMBER_OF_ONLINE,vo); | |||
| if (redisTemplate.opsForList().size(GENERAL_CURRENT_NUMBER_OF_ONLINE) > 150) { | |||
| redisTemplate.opsForList().rightPop(GENERAL_CURRENT_NUMBER_OF_ONLINE,1, TimeUnit.MINUTES); | |||
| } | |||
| return R.ok(Integer.parseInt(vo.getNumberOfOnline())); | |||
| } | |||
| /** | |||
| * 查询数字人设备管理列表 | |||
| */ | |||
| @@ -152,6 +216,7 @@ public class DmManDeviceController extends BaseController<DmManDeviceQuery, DmMa | |||
| dmManDevice.setManCode(manCode); | |||
| dmManDevice.setTId(dmManDevice.getTenantId()); | |||
| dmManDevice.setOnlineStatus(InitConstants.DEVICE_ACTIVATE_STATUS_NOT_ACTIVATE); | |||
| dmManDevice.setDelFlag(0L); | |||
| super.add(dmManDevice); | |||
| //创建设备映射表 | |||
| DmDeviceTenantMergeDto dmDeviceTenantMergeDto = new DmDeviceTenantMergeDto(); | |||
| @@ -199,6 +264,41 @@ public class DmManDeviceController extends BaseController<DmManDeviceQuery, DmMa | |||
| return super.batchRemove(idList); | |||
| } | |||
| @GetMapping("/dashboard_data") | |||
| @RequiresPermissions(Auth.DM_MAN_DEVICE_LIST) | |||
| public AjaxResult dashboardData() { | |||
| return AjaxResult.success(super.baseService.dashboardData()); | |||
| } | |||
| @GetMapping("/online_devices_to_chart") | |||
| @RequiresPermissions(Auth.DM_MAN_DEVICE_LIST) | |||
| public AjaxResult onlineDevicesToChart() { | |||
| Long total = redisTemplate.opsForList().size(GENERAL_CURRENT_NUMBER_OF_ONLINE); | |||
| // 从缓存中获取在线信息 | |||
| List devices = (List) redisTemplate.opsForList().range(GENERAL_CURRENT_NUMBER_OF_ONLINE, 0, total.longValue()); | |||
| // 获取最近五周的数据 | |||
| List<NumberOfOnlineToChartVo> charList = new ArrayList<>(); | |||
| int count = 0; | |||
| for (int i = 0; i < devices.size() && i < 35; i++) { | |||
| if (++count % 7 == 0) { | |||
| charList.add((NumberOfOnlineToChartVo) devices.get(i)); | |||
| } | |||
| } | |||
| JSONObject jsonObject = new JSONObject(); | |||
| jsonObject.put("near5Weeks", charList); | |||
| // 获取最近五个月的数据 | |||
| count = 0; | |||
| charList = new ArrayList<>(); | |||
| for (int i = 0; i < devices.size(); i++) { | |||
| if (++count % 30 == 0) { | |||
| charList.add((NumberOfOnlineToChartVo) devices.get(i)); | |||
| } | |||
| } | |||
| jsonObject.put("near5Months", charList); | |||
| return AjaxResult.success(jsonObject); | |||
| } | |||
| /** | |||
| * 获取数字人设备管理选择框列表 | |||
| */ | |||
| @@ -222,4 +322,6 @@ public class DmManDeviceController extends BaseController<DmManDeviceQuery, DmMa | |||
| /** 系统 - 数字人设备管理管理 - 删除 */ | |||
| String DM_MAN_DEVICE_DEL = "digitalmans:manDevice:delete"; | |||
| } | |||
| } | |||
| @@ -18,5 +18,5 @@ public interface IDmManDeviceManager extends IBaseManager<DmManDeviceQuery, DmMa | |||
| Integer updateInfoByManual(DmManDeviceDto dto); | |||
| List<DmManDeviceDto> selectListByManual(DmManDeviceQuery query); | |||
| List<DmManDeviceDto> selectManDeviceListNotNull(); | |||
| List<DmManDeviceDto> selectManDeviceListNotNullByTenantId(Long tenantId); | |||
| } | |||
| @@ -5,23 +5,26 @@ import com.xueyi.common.core.constant.basic.SqlConstants; | |||
| import com.xueyi.common.web.entity.manager.impl.BaseManagerImpl; | |||
| import com.xueyi.system.api.digitalmans.domain.dto.DmDigitalmanWorktimeDto; | |||
| import com.xueyi.system.api.digitalmans.domain.dto.DmSyncDigitalmanDto; | |||
| import com.xueyi.system.api.resource.domain.po.DmResourcesPo; | |||
| import com.xueyi.system.digitalmans.domain.dto.DmDigitalmanExtDto; | |||
| import com.xueyi.system.digitalmans.domain.model.DmDigitalmanWorktimeConverter; | |||
| import com.xueyi.system.api.digitalmans.domain.po.DmDigitalmanExtPo; | |||
| import com.xueyi.system.api.digitalmans.domain.po.DmDigitalmanPo; | |||
| import com.xueyi.system.digitalmans.domain.dto.DmDigitalmanDto; | |||
| import com.xueyi.system.api.digitalmans.domain.po.DmModelPo; | |||
| import com.xueyi.system.digitalmans.domain.query.DmDigitalmanQuery; | |||
| import com.xueyi.system.api.organize.domain.vo.SysDeptExt; | |||
| import com.xueyi.system.api.resource.domain.po.DmResourcesPo; | |||
| import com.xueyi.system.digitalmans.domain.dto.DmDigitalmanDto; | |||
| import com.xueyi.system.digitalmans.domain.model.DmDigitalmanConverter; | |||
| import com.xueyi.system.digitalmans.mapper.*; | |||
| import com.xueyi.system.digitalmans.domain.model.DmDigitalmanWorktimeConverter; | |||
| import com.xueyi.system.digitalmans.domain.query.DmDigitalmanQuery; | |||
| import com.xueyi.system.digitalmans.manager.IDmDigitalmanManager; | |||
| import com.xueyi.system.digitalmans.mapper.DmDigitalmanExtMapper; | |||
| import com.xueyi.system.digitalmans.mapper.DmDigitalmanMapper; | |||
| import com.xueyi.system.digitalmans.mapper.DmDigitalmanWorktimeMapper; | |||
| import com.xueyi.system.digitalmans.mapper.DmModelMapper; | |||
| import com.xueyi.system.organize.mapper.SysDeptExtMapper; | |||
| import com.xueyi.system.resource.mapper.DmResourcesMapper; | |||
| import org.springframework.beans.factory.annotation.Autowired; | |||
| import org.springframework.stereotype.Component; | |||
| import java.io.Serializable; | |||
| import java.util.List; | |||
| /** | |||
| * 数字人基础管理 数据封装层处理 | |||
| @@ -39,6 +42,9 @@ public class DmDigitalmanManager extends BaseManagerImpl<DmDigitalmanQuery, DmDi | |||
| @Autowired | |||
| DmResourcesMapper dmResourcesMapper; | |||
| @Autowired | |||
| SysDeptExtMapper sysDeptExtMapper; | |||
| @Autowired | |||
| DmDigitalmanWorktimeMapper digitalmanWorktimeMapper; | |||
| @@ -109,7 +115,15 @@ public class DmDigitalmanManager extends BaseManagerImpl<DmDigitalmanQuery, DmDi | |||
| public DmSyncDigitalmanDto syncDigitalmanInfo(String manCode, String timestamp) { | |||
| System.out.println("======syncDigitalmanInfo: manCode:" + manCode); | |||
| DmDigitalmanPo dmpo = mapperPo(super.baseMapper.selectByCode(manCode)); | |||
| DmDigitalmanExtPo extPo = digitalmanExtMapper.selectByManCode(manCode); | |||
| DmSyncDigitalmanDto sdmdto = new DmSyncDigitalmanDto(); | |||
| System.err.println(extPo); | |||
| System.err.println(extPo.getDeptId()); | |||
| if (null != extPo && null != extPo.getDeptId()) { | |||
| SysDeptExt deptExt = sysDeptExtMapper.selectWorkTimeByDeptId(extPo.getDeptId()); | |||
| sdmdto.setWorkdayHour(deptExt);//考勤时间 | |||
| } | |||
| sdmdto.setId(dmpo.getId()); | |||
| sdmdto.setManCode(dmpo.getManCode()); | |||
| sdmdto.setName(dmpo.getName()); | |||
| @@ -123,8 +137,10 @@ public class DmDigitalmanManager extends BaseManagerImpl<DmDigitalmanQuery, DmDi | |||
| System.out.println(mpo.getCurrentScreenOff()); | |||
| sdmdto.setBackground(dmResourcesMapper.selectById(mpo.getCurrentBackground())); | |||
| sdmdto.setIcon(dmResourcesMapper.selectById(mpo.getIconId())); | |||
| sdmdto.setIconPos(mpo.getIconPos()); | |||
| DmResourcesPo screenOffPo = dmResourcesMapper.selectById(mpo.getCurrentScreenOff()); | |||
| sdmdto.setScreenOff(screenOffPo); | |||
| System.out.println(sdmdto); | |||
| return sdmdto; | |||
| } | |||
| } | |||
| @@ -53,7 +53,7 @@ public class DmManDeviceManager extends BaseManagerImpl<DmManDeviceQuery, DmManD | |||
| } | |||
| @Override | |||
| public List<DmManDeviceDto> selectManDeviceListNotNull() { | |||
| return mapperDto(manDeviceMapper.selectListByManualDeviceIdNotNull()); | |||
| public List<DmManDeviceDto> selectManDeviceListNotNullByTenantId(Long tenantId) { | |||
| return mapperDto(manDeviceMapper.selectListByManualDeviceIdNotNullByTenantId(tenantId)); | |||
| } | |||
| } | |||
| @@ -12,7 +12,9 @@ import com.xueyi.system.digitalmans.mapper.DmModelMapper; | |||
| import com.xueyi.common.web.entity.manager.impl.BaseManagerImpl; | |||
| import com.xueyi.system.digitalmans.manager.IDmModelManager; | |||
| import com.xueyi.system.api.resource.domain.po.DmResourcesPo; | |||
| import com.xueyi.system.resource.domain.po.DmBackgroundPo; | |||
| import com.xueyi.system.resource.domain.po.DmScreenOffPo; | |||
| import com.xueyi.system.resource.mapper.DmBackgroundMapper; | |||
| import com.xueyi.system.resource.mapper.DmResourcesMapper; | |||
| import com.xueyi.system.resource.mapper.DmScreenOffMapper; | |||
| import org.springframework.beans.factory.annotation.Autowired; | |||
| @@ -41,6 +43,9 @@ public class DmModelManager extends BaseManagerImpl<DmModelQuery, DmModelDto, Dm | |||
| @Autowired | |||
| DmScreenOffMapper screenOffMapper; | |||
| @Autowired | |||
| DmBackgroundMapper backgroundMapper; | |||
| @Autowired | |||
| DmDigitalmanMapper digitalmanMapper; | |||
| @@ -64,12 +69,19 @@ public class DmModelManager extends BaseManagerImpl<DmModelQuery, DmModelDto, Dm | |||
| modelDto.getRSuits().add(dmResourcesMapper.selectById(Long.parseLong(suitItem))); | |||
| }); | |||
| } | |||
| // 获取背景页 | |||
| List<DmBackgroundPo> backgroundPos = backgroundMapper.selectList(null); | |||
| List<DmResourcesPo> bResourcesPos = new ArrayList<>(); | |||
| backgroundPos.forEach(rpo->bResourcesPos.add(dmResourcesMapper.selectById(rpo.getResourceId()))); | |||
| modelDto.setRBackgrounds(bResourcesPos); | |||
| /** 新业务 需求变更,代码暂时保留 | |||
| if (modelDto.getBackgroundContain() != null && modelDto.getBackgroundContain().length() > 0) { | |||
| modelDto.setRBackgrounds(new ArrayList<>(modelDto.getBackgroundContain().split(",").length)); | |||
| Arrays.asList(modelDto.getBackgroundContain().split(",")).forEach(bgItem-> { | |||
| modelDto.getRBackgrounds().add(dmResourcesMapper.selectById(Long.parseLong(bgItem))); | |||
| }); | |||
| } | |||
| **/ | |||
| // 获取模型页 | |||
| modelDto.setModelUrl(dmResourcesMapper.selectById(modelDto.getCurrentModel()).getUrl()); | |||
| // 获取展示页 | |||
| @@ -1,12 +1,10 @@ | |||
| package com.xueyi.system.digitalmans.mapper; | |||
| import com.xueyi.common.datasource.annotation.Isolate; | |||
| import com.xueyi.system.digitalmans.domain.dto.DmDigitalmanDto; | |||
| import com.xueyi.system.digitalmans.domain.query.DmDigitalmanExtQuery; | |||
| import com.xueyi.system.digitalmans.domain.dto.DmDigitalmanExtDto; | |||
| import com.xueyi.system.api.digitalmans.domain.po.DmDigitalmanExtPo; | |||
| import com.xueyi.common.web.entity.mapper.BaseMapper; | |||
| import com.xueyi.common.datasource.annotation.Master; | |||
| import com.xueyi.system.api.digitalmans.domain.po.DmDigitalmanExtPo; | |||
| import com.xueyi.system.digitalmans.domain.dto.DmDigitalmanExtDto; | |||
| import com.xueyi.system.digitalmans.domain.query.DmDigitalmanExtQuery; | |||
| /** | |||
| * 数字人扩展管理 数据层 | |||
| @@ -16,5 +14,6 @@ import com.xueyi.common.datasource.annotation.Master; | |||
| @Isolate | |||
| public interface DmDigitalmanExtMapper extends BaseMapper<DmDigitalmanExtQuery, DmDigitalmanExtDto, DmDigitalmanExtPo> { | |||
| public DmDigitalmanExtDto selectByManId(Long id); | |||
| public DmDigitalmanExtDto selectByManCode(String manCode); | |||
| } | |||
| @@ -5,6 +5,7 @@ import com.xueyi.system.api.digitalmans.domain.dto.DmManDeviceDto; | |||
| import com.xueyi.system.api.digitalmans.domain.po.DmManDevicePo; | |||
| import com.xueyi.common.web.entity.mapper.BaseMapper; | |||
| import com.xueyi.common.datasource.annotation.Master; | |||
| import org.apache.ibatis.annotations.Param; | |||
| import java.util.List; | |||
| @@ -16,7 +17,7 @@ import java.util.List; | |||
| @Master | |||
| public interface DmManDeviceMapper extends BaseMapper<DmManDeviceQuery, DmManDeviceDto, DmManDevicePo> { | |||
| List<DmManDevicePo> selectListByManual(DmManDevicePo po); | |||
| List<DmManDevicePo> selectListByManualDeviceIdNotNull(); | |||
| List<DmManDevicePo> selectListByManualDeviceIdNotNullByTenantId(@Param("tenantId")Long tenantId); | |||
| DmManDevicePo getOne(String devId); | |||
| @@ -4,6 +4,7 @@ import com.xueyi.common.web.entity.service.IBaseService; | |||
| import com.xueyi.message.api.transfer.domain.vo.DmActiveVo; | |||
| import com.xueyi.system.api.digitalmans.domain.po.DmManDevicePo; | |||
| import com.xueyi.system.api.digitalmans.domain.dto.DmManDeviceDto; | |||
| import com.xueyi.system.api.digitalmans.domain.vo.DashboardVo; | |||
| import com.xueyi.system.digitalmans.domain.query.DmManDeviceQuery; | |||
| import java.util.List; | |||
| @@ -17,6 +18,8 @@ public interface IDmManDeviceService extends IBaseService<DmManDeviceQuery, DmMa | |||
| DmManDeviceDto manDeviceInfoInner(String devId); | |||
| Integer manDeviceInfoInnerUpdate(DmActiveVo vo); | |||
| List<DmManDeviceDto> manDeviceListNotNull(); | |||
| List<DmManDeviceDto> manDeviceListNotNullByTenantId(Long tenantId); | |||
| DmManDevicePo getOne(String devId); | |||
| DashboardVo dashboardData(); | |||
| } | |||
| @@ -1,12 +1,11 @@ | |||
| package com.xueyi.system.digitalmans.service.impl; | |||
| import com.xueyi.common.web.entity.service.impl.BaseServiceImpl; | |||
| import com.xueyi.system.digitalmans.domain.dto.DmDigitalmanExtDto; | |||
| import com.xueyi.system.digitalmans.domain.query.DmDigitalmanExtQuery; | |||
| import com.xueyi.system.digitalmans.manager.IDmDigitalmanExtManager; | |||
| import com.xueyi.system.digitalmans.mapper.DmDigitalmanExtMapper; | |||
| import com.xueyi.system.digitalmans.mapper.DmDigitalmanMapper; | |||
| import com.xueyi.system.digitalmans.service.IDmDigitalmanExtService; | |||
| import com.xueyi.system.digitalmans.manager.IDmDigitalmanExtManager; | |||
| import com.xueyi.common.web.entity.service.impl.BaseServiceImpl; | |||
| import org.springframework.beans.factory.annotation.Autowired; | |||
| import org.springframework.stereotype.Service; | |||
| @@ -333,6 +333,7 @@ public class DmDigitalmanServiceImpl extends BaseServiceImpl<DmDigitalmanQuery, | |||
| resourcesDto.setName("logo"); | |||
| dmResourcesService.initAdd(resourcesDto); | |||
| modelDto.setIconId(resourcesDto.getId()); | |||
| modelDto.setIconPos("0"); | |||
| // 添加衣服 | |||
| resourcesDto = new DmResourcesDto(); | |||
| @@ -1,27 +1,31 @@ | |||
| package com.xueyi.system.digitalmans.service.impl; | |||
| import com.github.pagehelper.Page; | |||
| import com.baomidou.mybatisplus.core.toolkit.Wrappers; | |||
| import com.xueyi.common.core.constant.digitalman.InitConstants; | |||
| import com.xueyi.common.core.constant.digitalman.MessageConstants; | |||
| import com.xueyi.common.core.utils.core.IdUtil; | |||
| import com.xueyi.common.core.web.result.AjaxResult; | |||
| import com.xueyi.common.web.annotation.TenantIgnore; | |||
| import com.xueyi.common.web.entity.service.impl.BaseServiceImpl; | |||
| import com.xueyi.message.api.transfer.domain.vo.DmActiveVo; | |||
| import com.xueyi.message.api.transfer.domain.vo.DmDeviceVo; | |||
| import com.xueyi.message.api.transfer.feign.RemoteTransferService; | |||
| import com.xueyi.system.api.digitalmans.domain.po.DmManDevicePo; | |||
| import com.xueyi.system.api.digitalmans.domain.dto.DmManDeviceDto; | |||
| import com.xueyi.system.api.digitalmans.domain.po.DmManDevicePo; | |||
| import com.xueyi.system.api.digitalmans.domain.vo.DashboardVo; | |||
| import com.xueyi.system.digitalmans.domain.query.DmManDeviceQuery; | |||
| import com.xueyi.system.digitalmans.manager.IDmManDeviceManager; | |||
| import com.xueyi.system.digitalmans.mapper.DmManDeviceMapper; | |||
| import com.xueyi.system.digitalmans.service.IDmManDeviceService; | |||
| import com.xueyi.system.resource.service.IDmResourcesService; | |||
| import com.xueyi.system.emcs.domain.po.DmExceptionLogPo; | |||
| import com.xueyi.system.emcs.mapper.DmExceptionLogMapper; | |||
| import org.slf4j.Logger; | |||
| import org.slf4j.LoggerFactory; | |||
| import org.springframework.beans.factory.annotation.Autowired; | |||
| import org.springframework.data.redis.core.RedisTemplate; | |||
| import org.springframework.stereotype.Service; | |||
| import java.io.Serializable; | |||
| import java.time.LocalDateTime; | |||
| import java.time.format.DateTimeFormatter; | |||
| import java.util.List; | |||
| /** | |||
| @@ -33,6 +37,7 @@ import java.util.List; | |||
| public class DmManDeviceServiceImpl extends BaseServiceImpl<DmManDeviceQuery, DmManDeviceDto, IDmManDeviceManager> implements IDmManDeviceService { | |||
| private static final Logger log = LoggerFactory.getLogger(DmManDeviceServiceImpl.class); | |||
| @Autowired | |||
| RemoteTransferService remoteTransferService; | |||
| @@ -46,6 +51,10 @@ public class DmManDeviceServiceImpl extends BaseServiceImpl<DmManDeviceQuery, Dm | |||
| @Autowired | |||
| RedisTemplate<String, Serializable> manDeviceDtoRedisTemplate; | |||
| @Autowired | |||
| DmExceptionLogMapper exceptionLogMapper; | |||
| /** | |||
| * 查询数字人设备管理对象列表 | 数据权限 | |||
| @@ -111,8 +120,35 @@ public class DmManDeviceServiceImpl extends BaseServiceImpl<DmManDeviceQuery, Dm | |||
| } | |||
| @Override | |||
| public List<DmManDeviceDto> manDeviceListNotNull() { | |||
| public List<DmManDeviceDto> manDeviceListNotNullByTenantId(Long tenantId) { | |||
| return super.baseManager.selectManDeviceListNotNullByTenantId(tenantId); | |||
| } | |||
| return super.baseManager.selectManDeviceListNotNull(); | |||
| @Override | |||
| public DashboardVo dashboardData() { | |||
| DashboardVo vo = new DashboardVo(); | |||
| List<DmManDeviceDto> manDeviceDtoList = this.selectList(new DmManDeviceQuery()); | |||
| // 获取数字员工总数 | |||
| vo.setDigitalMans(manDeviceDtoList.size()); | |||
| // 获取当前在线率 | |||
| Long total = (long)manDeviceDtoList.size(); | |||
| Long onlineTotal = manDeviceDtoList.stream().filter(item->(!item.getOnlineStatus().isEmpty()) && | |||
| item.getOnlineStatus().equalsIgnoreCase("1")).count(); | |||
| int percent = (total == 0?0 : (int)(onlineTotal/total.doubleValue() * 100)); | |||
| log.info("数字员工总数为{},当前在线设备为{},当前在线率为:{}",total, onlineTotal, percent); | |||
| vo.setOnlineDevices(percent); | |||
| // 近七天预警 | |||
| LocalDateTime currentDate = LocalDateTime.now(); | |||
| LocalDateTime sevenDaysAgo =currentDate.minusDays(7).withHour(0).withMinute(0).withSecond(0); | |||
| DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); | |||
| vo.setAlertNear7Days(exceptionLogMapper.selectList(Wrappers.<DmExceptionLogPo>query().lambda() | |||
| .ge(DmExceptionLogPo::getCreateTime,sevenDaysAgo.format(formatter))).size()); | |||
| // 当前未解除预警数 | |||
| vo.setOnProcessAlert(exceptionLogMapper.selectList(Wrappers.<DmExceptionLogPo>query().lambda() | |||
| .eq(DmExceptionLogPo::getAlertStatus,0)).size()); | |||
| return vo; | |||
| } | |||
| } | |||
| @@ -0,0 +1,23 @@ | |||
| package com.xueyi.system.emcs.constant; | |||
| public class EmcsUploadType { | |||
| final static int TYPE_SCHEDULE_UPLOAD = 0; | |||
| final static int TYPE_ACTIVE_UPLOAD = 1; | |||
| final static int TYPE_CRACK_UPLOAD = 2; | |||
| public static int getTypeScheduleUpload(){ | |||
| return TYPE_SCHEDULE_UPLOAD; | |||
| } | |||
| public static int getTypeActiveUpload(){ | |||
| return TYPE_ACTIVE_UPLOAD; | |||
| } | |||
| public static int getTypeCrackUpload(){ | |||
| return TYPE_CRACK_UPLOAD; | |||
| } | |||
| } | |||
| @@ -0,0 +1,109 @@ | |||
| package com.xueyi.system.emcs.controller; | |||
| import com.xueyi.common.core.web.result.AjaxResult; | |||
| import com.xueyi.common.core.web.validate.V_A; | |||
| import com.xueyi.common.core.web.validate.V_E; | |||
| import com.xueyi.common.log.annotation.Log; | |||
| import com.xueyi.common.log.enums.BusinessType; | |||
| import com.xueyi.common.security.annotation.RequiresPermissions; | |||
| import com.xueyi.common.web.entity.controller.BaseController; | |||
| import com.xueyi.system.emcs.domain.dto.DmDeviceLogFileDto; | |||
| import com.xueyi.system.emcs.domain.query.DmDeviceLogFileQuery; | |||
| import com.xueyi.system.emcs.service.IDmDeviceLogFileService; | |||
| import org.springframework.validation.annotation.Validated; | |||
| import org.springframework.web.bind.annotation.*; | |||
| import java.io.Serializable; | |||
| import java.util.List; | |||
| /** | |||
| * 日志文件信息记录管理 业务处理 | |||
| * | |||
| * @author xueyi | |||
| */ | |||
| @RestController | |||
| @RequestMapping("/log_file") | |||
| public class DmDeviceLogFileController extends BaseController<DmDeviceLogFileQuery, DmDeviceLogFileDto, IDmDeviceLogFileService> { | |||
| /** 定义节点名称 */ | |||
| @Override | |||
| protected String getNodeName() { | |||
| return "日志文件信息记录" ; | |||
| } | |||
| /** | |||
| * 查询日志文件信息记录列表 | |||
| */ | |||
| @Override | |||
| @GetMapping("/list") | |||
| @RequiresPermissions(Auth.DM_DEVICE_LOG_FILE_LIST) | |||
| public AjaxResult list(DmDeviceLogFileQuery deviceLogFile) { | |||
| System.out.println("DmDeviceLogFileController:list"); | |||
| return super.list(deviceLogFile); | |||
| } | |||
| /** | |||
| * 查询日志文件信息记录详细 | |||
| */ | |||
| @Override | |||
| @GetMapping(value = "/{id}") | |||
| @RequiresPermissions(Auth.DM_DEVICE_LOG_FILE_SINGLE) | |||
| public AjaxResult getInfo(@PathVariable Serializable id) { | |||
| return super.getInfo(id); | |||
| } | |||
| /** | |||
| * 日志文件信息记录新增 | |||
| */ | |||
| @Override | |||
| @PostMapping | |||
| @RequiresPermissions(Auth.DM_DEVICE_LOG_FILE_ADD) | |||
| @Log(title = "日志文件信息记录管理", businessType = BusinessType.INSERT) | |||
| public AjaxResult add(@Validated({V_A.class}) @RequestBody DmDeviceLogFileDto deviceLogFile) { | |||
| return super.add(deviceLogFile); | |||
| } | |||
| /** | |||
| * 日志文件信息记录修改 | |||
| */ | |||
| @Override | |||
| @PutMapping | |||
| @RequiresPermissions(Auth.DM_DEVICE_LOG_FILE_EDIT) | |||
| @Log(title = "日志文件信息记录管理", businessType = BusinessType.UPDATE) | |||
| public AjaxResult edit(@Validated({V_E.class}) @RequestBody DmDeviceLogFileDto deviceLogFile) { | |||
| return super.edit(deviceLogFile); | |||
| } | |||
| /** | |||
| * 日志文件信息记录批量删除 | |||
| */ | |||
| @Override | |||
| @DeleteMapping("/batch/{idList}") | |||
| @RequiresPermissions(Auth.DM_DEVICE_LOG_FILE_DEL) | |||
| @Log(title = "日志文件信息记录管理", businessType = BusinessType.DELETE) | |||
| public AjaxResult batchRemove(@PathVariable List<Long> idList) { | |||
| return super.batchRemove(idList); | |||
| } | |||
| /** | |||
| * 获取日志文件信息记录选择框列表 | |||
| */ | |||
| @Override | |||
| @GetMapping("/option") | |||
| public AjaxResult option() { | |||
| return super.option(); | |||
| } | |||
| interface Auth { | |||
| /** 系统 - 日志文件信息记录管理 - 列表 */ | |||
| String DM_DEVICE_LOG_FILE_LIST = "system:file:list"; | |||
| /** 系统 - 日志文件信息记录管理 - 详情 */ | |||
| String DM_DEVICE_LOG_FILE_SINGLE = "system:file:single"; | |||
| /** 系统 - 日志文件信息记录管理 - 新增 */ | |||
| String DM_DEVICE_LOG_FILE_ADD = "system:file:add"; | |||
| /** 系统 - 日志文件信息记录管理 - 修改 */ | |||
| String DM_DEVICE_LOG_FILE_EDIT = "system:file:edit"; | |||
| /** 系统 - 日志文件信息记录管理 - 删除 */ | |||
| String DM_DEVICE_LOG_FILE_DEL = "system:file:delete"; | |||
| } | |||
| } | |||
| @@ -0,0 +1,327 @@ | |||
| package com.xueyi.system.emcs.controller; | |||
| import com.alibaba.fastjson2.JSONObject; | |||
| import com.baomidou.mybatisplus.core.toolkit.StringUtils; | |||
| import com.xueyi.common.core.web.result.AjaxResult; | |||
| import com.xueyi.common.core.web.validate.V_A; | |||
| import com.xueyi.common.core.web.validate.V_E; | |||
| import com.xueyi.common.log.annotation.Log; | |||
| import com.xueyi.common.log.enums.BusinessType; | |||
| import com.xueyi.common.mqtt.connection.MqttTemplate; | |||
| import com.xueyi.common.security.annotation.RequiresPermissions; | |||
| import com.xueyi.common.web.entity.controller.BaseController; | |||
| import com.xueyi.system.api.digitalmans.domain.vo.NumberOfAlertToChartVo; | |||
| import com.xueyi.system.emcs.domain.dto.DmExceptionLogDto; | |||
| import com.xueyi.system.emcs.domain.dto.RedisBaseDto; | |||
| import com.xueyi.system.emcs.domain.query.DmExceptionLogQuery; | |||
| import com.xueyi.system.emcs.service.BaseRedisListDataCache; | |||
| import com.xueyi.system.emcs.service.IDmExceptionLogService; | |||
| import com.xueyi.system.emcs.service.LogMqttMessageHandler; | |||
| import com.xueyi.system.emcs.service.impl.DmExceptionLogServiceImpl; | |||
| import org.springframework.beans.factory.annotation.Autowired; | |||
| import org.springframework.validation.annotation.Validated; | |||
| import org.springframework.web.bind.annotation.DeleteMapping; | |||
| import org.springframework.web.bind.annotation.GetMapping; | |||
| import org.springframework.web.bind.annotation.PathVariable; | |||
| import org.springframework.web.bind.annotation.PostMapping; | |||
| import org.springframework.web.bind.annotation.PutMapping; | |||
| import org.springframework.web.bind.annotation.RequestBody; | |||
| import org.springframework.web.bind.annotation.RequestMapping; | |||
| import org.springframework.web.bind.annotation.RestController; | |||
| import java.io.Serializable; | |||
| import java.time.DayOfWeek; | |||
| import java.time.LocalDate; | |||
| import java.time.LocalDateTime; | |||
| import java.time.LocalTime; | |||
| import java.time.Month; | |||
| import java.time.YearMonth; | |||
| import java.time.format.DateTimeFormatter; | |||
| import java.util.ArrayList; | |||
| import java.util.Arrays; | |||
| import java.util.HashMap; | |||
| import java.util.List; | |||
| import java.util.Map; | |||
| /** | |||
| * 数字人状态事件上报日志管理 业务处理 | |||
| * | |||
| * @author xueyi | |||
| */ | |||
| @RestController | |||
| @RequestMapping("/log") | |||
| public class DmExceptionLogController extends BaseController<DmExceptionLogQuery, DmExceptionLogDto, IDmExceptionLogService> { | |||
| private final static String HEART_MQTT_PREFIX = "digital-man"; | |||
| private final static String[] CHART_TYPES = new String[]{"network", "cpu", "memory"}; | |||
| @Autowired | |||
| private MqttTemplate mqttTemplate; | |||
| @Autowired | |||
| private LogMqttMessageHandler logMqttMessageHandler; | |||
| @Autowired | |||
| private BaseRedisListDataCache baseRedisListDataCache; | |||
| @Autowired | |||
| private DmExceptionLogServiceImpl exceptionLogService; | |||
| /** 定义节点名称 */ | |||
| @Override | |||
| protected String getNodeName() { | |||
| return "数字人状态事件上报日志" ; | |||
| } | |||
| /** | |||
| * 查询数字人状态事件上报日志列表 | |||
| */ | |||
| @Override | |||
| @GetMapping("/list") | |||
| @RequiresPermissions(Auth.DM_EXCEPTION_LOG_LIST) | |||
| public AjaxResult list(DmExceptionLogQuery exceptionLog) { | |||
| return super.list(exceptionLog); | |||
| } | |||
| /** | |||
| * 查询数字人状态事件上报日志详细 | |||
| */ | |||
| @Override | |||
| @GetMapping(value = "/{id}") | |||
| @RequiresPermissions(Auth.DM_EXCEPTION_LOG_SINGLE) | |||
| public AjaxResult getInfo(@PathVariable Serializable id) { | |||
| return super.getInfo(id); | |||
| } | |||
| /** | |||
| * 数字人状态事件上报日志新增 | |||
| */ | |||
| @Override | |||
| @PostMapping | |||
| @RequiresPermissions(Auth.DM_EXCEPTION_LOG_ADD) | |||
| @Log(title = "数字人状态事件上报日志管理", businessType = BusinessType.INSERT) | |||
| public AjaxResult add(@Validated({V_A.class}) @RequestBody DmExceptionLogDto exceptionLog) { | |||
| return super.add(exceptionLog); | |||
| } | |||
| /** | |||
| * 数字人状态事件上报日志修改 | |||
| */ | |||
| @Override | |||
| @PutMapping | |||
| @RequiresPermissions(Auth.DM_EXCEPTION_LOG_EDIT) | |||
| @Log(title = "数字人状态事件上报日志管理", businessType = BusinessType.UPDATE) | |||
| public AjaxResult edit(@Validated({V_E.class}) @RequestBody DmExceptionLogDto exceptionLog) { | |||
| if (exceptionLog == null || exceptionLog.getId() == null) { | |||
| return error("参数不合法"); | |||
| } | |||
| DmExceptionLogDto dto = exceptionLogService.selectById(exceptionLog.getId()); | |||
| dto.setAlertStatus(exceptionLog.getAlertStatus()); | |||
| dto.setEndTime(LocalDateTime.now()); | |||
| return super.edit(dto); | |||
| } | |||
| public static List<String> getRecentHourTimes() { | |||
| List<String> recentHourTimes = new ArrayList<>(); | |||
| // 获取当前时间 | |||
| LocalDateTime now = LocalDateTime.now(); | |||
| // 获取一个小时前的时间 | |||
| LocalDateTime oneHourAgo = now.minusHours(1); | |||
| // 从一个小时前的时间开始,每分钟递增,直到当前时间 | |||
| LocalDateTime current = oneHourAgo; | |||
| while (current.isBefore(now)) { | |||
| // 格式化时间为HH:mm | |||
| String formattedTime = current.format(DateTimeFormatter.ofPattern("HH:mm")); | |||
| // 添加到列表中 | |||
| recentHourTimes.add(formattedTime); | |||
| // 当前时间加一分钟 | |||
| current = current.plusMinutes(1); | |||
| } | |||
| return recentHourTimes; | |||
| } | |||
| @GetMapping( value = "/chart/{devId}") | |||
| public AjaxResult queryChartData(@PathVariable String devId) { | |||
| JSONObject json = new JSONObject(); | |||
| List<String> times = getRecentHourTimes(); | |||
| Arrays.stream(CHART_TYPES).toList().forEach(item->{ | |||
| List<Serializable> redisList = new ArrayList<>(); | |||
| String key = HEART_MQTT_PREFIX + ":" + devId + ":" + item; | |||
| redisList = baseRedisListDataCache.getList(key); | |||
| if (redisList!= null && redisList.size() > 0) { | |||
| RedisBaseDto baseDto = (RedisBaseDto) redisList.get(redisList.size()-1); | |||
| String occur = baseDto.getOccurTime(); | |||
| String last = times.get(times.size()-1); | |||
| LocalTime localTime1 = LocalTime.parse(occur); | |||
| LocalTime localTime2 = LocalTime.parse(last); | |||
| LocalTime localTime = localTime2.minusMinutes(3); | |||
| if (localTime.compareTo(localTime1) > 0 ){ | |||
| JSONObject redisDto = new JSONObject(); | |||
| redisDto.put("occurTime", localTime2.format(DateTimeFormatter.ofPattern("HH:mm"))); | |||
| redisDto.put("val", "N"); | |||
| redisList.add(redisDto); | |||
| } | |||
| } else { | |||
| String last = times.get(times.size()-1); | |||
| LocalTime localTime2 = LocalTime.parse(last); | |||
| JSONObject redisDto = new JSONObject(); | |||
| redisDto.put("occurTime", localTime2.format(DateTimeFormatter.ofPattern("HH:mm"))); | |||
| redisDto.put("val", "N"); | |||
| redisList.add(redisDto); | |||
| } | |||
| // redisList.get(redisList.size()-1); | |||
| json.put(item, redisList); | |||
| }); | |||
| System.err.println(getRecentHourTimes()); | |||
| return success(json); | |||
| } | |||
| /** | |||
| * 数字人状态事件上报日志批量删除 | |||
| */ | |||
| @Override | |||
| @DeleteMapping("/batch/{idList}") | |||
| @RequiresPermissions(Auth.DM_EXCEPTION_LOG_DEL) | |||
| @Log(title = "数字人状态事件上报日志管理", businessType = BusinessType.DELETE) | |||
| public AjaxResult batchRemove(@PathVariable List<Long> idList) { | |||
| return super.batchRemove(idList); | |||
| } | |||
| @GetMapping("/range_alerts_to_chart") | |||
| public AjaxResult rangeAlertsToChart() { | |||
| JSONObject jsonObject = new JSONObject(); | |||
| List<NumberOfAlertToChartVo> rangeBy5Weeks = new ArrayList<>(); | |||
| // select nearly 5 weeks alerts from dm_exception_log | |||
| DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); | |||
| LocalDateTime startL = LocalDateTime.now(); | |||
| LocalDateTime endL = null; | |||
| for (int i = 0;i < 5;i++) { | |||
| // 格式化日期时间 | |||
| // 把startL设置当前时间减一周后的周一00:00:00 | |||
| startL = startL.with(DayOfWeek.MONDAY).withHour(0).withMinute(0).withSecond(0); | |||
| // 把endL设置成周日23:59:59,如果是当前一周,设置成当前时间 | |||
| if (i == 0) { | |||
| endL = LocalDateTime.now(); | |||
| } else { | |||
| endL = startL.with(DayOfWeek.SUNDAY).withHour(23).withMinute(59).withSecond(59); | |||
| } | |||
| String start = startL.format(formatter); | |||
| String end = endL.format(formatter); | |||
| NumberOfAlertToChartVo vo = new NumberOfAlertToChartVo(); | |||
| DateTimeFormatter formatter_for_week = DateTimeFormatter.ofPattern("MM-dd"); | |||
| vo.setNumberOfAlert(String.valueOf(super.baseService.selectListRangeByCreateTime(start,end).size())); | |||
| vo.setDate(startL.format(formatter_for_week)); | |||
| rangeBy5Weeks.add(0,vo); | |||
| // 将startL减去1周 | |||
| startL = startL.minusWeeks(1); | |||
| } | |||
| jsonObject.put("rangeBy5Weeks",rangeBy5Weeks); | |||
| //获取近五月的预警 | |||
| startL = LocalDateTime.now(); | |||
| List<NumberOfAlertToChartVo> rangeBy5Months = new ArrayList<>(); | |||
| for (int i = 0;i < 5;i++) { | |||
| // 格式化日期时间 | |||
| // 把startL设置当前时间减一周后的周一00:00:00 | |||
| startL = startL.withDayOfMonth(1).withHour(0).withMinute(0).withSecond(0); | |||
| // 把endL设置成周日23:59:59,如果是当前一周,设置成当前时间 | |||
| if (i == 0) { | |||
| endL = LocalDateTime.now(); | |||
| } else { | |||
| endL = startL.plusMonths(1).minusDays(1).withHour(23).withMinute(59).withSecond(59); | |||
| } | |||
| String start = startL.format(formatter); | |||
| String end = endL.format(formatter); | |||
| NumberOfAlertToChartVo vo = new NumberOfAlertToChartVo(); | |||
| DateTimeFormatter formatter_for_month = DateTimeFormatter.ofPattern("MM"); | |||
| vo.setNumberOfAlert(String.valueOf(super.baseService.selectListRangeByCreateTime(start,end).size())); | |||
| vo.setDate(startL.format(formatter_for_month)); | |||
| rangeBy5Months.add(0,vo); | |||
| // 开始时间减去1个月 | |||
| startL = startL.minusMonths(1); | |||
| } | |||
| jsonObject.put("rangeBy5Months",rangeBy5Months); | |||
| return AjaxResult.success(jsonObject); | |||
| } | |||
| @GetMapping("/alerts_counts_to_chart/{devId}") | |||
| public AjaxResult rangeAlertCountsToChart(@PathVariable String devId) { | |||
| JSONObject jsonObject = new JSONObject(); | |||
| List<Map<String, Integer>> range = new ArrayList<>(); | |||
| YearMonth currentYearMonth = YearMonth.now(); | |||
| int currentYear = currentYearMonth.getYear(); | |||
| int currentMonth = currentYearMonth.getMonthValue(); | |||
| DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd"); | |||
| // 遍历每个月 | |||
| for (Month month : Month.values()) { | |||
| int monthValue = month.getValue(); | |||
| // 如果当前月份已经过去,则跳过输出 | |||
| if (currentYear == currentYear && monthValue > currentMonth) { | |||
| continue; | |||
| } | |||
| // 获取当前月份的第一天和最后一天 | |||
| LocalDate firstDay = LocalDate.of(currentYear, month, 1); | |||
| LocalDate lastDay = firstDay.withDayOfMonth(firstDay.lengthOfMonth()); | |||
| String start = firstDay.atStartOfDay().withHour(0).withMinute(0).withSecond(0).format(formatter); | |||
| String end = lastDay.atStartOfDay().withHour(23).withMinute(59).withSecond(59).format(formatter); | |||
| Map<String, Integer> map = new HashMap<>(); | |||
| map.put(monthValue+"月",super.baseService.selectListRangeByCreateTimeAndDevId(start, end, devId).size()); | |||
| range.add(map); | |||
| } | |||
| jsonObject.put("range",range); | |||
| return AjaxResult.success(jsonObject); | |||
| } | |||
| /* | |||
| * @Author yangkai | |||
| * @Description //主动拉取日志操作 | |||
| * @Date 2023/5/10 | |||
| * @Param [devId, uploadType] | |||
| * @return com.xueyi.common.core.web.result.AjaxResult | |||
| **/ | |||
| @PostMapping("/fetch-log") | |||
| public AjaxResult sendMqttMsgToDev(@RequestBody JSONObject json){ | |||
| String devId = json.getString("devId"); | |||
| devId = StringUtils.isEmpty(devId) ? json.getString("id") : devId; | |||
| JSONObject jsonObject = new JSONObject(); | |||
| jsonObject.put("devId", devId); | |||
| mqttTemplate.sendToMqtt("/digital_man"+"/"+devId+"/log_upload", jsonObject.toJSONString()); | |||
| return success("操作成功"); | |||
| } | |||
| /** | |||
| * 获取数字人状态事件上报日志选择框列表 | |||
| */ | |||
| @Override | |||
| @GetMapping("/option") | |||
| public AjaxResult option() { | |||
| return super.option(); | |||
| } | |||
| interface Auth { | |||
| /** 系统 - 数字人状态事件上报日志管理 - 列表 */ | |||
| String DM_EXCEPTION_LOG_LIST = "log:log:list"; | |||
| /** 系统 - 数字人状态事件上报日志管理 - 详情 */ | |||
| String DM_EXCEPTION_LOG_SINGLE = "log:log:single"; | |||
| /** 系统 - 数字人状态事件上报日志管理 - 新增 */ | |||
| String DM_EXCEPTION_LOG_ADD = "log:log:add"; | |||
| /** 系统 - 数字人状态事件上报日志管理 - 修改 */ | |||
| String DM_EXCEPTION_LOG_EDIT = "log:log:edit"; | |||
| /** 系统 - 数字人状态事件上报日志管理 - 删除 */ | |||
| String DM_EXCEPTION_LOG_DEL = "log:log:delete"; | |||
| } | |||
| } | |||
| @@ -0,0 +1,30 @@ | |||
| package com.xueyi.system.emcs.domain.dto; | |||
| import com.xueyi.common.core.annotation.Correlation; | |||
| import com.xueyi.common.core.constant.basic.OperateConstants; | |||
| import com.xueyi.system.api.digitalmans.domain.dto.DmManDeviceDto; | |||
| import com.xueyi.system.emcs.domain.po.DmDeviceLogFilePo; | |||
| import lombok.Data; | |||
| import lombok.EqualsAndHashCode; | |||
| import java.io.Serial; | |||
| import static com.xueyi.system.api.exception.domain.merge.MergeGroup.LOG_DmDevice_GROUP; | |||
| /** | |||
| * 日志文件信息记录 数据传输对象 | |||
| * | |||
| * @author xueyi | |||
| */ | |||
| @Data | |||
| @EqualsAndHashCode(callSuper = true) | |||
| public class DmDeviceLogFileDto extends DmDeviceLogFilePo { | |||
| @Serial | |||
| private static final long serialVersionUID = 1L; | |||
| /** 模块信息 */ | |||
| @Correlation(groupName = LOG_DmDevice_GROUP, keyType = OperateConstants.SubKeyType.RECEIVE) | |||
| private DmManDeviceDto dmManDeviceDto; | |||
| } | |||
| @@ -1,6 +1,6 @@ | |||
| package com.xueyi.system.exception.domain.dto; | |||
| package com.xueyi.system.emcs.domain.dto; | |||
| import com.xueyi.system.exception.domain.po.DmExceptionLogPo; | |||
| import com.xueyi.system.emcs.domain.po.DmExceptionLogPo; | |||
| import lombok.Data; | |||
| import lombok.EqualsAndHashCode; | |||
| @@ -18,4 +18,6 @@ public class DmExceptionLogDto extends DmExceptionLogPo { | |||
| @Serial | |||
| private static final long serialVersionUID = 1L; | |||
| private String tenantName; | |||
| } | |||
| @@ -0,0 +1,24 @@ | |||
| package com.xueyi.system.emcs.domain.dto; | |||
| import lombok.Data; | |||
| import java.io.Serializable; | |||
| /** | |||
| * 数字人状态事件上报日志网络参数DTO | |||
| * | |||
| * @author xueyi | |||
| */ | |||
| @Data | |||
| public class RedisBaseDto implements Serializable { | |||
| private String occurTime; | |||
| private String val; | |||
| public RedisBaseDto(){} | |||
| public RedisBaseDto(String occurTime, String val) { | |||
| this.occurTime = occurTime; | |||
| this.val = val; | |||
| } | |||
| } | |||
| @@ -0,0 +1,17 @@ | |||
| package com.xueyi.system.emcs.domain.model; | |||
| import com.xueyi.common.core.web.entity.model.BaseConverter; | |||
| import com.xueyi.system.emcs.domain.dto.DmDeviceLogFileDto; | |||
| import com.xueyi.system.emcs.domain.po.DmDeviceLogFilePo; | |||
| import com.xueyi.system.emcs.domain.query.DmDeviceLogFileQuery; | |||
| import org.mapstruct.Mapper; | |||
| import org.mapstruct.MappingConstants; | |||
| /** | |||
| * 日志文件信息记录 对象映射器 | |||
| * | |||
| * @author xueyi | |||
| */ | |||
| @Mapper(componentModel = MappingConstants.ComponentModel.SPRING) | |||
| public interface DmDeviceLogFileConverter extends BaseConverter<DmDeviceLogFileQuery, DmDeviceLogFileDto, DmDeviceLogFilePo> { | |||
| } | |||
| @@ -1,9 +1,9 @@ | |||
| package com.xueyi.system.exception.domain.model; | |||
| package com.xueyi.system.emcs.domain.model; | |||
| import com.xueyi.common.core.web.entity.model.BaseConverter; | |||
| import com.xueyi.system.exception.domain.dto.DmExceptionLogDto; | |||
| import com.xueyi.system.exception.domain.po.DmExceptionLogPo; | |||
| import com.xueyi.system.exception.domain.query.DmExceptionLogQuery; | |||
| import com.xueyi.system.emcs.domain.dto.DmExceptionLogDto; | |||
| import com.xueyi.system.emcs.domain.po.DmExceptionLogPo; | |||
| import com.xueyi.system.emcs.domain.query.DmExceptionLogQuery; | |||
| import org.mapstruct.Mapper; | |||
| import org.mapstruct.MappingConstants; | |||
| @@ -0,0 +1,56 @@ | |||
| package com.xueyi.system.emcs.domain.po; | |||
| import com.xueyi.common.core.annotation.Correlation; | |||
| import com.xueyi.common.core.annotation.Correlations; | |||
| import com.xueyi.common.core.constant.basic.OperateConstants; | |||
| import com.xueyi.common.core.web.entity.base.BaseEntity; | |||
| import com.xueyi.common.core.annotation.Excel; | |||
| import com.baomidou.mybatisplus.annotation.TableName; | |||
| import lombok.Data; | |||
| import lombok.EqualsAndHashCode; | |||
| import javax.validation.constraints.NotNull; | |||
| import java.io.Serial; | |||
| import static com.xueyi.common.core.constant.basic.EntityConstants.*; | |||
| import static com.xueyi.system.api.exception.domain.merge.MergeGroup.LOG_DmDevice_GROUP; | |||
| /** | |||
| * 日志文件信息记录 持久化对象 | |||
| * | |||
| * @author xueyi | |||
| */ | |||
| @Data | |||
| @EqualsAndHashCode(callSuper = true) | |||
| @TableName(value = "dm_device_log_file", excludeProperty = { STATUS, SORT, REMARK, DEL_FLAG }) | |||
| public class DmDeviceLogFilePo extends BaseEntity { | |||
| @Serial | |||
| private static final long serialVersionUID = 1L; | |||
| /** 日志类型(1:通用;2:主动拉起;3:崩溃重启) */ | |||
| @Excel(name = "日志类型(1:通用;2:主动拉起;3:崩溃重启)") | |||
| protected Integer type; | |||
| /** 设备管理主键ID */ | |||
| /** 模块Id */ | |||
| @NotNull(message = "模块Id不能为空") | |||
| @Correlations({ | |||
| @Correlation(groupName = LOG_DmDevice_GROUP, keyType = OperateConstants.SubKeyType.MAIN) | |||
| }) | |||
| protected Long manDeviceId; | |||
| /** url地址 */ | |||
| @Excel(name = "url地址") | |||
| protected String url; | |||
| /** 所属组织ID */ | |||
| @Excel(name = "所属组织ID") | |||
| protected Long deptId; | |||
| /** 文件大小 */ | |||
| @Excel(name = "文件大小") | |||
| protected Long fileSize; | |||
| } | |||
| @@ -1,4 +1,4 @@ | |||
| package com.xueyi.system.exception.domain.po; | |||
| package com.xueyi.system.emcs.domain.po; | |||
| import com.baomidou.mybatisplus.annotation.TableName; | |||
| import com.fasterxml.jackson.annotation.JsonFormat; | |||
| @@ -29,12 +29,15 @@ public class DmExceptionLogPo extends BaseEntity { | |||
| private static final long serialVersionUID = 1L; | |||
| /** 数字人ID */ | |||
| @Excel(name = "数字人ID") | |||
| protected Long manId; | |||
| @Excel(name = "数字人Code") | |||
| protected String manCode; | |||
| @Excel(name = "devId") | |||
| protected String devId; | |||
| /** 故障类型(重启,摄像头故障等) */ | |||
| @Excel(name = "故障类型(重启,摄像头故障等)") | |||
| protected Integer type; | |||
| protected String type; | |||
| /** 故障等级 */ | |||
| @Excel(name = "故障等级") | |||
| @@ -0,0 +1,25 @@ | |||
| package com.xueyi.system.emcs.domain.query; | |||
| import com.xueyi.system.digitalmans.domain.query.DmManDeviceQuery; | |||
| import com.xueyi.system.emcs.domain.po.DmDeviceLogFilePo; | |||
| import lombok.Data; | |||
| import lombok.EqualsAndHashCode; | |||
| import java.io.Serial; | |||
| /** | |||
| * 日志文件信息记录 数据查询对象 | |||
| * | |||
| * @author xueyi | |||
| */ | |||
| @Data | |||
| @EqualsAndHashCode(callSuper = true) | |||
| public class DmDeviceLogFileQuery extends DmDeviceLogFilePo { | |||
| @Serial | |||
| private static final long serialVersionUID = 1L; | |||
| protected String startTime; | |||
| protected String endTime; | |||
| protected DmManDeviceQuery manDeviceQuery; | |||
| } | |||
| @@ -1,6 +1,6 @@ | |||
| package com.xueyi.system.exception.domain.query; | |||
| package com.xueyi.system.emcs.domain.query; | |||
| import com.xueyi.system.exception.domain.po.DmExceptionLogPo; | |||
| import com.xueyi.system.emcs.domain.po.DmExceptionLogPo; | |||
| import lombok.Data; | |||
| import lombok.EqualsAndHashCode; | |||
| @@ -0,0 +1,13 @@ | |||
| package com.xueyi.system.emcs.manager; | |||
| import com.xueyi.system.emcs.domain.dto.DmDeviceLogFileDto; | |||
| import com.xueyi.system.emcs.domain.query.DmDeviceLogFileQuery; | |||
| import com.xueyi.common.web.entity.manager.IBaseManager; | |||
| /** | |||
| * 日志文件信息记录管理 数据封装层 | |||
| * | |||
| * @author xueyi | |||
| */ | |||
| public interface IDmDeviceLogFileManager extends IBaseManager<DmDeviceLogFileQuery, DmDeviceLogFileDto> { | |||
| } | |||
| @@ -0,0 +1,17 @@ | |||
| package com.xueyi.system.emcs.manager; | |||
| import com.xueyi.system.emcs.domain.dto.DmExceptionLogDto; | |||
| import com.xueyi.system.emcs.domain.query.DmExceptionLogQuery; | |||
| import com.xueyi.common.web.entity.manager.IBaseManager; | |||
| import java.util.List; | |||
| /** | |||
| * 数字人状态事件上报日志管理 数据封装层 | |||
| * | |||
| * @author xueyi | |||
| */ | |||
| public interface IDmExceptionLogManager extends IBaseManager<DmExceptionLogQuery, DmExceptionLogDto> { | |||
| List<DmExceptionLogDto> selectListRangeByCreateTime(String start,String end); | |||
| List<DmExceptionLogDto> selectListRangeByCreateTimeAndDevId(String start,String end,String devId); | |||
| } | |||
| @@ -0,0 +1,65 @@ | |||
| package com.xueyi.system.emcs.manager.impl; | |||
| import com.baomidou.mybatisplus.core.toolkit.StringUtils; | |||
| import com.github.pagehelper.Page; | |||
| import com.xueyi.common.core.constant.basic.OperateConstants; | |||
| import com.xueyi.common.core.utils.core.CollUtil; | |||
| import com.xueyi.common.core.utils.page.PageUtil; | |||
| import com.xueyi.common.web.entity.domain.SlaveRelation; | |||
| import com.xueyi.system.api.digitalmans.domain.dto.DmManDeviceDto; | |||
| import com.xueyi.system.digitalmans.manager.impl.DmManDeviceManager; | |||
| import com.xueyi.system.emcs.domain.po.DmDeviceLogFilePo; | |||
| import com.xueyi.system.emcs.domain.dto.DmDeviceLogFileDto; | |||
| import com.xueyi.system.emcs.domain.query.DmDeviceLogFileQuery; | |||
| import com.xueyi.system.emcs.domain.model.DmDeviceLogFileConverter; | |||
| import com.xueyi.system.emcs.mapper.DmDeviceLogFileMapper; | |||
| import com.xueyi.common.web.entity.manager.impl.BaseManagerImpl; | |||
| import com.xueyi.system.emcs.manager.IDmDeviceLogFileManager; | |||
| import org.springframework.beans.factory.annotation.Autowired; | |||
| import org.springframework.stereotype.Component; | |||
| import java.util.ArrayList; | |||
| import java.util.List; | |||
| import java.util.stream.Collectors; | |||
| import static com.xueyi.system.api.exception.domain.merge.MergeGroup.LOG_DmDevice_GROUP; | |||
| /** | |||
| * 日志文件信息记录管理 数据封装层处理 | |||
| * | |||
| * @author xueyi | |||
| */ | |||
| @Component | |||
| public class DmDeviceLogFileManager extends BaseManagerImpl<DmDeviceLogFileQuery, DmDeviceLogFileDto, DmDeviceLogFilePo, DmDeviceLogFileMapper, DmDeviceLogFileConverter> implements IDmDeviceLogFileManager { | |||
| @Autowired | |||
| DmManDeviceManager manDeviceManager; | |||
| @Override | |||
| protected List<SlaveRelation> subRelationInit() { | |||
| return new ArrayList<>() {{ | |||
| add(new SlaveRelation(LOG_DmDevice_GROUP, DmManDeviceManager.class, OperateConstants.SubOperateLimit.ONLY_SEL)); | |||
| }}; | |||
| } | |||
| @Override | |||
| public List<DmDeviceLogFileDto> selectList(DmDeviceLogFileQuery query) { | |||
| // 因为Page在执行第一次查询时会强制注入Limit,所以导致业务逻辑错误,需要先清除Page信息后查询数字人列表,再重新设置Page信息后查询日志 | |||
| Page page = PageUtil.getLocalPage(); | |||
| System.out.println(page.getPageNum() + " " + page.getPageSize()); | |||
| PageUtil.clearPage(); | |||
| List<DmManDeviceDto> manDeviceDtos = manDeviceManager.selectList(query.getManDeviceQuery()); | |||
| List<Long> manDeviceIds = manDeviceDtos.stream().map(DmManDeviceDto::getId).collect(Collectors.toList()); | |||
| if (CollUtil.isEmpty(manDeviceIds)) { | |||
| return new Page<>(); | |||
| } | |||
| PageUtil.startPage(page.getPageNum(), page.getPageSize()); | |||
| return subMerge(mapperDto(super.baseMapper.selectList(selectListQuery(query) | |||
| .and(StringUtils.isNotEmpty(query.getStartTime()) && StringUtils.isNotEmpty(query.getEndTime()), t->{ | |||
| t.ge(DmDeviceLogFilePo::getCreateTime,query.getStartTime()); | |||
| t.le(DmDeviceLogFilePo::getCreateTime,query.getEndTime()); | |||
| }) | |||
| .and(CollUtil.isNotEmpty(manDeviceIds),i->i.in(DmDeviceLogFilePo::getManDeviceId, manDeviceIds))))); | |||
| } | |||
| } | |||
| @@ -0,0 +1,42 @@ | |||
| package com.xueyi.system.emcs.manager.impl; | |||
| import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; | |||
| import com.baomidou.mybatisplus.core.toolkit.StringUtils; | |||
| import com.xueyi.common.web.entity.manager.impl.BaseManagerImpl; | |||
| import com.xueyi.system.emcs.domain.dto.DmExceptionLogDto; | |||
| import com.xueyi.system.emcs.domain.model.DmExceptionLogConverter; | |||
| import com.xueyi.system.emcs.domain.po.DmExceptionLogPo; | |||
| import com.xueyi.system.emcs.domain.query.DmExceptionLogQuery; | |||
| import com.xueyi.system.emcs.manager.IDmExceptionLogManager; | |||
| import com.xueyi.system.emcs.mapper.DmExceptionLogMapper; | |||
| import org.springframework.stereotype.Component; | |||
| import java.util.List; | |||
| /** | |||
| * 数字人状态事件上报日志管理 数据封装层处理 | |||
| * | |||
| * @author xueyi | |||
| */ | |||
| @Component | |||
| public class DmExceptionLogManager extends BaseManagerImpl<DmExceptionLogQuery, DmExceptionLogDto, DmExceptionLogPo, DmExceptionLogMapper, DmExceptionLogConverter> implements IDmExceptionLogManager { | |||
| @Override | |||
| public List<DmExceptionLogDto> selectListRangeByCreateTime(String start,String end) { | |||
| return mapperDto(super.baseMapper.selectList(new LambdaQueryWrapper<DmExceptionLogPo>() | |||
| .and(StringUtils.isNotEmpty(start) && StringUtils.isNotEmpty(end), t->{ | |||
| t.ge(DmExceptionLogPo::getCreateTime,start); | |||
| t.le(DmExceptionLogPo::getCreateTime,end); | |||
| }))); | |||
| } | |||
| @Override | |||
| public List<DmExceptionLogDto> selectListRangeByCreateTimeAndDevId(String start, String end, String devId) { | |||
| return mapperDto(super.baseMapper.selectList(new LambdaQueryWrapper<DmExceptionLogPo>().eq(DmExceptionLogPo::getDevId,devId) | |||
| .and(StringUtils.isNotEmpty(start) && StringUtils.isNotEmpty(end), t->{ | |||
| t.ge(DmExceptionLogPo::getCreateTime,start); | |||
| t.le(DmExceptionLogPo::getCreateTime,end); | |||
| }))); | |||
| } | |||
| } | |||
| @@ -0,0 +1,16 @@ | |||
| package com.xueyi.system.emcs.mapper; | |||
| import com.xueyi.system.emcs.domain.query.DmDeviceLogFileQuery; | |||
| import com.xueyi.system.emcs.domain.dto.DmDeviceLogFileDto; | |||
| import com.xueyi.system.emcs.domain.po.DmDeviceLogFilePo; | |||
| import com.xueyi.common.web.entity.mapper.BaseMapper; | |||
| import com.xueyi.common.datasource.annotation.Master; | |||
| /** | |||
| * 日志文件信息记录管理 数据层 | |||
| * | |||
| * @author xueyi | |||
| */ | |||
| @Master | |||
| public interface DmDeviceLogFileMapper extends BaseMapper<DmDeviceLogFileQuery, DmDeviceLogFileDto, DmDeviceLogFilePo> { | |||
| } | |||
| @@ -1,10 +1,10 @@ | |||
| package com.xueyi.system.exception.mapper; | |||
| package com.xueyi.system.emcs.mapper; | |||
| import com.xueyi.common.datasource.annotation.Master; | |||
| import com.xueyi.common.web.entity.mapper.BaseMapper; | |||
| import com.xueyi.system.exception.domain.dto.DmExceptionLogDto; | |||
| import com.xueyi.system.exception.domain.po.DmExceptionLogPo; | |||
| import com.xueyi.system.exception.domain.query.DmExceptionLogQuery; | |||
| import com.xueyi.system.emcs.domain.dto.DmExceptionLogDto; | |||
| import com.xueyi.system.emcs.domain.po.DmExceptionLogPo; | |||
| import com.xueyi.system.emcs.domain.query.DmExceptionLogQuery; | |||
| /** | |||
| * 数字人状态事件上报日志管理 数据层 | |||
| @@ -0,0 +1,53 @@ | |||
| package com.xueyi.system.emcs.service; | |||
| import org.springframework.beans.factory.annotation.Autowired; | |||
| import org.springframework.data.redis.core.RedisTemplate; | |||
| import org.springframework.stereotype.Component; | |||
| import java.io.Serializable; | |||
| import java.time.Duration; | |||
| import java.time.LocalDateTime; | |||
| import java.time.temporal.ChronoUnit; | |||
| import java.util.List; | |||
| import java.util.concurrent.TimeUnit; | |||
| /** | |||
| * @author yk | |||
| * @description | |||
| * @date 2023-05-12 14:22 | |||
| */ | |||
| @Component | |||
| public class BaseRedisListDataCache { | |||
| @Autowired | |||
| private RedisTemplate<String, Serializable> redisTemplate; | |||
| private Integer size; | |||
| public BaseRedisListDataCache init( Integer size) { | |||
| this.size = size; | |||
| return this; | |||
| } | |||
| public void addToList(String key, Serializable value) { | |||
| // 将新值添加到List中 | |||
| redisTemplate.opsForList().rightPush(key, value); | |||
| // 如果List长度超过设定值,则淘汰最早的元素 | |||
| if (redisTemplate.opsForList().size(key) > size) { | |||
| redisTemplate.opsForList().leftPop(key); | |||
| } | |||
| } | |||
| public List<Serializable> getList(String key) { | |||
| return redisTemplate.opsForList().range(key, 0, -1); | |||
| } | |||
| public void setListExpiration(String key, Duration duration) { | |||
| // 计算过期时间的秒数 | |||
| long expirationSeconds = LocalDateTime.now().plus(duration).until(LocalDateTime.now(), ChronoUnit.SECONDS); | |||
| // 设置键的过期时间 | |||
| redisTemplate.expire(key, expirationSeconds, TimeUnit.SECONDS); | |||
| } | |||
| } | |||
| @@ -0,0 +1,62 @@ | |||
| package com.xueyi.system.emcs.service; | |||
| import com.alibaba.fastjson2.JSONObject; | |||
| import com.baomidou.mybatisplus.core.toolkit.StringUtils; | |||
| import com.xueyi.common.mqtt.service.MqttMessageHandler; | |||
| import com.xueyi.common.redis.service.RedisService; | |||
| import com.xueyi.common.web.utils.DateUtils; | |||
| import com.xueyi.system.emcs.domain.dto.RedisBaseDto; | |||
| import org.springframework.beans.factory.annotation.Autowired; | |||
| import org.springframework.stereotype.Service; | |||
| /** | |||
| * @author yk | |||
| * @description | |||
| * @date 2023-05-10 19:08 | |||
| */ | |||
| @Service | |||
| public class HeartBeatMessageHandler implements MqttMessageHandler { | |||
| @Autowired | |||
| private RedisService redis; | |||
| private final static String HEART_MQTT_PREFIX = "digital-man"; | |||
| private final static Integer REDIS_LIST_SIZE = 60; | |||
| @Autowired | |||
| private BaseRedisListDataCache baseRedisListDataCache; | |||
| @Override | |||
| public void handleMessage(String topic, String message) throws Exception{ | |||
| System.err.println("HeartBeatMessageHandler: " + message); | |||
| JSONObject heartBeatObj = JSONObject.parseObject(message); | |||
| String devId = heartBeatObj.getString("devId"); | |||
| String timestamp = heartBeatObj.getString("timestamp"); | |||
| String network = heartBeatObj.getString("wifi_rssi"); | |||
| String cpu_max = heartBeatObj.getString("cpuinfo_max_freq"); | |||
| String cpu_scaling = heartBeatObj.getString("scaling_cur_freq"); | |||
| String cpu = Double.valueOf(cpu_scaling) / Double.valueOf(cpu_max) * 100 + ""; | |||
| String memory_cur = heartBeatObj.getString("memory_total"); | |||
| // String memoryTotal = heartBeatObj.getString("MemTotal").substring(0,heartBeatObj.getString("MemTotal").length() - 2); | |||
| String memoryTotal = heartBeatObj.getString("memory_total"); | |||
| Double memoryFree = Double.valueOf(heartBeatObj.getString("memory_free")); | |||
| String memory = (Double.valueOf(memoryTotal) - memoryFree) / Double.valueOf(memoryTotal) * 100 + ""; | |||
| String occurTime = ""; | |||
| occurTime = DateUtils.formatDate(DateUtils.parseLongToDate(timestamp),"HH:mm"); | |||
| if (StringUtils.isNotEmpty(devId)) { | |||
| if (StringUtils.isNotEmpty(network)){ | |||
| baseRedisListDataCache.init (REDIS_LIST_SIZE).addToList(HEART_MQTT_PREFIX+":"+devId+":network", new RedisBaseDto(occurTime, network)); | |||
| } | |||
| if (StringUtils.isNotEmpty(cpu)) { | |||
| baseRedisListDataCache.init(REDIS_LIST_SIZE).addToList(HEART_MQTT_PREFIX + ":" + devId + ":cpu", new RedisBaseDto(occurTime, cpu)); | |||
| } | |||
| if (StringUtils.isNotEmpty(memory)) { | |||
| baseRedisListDataCache.init(REDIS_LIST_SIZE).addToList(HEART_MQTT_PREFIX + ":" + devId + ":memory", new RedisBaseDto(occurTime, memory)); | |||
| } | |||
| } | |||
| System.err.println(heartBeatObj.toJSONString()); | |||
| } | |||
| } | |||
| @@ -0,0 +1,13 @@ | |||
| package com.xueyi.system.emcs.service; | |||
| import com.xueyi.system.emcs.domain.query.DmDeviceLogFileQuery; | |||
| import com.xueyi.system.emcs.domain.dto.DmDeviceLogFileDto; | |||
| import com.xueyi.common.web.entity.service.IBaseService; | |||
| /** | |||
| * 日志文件信息记录管理 服务层 | |||
| * | |||
| * @author xueyi | |||
| */ | |||
| public interface IDmDeviceLogFileService extends IBaseService<DmDeviceLogFileQuery, DmDeviceLogFileDto> { | |||
| } | |||
| @@ -0,0 +1,20 @@ | |||
| package com.xueyi.system.emcs.service; | |||
| import com.xueyi.system.emcs.domain.query.DmExceptionLogQuery; | |||
| import com.xueyi.system.emcs.domain.dto.DmExceptionLogDto; | |||
| import com.xueyi.common.web.entity.service.IBaseService; | |||
| import java.util.List; | |||
| /** | |||
| * 数字人状态事件上报日志管理 服务层 | |||
| * | |||
| * @author xueyi | |||
| */ | |||
| public interface IDmExceptionLogService extends IBaseService<DmExceptionLogQuery, DmExceptionLogDto> { | |||
| // 获取某一时间段的数据集合 | |||
| List<DmExceptionLogDto> selectListRangeByCreateTime(String start,String end); | |||
| List<DmExceptionLogDto> selectListRangeByCreateTimeAndDevId(String start,String end,String devId); | |||
| } | |||
| @@ -0,0 +1,38 @@ | |||
| package com.xueyi.system.emcs.service; | |||
| import com.xueyi.common.mqtt.service.MqttMessageHandler; | |||
| import org.springframework.beans.factory.annotation.Autowired; | |||
| import org.springframework.stereotype.Service; | |||
| import java.util.List; | |||
| /** | |||
| * @author yk | |||
| * @description | |||
| * @date 2023-05-10 19:08 | |||
| */ | |||
| @Service | |||
| public class LogMqttMessageHandler implements MqttMessageHandler { | |||
| private final static List<String> TOPICS = List.of("/digital_man/heart_beat", "/digital_man/log_upload_notification"); | |||
| @Autowired | |||
| private HeartBeatMessageHandler heartBeatMessageHandler; | |||
| @Autowired | |||
| private LogUploadMessageHandler logUploadMessageHandler; | |||
| @Override | |||
| public void handleMessage(String topic, String message) throws Exception{ | |||
| // 处理消息的业务逻辑 | |||
| System.out.println("收到主题:" + topic + ",消息内:" + message); | |||
| if (TOPICS.contains(topic)){ | |||
| if (topic.equalsIgnoreCase("/digital_man/log_upload_notification")){ | |||
| logUploadMessageHandler.handleMessage(topic, message); | |||
| } else if (topic.equalsIgnoreCase("/digital_man/heart_beat")){ | |||
| heartBeatMessageHandler.handleMessage(topic, message); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| @@ -0,0 +1,87 @@ | |||
| package com.xueyi.system.emcs.service; | |||
| import com.alibaba.fastjson2.JSONObject; | |||
| import com.baomidou.mybatisplus.core.toolkit.Wrappers; | |||
| import com.xueyi.common.core.constant.basic.SqlConstants; | |||
| import com.xueyi.common.mqtt.service.MqttMessageHandler; | |||
| import com.xueyi.common.web.utils.DateUtils; | |||
| import com.xueyi.system.api.digitalmans.domain.po.DmManDevicePo; | |||
| import com.xueyi.system.digitalmans.mapper.DmManDeviceMapper; | |||
| import com.xueyi.system.emcs.constant.EmcsUploadType; | |||
| import com.xueyi.system.emcs.domain.dto.DmDeviceLogFileDto; | |||
| import com.xueyi.system.emcs.domain.dto.DmExceptionLogDto; | |||
| import com.xueyi.system.emcs.mapper.DmDeviceLogFileMapper; | |||
| import com.xueyi.system.emcs.mapper.DmExceptionLogMapper; | |||
| import org.springframework.beans.factory.annotation.Autowired; | |||
| import org.springframework.stereotype.Service; | |||
| import java.text.ParseException; | |||
| /** | |||
| * | |||
| * @author yk | |||
| * @description 处理订阅到的mqtt设备异常记录 | |||
| * @date 2023-05-10 19:08 | |||
| */ | |||
| @Service | |||
| public class LogUploadMessageHandler implements MqttMessageHandler { | |||
| @Autowired | |||
| private DmManDeviceMapper manDeviceMapper; | |||
| @Autowired | |||
| private DmExceptionLogMapper exceptionLogMapper; | |||
| @Autowired | |||
| private DmDeviceLogFileMapper deviceLogFileMapper; | |||
| @Override | |||
| public void handleMessage(String topic, String message) { | |||
| System.out.println("发送日志到主题:" + topic + ",消息:" + message); | |||
| JSONObject heartBeatObj = JSONObject.parseObject(message); | |||
| String devId = heartBeatObj.getString("devId"); | |||
| String timestamp = heartBeatObj.getString("timestamp"); | |||
| String fileName = heartBeatObj.getString("file_name"); | |||
| String path = heartBeatObj.getString("path"); | |||
| String type = heartBeatObj.getString("type"); | |||
| Integer level = heartBeatObj.getInteger("level"); | |||
| Integer uploadType = heartBeatObj.getInteger("upload_type"); | |||
| DmExceptionLogDto exceptionLogDto = new DmExceptionLogDto(); | |||
| exceptionLogDto.setType(type); | |||
| exceptionLogDto.setLevel(level); | |||
| exceptionLogDto.setDevId(devId); | |||
| DmManDevicePo devicePo = manDeviceMapper.selectOne(Wrappers.<DmManDevicePo>lambdaQuery().eq(DmManDevicePo::getDeviceId, devId).last(SqlConstants.LIMIT_ONE)); | |||
| try { | |||
| if (null!= devicePo) { | |||
| exceptionLogDto.setManCode(devicePo.getManCode()); | |||
| exceptionLogDto.setTId(devicePo.getTId()); | |||
| exceptionLogDto.setOccurTime(DateUtils.dateToLocalDateTime(DateUtils.parseLongToDate(timestamp))); | |||
| // 上传类型为崩溃上传时,插入异常日志 | |||
| if (uploadType == EmcsUploadType.getTypeCrackUpload()) { | |||
| exceptionLogMapper.insert(exceptionLogDto); | |||
| } | |||
| //DmExceptionLogDto 持久化 | |||
| DmDeviceLogFileDto deviceLogFileDto = new DmDeviceLogFileDto(); | |||
| deviceLogFileDto.setManDeviceId(devicePo.getId()); | |||
| deviceLogFileDto.setUrl(path); | |||
| deviceLogFileDto.setType(uploadType); | |||
| deviceLogFileDto.setName(fileName); | |||
| deviceLogFileMapper.insert(deviceLogFileDto); | |||
| } else { | |||
| return; | |||
| } | |||
| } catch (ParseException e) { | |||
| throw new RuntimeException(e); | |||
| } | |||
| } | |||
| } | |||
| @@ -0,0 +1,32 @@ | |||
| package com.xueyi.system.emcs.service.impl; | |||
| import com.xueyi.system.emcs.domain.dto.DmDeviceLogFileDto; | |||
| import com.xueyi.system.emcs.domain.query.DmDeviceLogFileQuery; | |||
| import com.xueyi.system.emcs.service.IDmDeviceLogFileService; | |||
| import com.xueyi.system.emcs.manager.IDmDeviceLogFileManager; | |||
| import com.xueyi.common.web.entity.service.impl.BaseServiceImpl; | |||
| import org.springframework.stereotype.Service; | |||
| import java.util.List; | |||
| /** | |||
| * 日志文件信息记录管理 服务层处理 | |||
| * | |||
| * @author xueyi | |||
| */ | |||
| @Service | |||
| public class DmDeviceLogFileServiceImpl extends BaseServiceImpl<DmDeviceLogFileQuery, DmDeviceLogFileDto, IDmDeviceLogFileManager> implements IDmDeviceLogFileService { | |||
| /** | |||
| * 查询日志文件信息记录对象列表 | 数据权限 | |||
| * | |||
| * @param deviceLogFile 日志文件信息记录对象 | |||
| * @return 日志文件信息记录对象集合 | |||
| */ | |||
| @Override | |||
| //@DataScope(userAlias = "createBy", mapperScope = {"DmDeviceLogFileMapper"}) | |||
| public List<DmDeviceLogFileDto> selectListScope(DmDeviceLogFileQuery deviceLogFile) { | |||
| return baseManager.selectList(deviceLogFile); | |||
| } | |||
| } | |||
| @@ -0,0 +1,54 @@ | |||
| package com.xueyi.system.emcs.service.impl; | |||
| import com.xueyi.common.web.entity.service.impl.BaseServiceImpl; | |||
| import com.xueyi.system.api.organize.domain.dto.SysEnterpriseDto; | |||
| import com.xueyi.system.emcs.domain.dto.DmExceptionLogDto; | |||
| import com.xueyi.system.emcs.domain.query.DmExceptionLogQuery; | |||
| import com.xueyi.system.emcs.manager.IDmExceptionLogManager; | |||
| import com.xueyi.system.emcs.service.IDmExceptionLogService; | |||
| import com.xueyi.system.organize.service.ISysEnterpriseService; | |||
| import org.springframework.beans.factory.annotation.Autowired; | |||
| import org.springframework.stereotype.Service; | |||
| import java.util.List; | |||
| /** | |||
| * 数字人状态事件上报日志管理 服务层处理 | |||
| * | |||
| * @author xueyi | |||
| */ | |||
| @Service | |||
| public class DmExceptionLogServiceImpl extends BaseServiceImpl<DmExceptionLogQuery, DmExceptionLogDto, IDmExceptionLogManager> implements IDmExceptionLogService { | |||
| @Autowired | |||
| private ISysEnterpriseService enterpriseService; | |||
| /** | |||
| * 查询数字人状态事件上报日志对象列表 | 数据权限 | |||
| * | |||
| * @param exceptionLog 数字人状态事件上报日志对象 | |||
| * @return 数字人状态事件上报日志对象集合 | |||
| */ | |||
| @Override | |||
| //@DataScope(userAlias = "createBy", mapperScope = {"DmExceptionLogMapper"}) | |||
| public List<DmExceptionLogDto> selectListScope(DmExceptionLogQuery exceptionLog) { | |||
| List<DmExceptionLogDto> exceptionLogDtos = baseManager.selectList(exceptionLog); | |||
| exceptionLogDtos.forEach(dto->{ | |||
| Long tId = dto.getTId(); | |||
| if (tId!= null) { | |||
| SysEnterpriseDto enterpriseDto = enterpriseService.selectById(tId); | |||
| dto.setTenantName(enterpriseDto.getName()); | |||
| } | |||
| }); | |||
| return exceptionLogDtos; | |||
| } | |||
| @Override | |||
| public List<DmExceptionLogDto> selectListRangeByCreateTime(String start,String end) { | |||
| return super.baseManager.selectListRangeByCreateTime(start,end); | |||
| } | |||
| @Override | |||
| public List<DmExceptionLogDto> selectListRangeByCreateTimeAndDevId(String start, String end, String devId) { | |||
| return super.baseManager.selectListRangeByCreateTimeAndDevId(start, end, devId); | |||
| } | |||
| } | |||
| @@ -1,159 +0,0 @@ | |||
| package com.xueyi.system.exception.controller; | |||
| import com.alibaba.fastjson2.JSONObject; | |||
| import com.xueyi.common.core.web.result.AjaxResult; | |||
| import com.xueyi.common.core.web.validate.V_A; | |||
| import com.xueyi.common.core.web.validate.V_E; | |||
| import com.xueyi.common.log.annotation.Log; | |||
| import com.xueyi.common.log.enums.BusinessType; | |||
| import com.xueyi.common.mqtt.configure.MqttConfig; | |||
| import com.xueyi.common.mqtt.service.MqttMessageHandlerService; | |||
| import com.xueyi.common.mqtt.service.MqttService; | |||
| import com.xueyi.common.security.annotation.RequiresPermissions; | |||
| import com.xueyi.common.web.entity.controller.BaseController; | |||
| import com.xueyi.system.exception.domain.dto.DmExceptionLogDto; | |||
| import com.xueyi.system.exception.domain.query.DmExceptionLogQuery; | |||
| import com.xueyi.system.exception.service.IDmExceptionLogService; | |||
| import com.xueyi.system.exception.service.LogMqttMessageHandler; | |||
| import org.eclipse.paho.client.mqttv3.MqttException; | |||
| import org.springframework.beans.factory.annotation.Autowired; | |||
| import org.springframework.validation.annotation.Validated; | |||
| import org.springframework.web.bind.annotation.DeleteMapping; | |||
| import org.springframework.web.bind.annotation.GetMapping; | |||
| import org.springframework.web.bind.annotation.PathVariable; | |||
| import org.springframework.web.bind.annotation.PostMapping; | |||
| import org.springframework.web.bind.annotation.PutMapping; | |||
| import org.springframework.web.bind.annotation.RequestBody; | |||
| import org.springframework.web.bind.annotation.RequestMapping; | |||
| import org.springframework.web.bind.annotation.RestController; | |||
| import javax.annotation.PostConstruct; | |||
| import java.io.Serializable; | |||
| import java.util.List; | |||
| /** | |||
| * 数字人状态事件上报日志管理 业务处理 | |||
| * | |||
| * @author xueyi | |||
| */ | |||
| @RestController | |||
| @RequestMapping("/log") | |||
| public class DmExceptionLogController extends BaseController<DmExceptionLogQuery, DmExceptionLogDto, IDmExceptionLogService> { | |||
| @Autowired | |||
| private MqttService mqttService; | |||
| @Autowired | |||
| private LogMqttMessageHandler logMqttMessageHandler; | |||
| @Autowired | |||
| private MqttConfig mqttConfig; | |||
| /** 定义节点名称 */ | |||
| @Override | |||
| protected String getNodeName() { | |||
| return "数字人状态事件上报日志" ; | |||
| } | |||
| @PostConstruct | |||
| private void init() { | |||
| System.err.println(System.nanoTime()+"-------heelo"); | |||
| MqttMessageHandlerService mqttMessageHandlerService = new MqttMessageHandlerService(mqttService, logMqttMessageHandler); | |||
| } | |||
| /** | |||
| * 查询数字人状态事件上报日志列表 | |||
| */ | |||
| @Override | |||
| @GetMapping("/list") | |||
| @RequiresPermissions(Auth.DM_EXCEPTION_LOG_LIST) | |||
| public AjaxResult list(DmExceptionLogQuery exceptionLog) { | |||
| return super.list(exceptionLog); | |||
| } | |||
| /** | |||
| * 查询数字人状态事件上报日志详细 | |||
| */ | |||
| @Override | |||
| @GetMapping(value = "/{id}") | |||
| @RequiresPermissions(Auth.DM_EXCEPTION_LOG_SINGLE) | |||
| public AjaxResult getInfo(@PathVariable Serializable id) { | |||
| return super.getInfo(id); | |||
| } | |||
| /** | |||
| * 数字人状态事件上报日志新增 | |||
| */ | |||
| @Override | |||
| @PostMapping | |||
| @RequiresPermissions(Auth.DM_EXCEPTION_LOG_ADD) | |||
| @Log(title = "数字人状态事件上报日志管理", businessType = BusinessType.INSERT) | |||
| public AjaxResult add(@Validated({V_A.class}) @RequestBody DmExceptionLogDto exceptionLog) { | |||
| return super.add(exceptionLog); | |||
| } | |||
| /** | |||
| * 数字人状态事件上报日志修改 | |||
| */ | |||
| @Override | |||
| @PutMapping | |||
| @RequiresPermissions(Auth.DM_EXCEPTION_LOG_EDIT) | |||
| @Log(title = "数字人状态事件上报日志管理", businessType = BusinessType.UPDATE) | |||
| public AjaxResult edit(@Validated({V_E.class}) @RequestBody DmExceptionLogDto exceptionLog) { | |||
| return super.edit(exceptionLog); | |||
| } | |||
| /** | |||
| * 数字人状态事件上报日志批量删除 | |||
| */ | |||
| @Override | |||
| @DeleteMapping("/batch/{idList}") | |||
| @RequiresPermissions(Auth.DM_EXCEPTION_LOG_DEL) | |||
| @Log(title = "数字人状态事件上报日志管理", businessType = BusinessType.DELETE) | |||
| public AjaxResult batchRemove(@PathVariable List<Long> idList) { | |||
| return super.batchRemove(idList); | |||
| } | |||
| /* | |||
| * @Author yangkai | |||
| * @Description //主动拉取日志操作 | |||
| * @Date 2023/5/10 | |||
| * @Param [devId, uploadType] | |||
| * @return com.xueyi.common.core.web.result.AjaxResult | |||
| **/ | |||
| @PostMapping("/fetch-log") | |||
| public AjaxResult sendMqttMsgToDev(@RequestBody JSONObject json){ | |||
| JSONObject jsonObject = new JSONObject(); | |||
| jsonObject.put("device_id", "12345"); | |||
| try { | |||
| mqttService.sendMessage(mqttConfig.getFetchLogTopic(), jsonObject.toJSONString()); | |||
| } catch (MqttException e) { | |||
| e.printStackTrace(); | |||
| return error(e.getMessage()); | |||
| } | |||
| return success("操作成功"); | |||
| } | |||
| /** | |||
| * 获取数字人状态事件上报日志选择框列表 | |||
| */ | |||
| @Override | |||
| @GetMapping("/option") | |||
| public AjaxResult option() { | |||
| return super.option(); | |||
| } | |||
| interface Auth { | |||
| /** 系统 - 数字人状态事件上报日志管理 - 列表 */ | |||
| String DM_EXCEPTION_LOG_LIST = "log:log:list"; | |||
| /** 系统 - 数字人状态事件上报日志管理 - 详情 */ | |||
| String DM_EXCEPTION_LOG_SINGLE = "log:log:single"; | |||
| /** 系统 - 数字人状态事件上报日志管理 - 新增 */ | |||
| String DM_EXCEPTION_LOG_ADD = "log:log:add"; | |||
| /** 系统 - 数字人状态事件上报日志管理 - 修改 */ | |||
| String DM_EXCEPTION_LOG_EDIT = "log:log:edit"; | |||
| /** 系统 - 数字人状态事件上报日志管理 - 删除 */ | |||
| String DM_EXCEPTION_LOG_DEL = "log:log:delete"; | |||
| } | |||
| } | |||
| @@ -1,13 +0,0 @@ | |||
| package com.xueyi.system.exception.manager; | |||
| import com.xueyi.system.exception.domain.dto.DmExceptionLogDto; | |||
| import com.xueyi.system.exception.domain.query.DmExceptionLogQuery; | |||
| import com.xueyi.common.web.entity.manager.IBaseManager; | |||
| /** | |||
| * 数字人状态事件上报日志管理 数据封装层 | |||
| * | |||
| * @author xueyi | |||
| */ | |||
| public interface IDmExceptionLogManager extends IBaseManager<DmExceptionLogQuery, DmExceptionLogDto> { | |||
| } | |||
| @@ -1,19 +0,0 @@ | |||
| package com.xueyi.system.exception.manager.impl; | |||
| import com.xueyi.common.web.entity.manager.impl.BaseManagerImpl; | |||
| import com.xueyi.system.exception.domain.dto.DmExceptionLogDto; | |||
| import com.xueyi.system.exception.domain.model.DmExceptionLogConverter; | |||
| import com.xueyi.system.exception.domain.po.DmExceptionLogPo; | |||
| import com.xueyi.system.exception.domain.query.DmExceptionLogQuery; | |||
| import com.xueyi.system.exception.manager.IDmExceptionLogManager; | |||
| import com.xueyi.system.exception.mapper.DmExceptionLogMapper; | |||
| import org.springframework.stereotype.Component; | |||
| /** | |||
| * 数字人状态事件上报日志管理 数据封装层处理 | |||
| * | |||
| * @author xueyi | |||
| */ | |||
| @Component | |||
| public class DmExceptionLogManager extends BaseManagerImpl<DmExceptionLogQuery, DmExceptionLogDto, DmExceptionLogPo, DmExceptionLogMapper, DmExceptionLogConverter> implements IDmExceptionLogManager { | |||
| } | |||
| @@ -1,13 +0,0 @@ | |||
| package com.xueyi.system.exception.service; | |||
| import com.xueyi.system.exception.domain.query.DmExceptionLogQuery; | |||
| import com.xueyi.system.exception.domain.dto.DmExceptionLogDto; | |||
| import com.xueyi.common.web.entity.service.IBaseService; | |||
| /** | |||
| * 数字人状态事件上报日志管理 服务层 | |||
| * | |||
| * @author xueyi | |||
| */ | |||
| public interface IDmExceptionLogService extends IBaseService<DmExceptionLogQuery, DmExceptionLogDto> { | |||
| } | |||
| @@ -1,19 +0,0 @@ | |||
| package com.xueyi.system.exception.service; | |||
| import com.xueyi.common.mqtt.service.MqttMessageHandler; | |||
| import org.springframework.stereotype.Service; | |||
| /** | |||
| * @author yk | |||
| * @description | |||
| * @date 2023-05-10 19:08 | |||
| */ | |||
| @Service | |||
| public class LogMqttMessageHandler implements MqttMessageHandler { | |||
| @Override | |||
| public void handleMessage(String topic, String message) { | |||
| // 处理消息的业务逻辑 | |||
| System.out.println("收到主题eee:" + topic + ",消息内容eee:" + message); | |||
| } | |||
| } | |||
| @@ -1,32 +0,0 @@ | |||
| package com.xueyi.system.exception.service.impl; | |||
| import com.xueyi.system.exception.domain.dto.DmExceptionLogDto; | |||
| import com.xueyi.system.exception.domain.query.DmExceptionLogQuery; | |||
| import com.xueyi.system.exception.service.IDmExceptionLogService; | |||
| import com.xueyi.system.exception.manager.IDmExceptionLogManager; | |||
| import com.xueyi.common.web.entity.service.impl.BaseServiceImpl; | |||
| import org.springframework.stereotype.Service; | |||
| import java.util.List; | |||
| /** | |||
| * 数字人状态事件上报日志管理 服务层处理 | |||
| * | |||
| * @author xueyi | |||
| */ | |||
| @Service | |||
| public class DmExceptionLogServiceImpl extends BaseServiceImpl<DmExceptionLogQuery, DmExceptionLogDto, IDmExceptionLogManager> implements IDmExceptionLogService { | |||
| /** | |||
| * 查询数字人状态事件上报日志对象列表 | 数据权限 | |||
| * | |||
| * @param exceptionLog 数字人状态事件上报日志对象 | |||
| * @return 数字人状态事件上报日志对象集合 | |||
| */ | |||
| @Override | |||
| //@DataScope(userAlias = "createBy", mapperScope = {"DmExceptionLogMapper"}) | |||
| public List<DmExceptionLogDto> selectListScope(DmExceptionLogQuery exceptionLog) { | |||
| return baseManager.selectList(exceptionLog); | |||
| } | |||
| } | |||
| @@ -99,6 +99,14 @@ public class DmMeetingApiController extends BaseApiController { | |||
| return remoteMeetingService.listsInner(dateStr, spaceId, vo.getTenantId(),vo.getSourceSlave(),SecurityConstants.INNER); | |||
| } | |||
| @ResponseBody | |||
| @GetMapping(value = "/lists/{devId}") | |||
| public JSONObject listAll(@PathVariable(required = true) String devId) { | |||
| DeviceTenantSourceMergeVo vo = super.getDeviceTenantSourceMergeVo(devId); | |||
| return remoteMeetingService.listsAllInner(vo.getTenantId(),vo.getSourceSlave(),SecurityConstants.INNER); | |||
| } | |||
| @ResponseBody | |||
| @PostMapping(value = "/date-lists") | |||
| @@ -108,6 +116,15 @@ public class DmMeetingApiController extends BaseApiController { | |||
| return remoteMeetingService.listsByDate(dateStr, vo.getTenantId(),vo.getSourceSlave(),SecurityConstants.INNER); | |||
| } | |||
| @ResponseBody | |||
| @PostMapping(value = "/lists-all") | |||
| public JSONObject listAfter(String dateStr, Long spaceId, String devId) { | |||
| DeviceTenantSourceMergeVo vo = super.getDeviceTenantSourceMergeVo(devId); | |||
| return remoteMeetingService.listAllInner(dateStr, spaceId, vo.getTenantId(),vo.getSourceSlave(),SecurityConstants.INNER); | |||
| } | |||
| @Autowired | |||
| private RemoteRecognizedRecordsService recognizedRecordsService; | |||
| @@ -102,6 +102,11 @@ public class DmMeetingInnerApiController extends BaseApiController { | |||
| StringBuilder mms = new StringBuilder(); | |||
| SimpleDateFormat dateFormat1 = new SimpleDateFormat("yyyy-MM-dd"); | |||
| SimpleDateFormat dateFormat2 = new SimpleDateFormat("HH:mm"); | |||
| DmMeetingRoomsPo meetingRoom = dmMeetingRoomsService.selectById(order.getSpaceId().toString()); | |||
| if (null == meetingRoom){ | |||
| return output(ResponseCode.ILLEGAL_PARAMETER, "spaceId").toJSON(); | |||
| } | |||
| for (Object js : jsonArray) { | |||
| JSONObject temp = (JSONObject) js; | |||
| String date = temp.getString("date"); | |||
| @@ -135,7 +140,7 @@ public class DmMeetingInnerApiController extends BaseApiController { | |||
| } | |||
| dmMeetingOrdersMapper.insertBatch(list); | |||
| DmMeetingRoomsPo meetingRoom = dmMeetingRoomsService.selectById(order.getSpaceId().toString()); | |||
| mms.append(mms.substring(0, mms.length() - 1) + "于" + meetingRoom.getName()); | |||
| DmStaffPo dmStaffPo = dmStaffMapper.selectById(order.getOrderBy()); | |||
| @@ -222,12 +227,13 @@ public class DmMeetingInnerApiController extends BaseApiController { | |||
| List<DmMeetingOrdersPo> list = dmMeetingOrdersMapper.findListByDateStr(dateStr); | |||
| List<DmMeetingOrdersDto> res = new ArrayList<>(); | |||
| list.forEach(item -> { | |||
| DmMeetingOrdersDto dto = dmMeetingOrdersConverter.mapperDto(item); | |||
| DmMeetingRoomsPo mr = dmMeetingRoomsMapper.findById(item.getSpaceId()); | |||
| dto.setRoomName(mr.getName()); | |||
| dmMeetingOrdersService.fixColumns(dto); | |||
| res.add(dto); | |||
| if (null != mr) { | |||
| DmMeetingOrdersDto dto = dmMeetingOrdersConverter.mapperDto(item); | |||
| dto.setRoomName(mr.getName()); | |||
| dmMeetingOrdersService.fixColumns(dto); | |||
| res.add(dto); | |||
| } | |||
| }); | |||
| return outputSuccess(res).toJSON(); | |||
| } | |||
| @@ -246,4 +252,35 @@ public class DmMeetingInnerApiController extends BaseApiController { | |||
| return outputSuccess(res).toJSON(); | |||
| } | |||
| @InnerAuth | |||
| @PostMapping(value = "/lists-all") | |||
| public JSONObject listAllInner(@RequestParam("dateStr") String dateStr, @RequestParam("spaceId") Long spaceId) { | |||
| String date = dateStr.substring(0, 10); | |||
| String time = dateStr.substring(11); | |||
| System.err.println("date:"+date+"; time:"+time+";spaceId:"+spaceId); | |||
| List<DmMeetingOrdersPo> list = dmMeetingOrdersMapper.findAllListByDate(date,time, spaceId); | |||
| List<DmMeetingOrdersDto> res = new ArrayList<>(); | |||
| list.forEach(item -> { | |||
| DmMeetingOrdersDto dto = dmMeetingOrdersConverter.mapperDto(item); | |||
| dmMeetingOrdersService.fixColumns(dto); | |||
| res.add(dto); | |||
| }); | |||
| return outputSuccess(res).toJSON(); | |||
| } | |||
| @InnerAuth | |||
| @GetMapping(value = "/lists") | |||
| public JSONObject listAllInner() { | |||
| List<DmMeetingOrdersPo> list = dmMeetingOrdersMapper.findAllList(); | |||
| List<DmMeetingOrdersDto> res = new ArrayList<>(); | |||
| list.forEach(item -> { | |||
| DmMeetingOrdersDto dto = dmMeetingOrdersConverter.mapperDto(item); | |||
| DmMeetingRoomsPo mr = dmMeetingRoomsMapper.findById(dto.getSpaceId()); | |||
| dto.setRoomName(mr.getName()); | |||
| dmMeetingOrdersService.fixColumns(dto); | |||
| res.add(dto); | |||
| }); | |||
| return outputSuccess(res).toJSON(); | |||
| } | |||
| } | |||
| @@ -21,5 +21,9 @@ public interface DmMeetingOrdersMapper extends BaseMapper<DmMeetingOrdersQuery, | |||
| DmMeetingOrdersPo findLastByEmpId(@Param("empId") Long empId); | |||
| List<DmMeetingOrdersPo> findListByDate(@Param("orderDate") String orderDate, @Param("spaceId") Long spaceId); | |||
| List<DmMeetingOrdersPo> findAllListByDate(@Param("date") String date, @Param("time") String time, @Param("spaceId") Long spaceId); | |||
| List<DmMeetingOrdersPo> findAllList(); | |||
| List<DmMeetingOrdersPo> findListByDateStr(@Param("orderDate") String orderDate); | |||
| } | |||
| @@ -6,10 +6,15 @@ import com.xueyi.common.security.annotation.Logical; | |||
| import com.xueyi.common.security.annotation.RequiresPermissions; | |||
| import com.xueyi.common.security.auth.Auth; | |||
| import com.xueyi.common.web.entity.controller.BasisController; | |||
| import com.xueyi.system.organize.domain.vo.SysDeptExt; | |||
| import com.xueyi.system.api.organize.domain.vo.SysDeptExt; | |||
| import com.xueyi.system.organize.service.ISysOrganizeService; | |||
| import org.springframework.beans.factory.annotation.Autowired; | |||
| import org.springframework.web.bind.annotation.*; | |||
| import org.springframework.web.bind.annotation.GetMapping; | |||
| import org.springframework.web.bind.annotation.PathVariable; | |||
| 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; | |||
| /** | |||
| * 组织管理 业务处理 | |||
| @@ -21,19 +21,19 @@ public class SysDeptExtPo extends TBaseEntity { | |||
| private Long deptId; | |||
| /** 工作日上班时间 */ | |||
| @Excel(name = "工作日上班时间") | |||
| protected String workdayHourStart; | |||
| /** 上班打卡开始时间 */ | |||
| @Excel(name = "上班打卡开始时间") | |||
| protected String onDutyHourStart; | |||
| /** 工作日下班时间 */ | |||
| @Excel(name = "工作日下班时间") | |||
| protected String workdayHourEnd; | |||
| /** 上班打卡结束时间 */ | |||
| @Excel(name = "上班打卡结束时间") | |||
| protected String onDutyHourEnd; | |||
| /** 休息日上班时间 */ | |||
| @Excel(name = "休息日上班时间") | |||
| protected String weekendHourStart; | |||
| /** 下班打卡开始时间 */ | |||
| @Excel(name = "下班打卡开始时间") | |||
| protected String offDutyHourStart; | |||
| /** 休息日下班时间 */ | |||
| @Excel(name = "休息日下班时间") | |||
| protected String weekendHourEnd; | |||
| /** 下班打卡结束时间 */ | |||
| @Excel(name = "下班打卡结束时间") | |||
| protected String offDutyHourEnd; | |||
| } | |||
| @@ -1,26 +0,0 @@ | |||
| package com.xueyi.system.organize.domain.vo; | |||
| import lombok.Data; | |||
| import lombok.NoArgsConstructor; | |||
| @Data | |||
| @NoArgsConstructor | |||
| public class SysDeptExt { | |||
| /** Id */ | |||
| private Long deptId; | |||
| /** Id */ | |||
| private String workdayHourStart; | |||
| /** Id */ | |||
| private String workdayHourEnd; | |||
| /** Id */ | |||
| private String weekendHourStart; | |||
| /** Id */ | |||
| private String weekendHourEnd; | |||
| } | |||
| @@ -1,6 +1,6 @@ | |||
| package com.xueyi.system.organize.manager; | |||
| import com.xueyi.system.organize.domain.vo.SysDeptExt; | |||
| import com.xueyi.system.api.organize.domain.vo.SysDeptExt; | |||
| import com.xueyi.system.organize.domain.vo.SysOrganizeTree; | |||
| import java.util.Collection; | |||
| @@ -6,11 +6,11 @@ import com.xueyi.common.core.utils.core.ArrayUtil; | |||
| import com.xueyi.common.core.utils.core.CollUtil; | |||
| import com.xueyi.system.api.organize.domain.dto.SysDeptDto; | |||
| import com.xueyi.system.api.organize.domain.dto.SysPostDto; | |||
| import com.xueyi.system.api.organize.domain.vo.SysDeptExt; | |||
| import com.xueyi.system.organize.domain.merge.SysOrganizeRoleMerge; | |||
| import com.xueyi.system.organize.domain.merge.SysRoleDeptMerge; | |||
| import com.xueyi.system.organize.domain.merge.SysRolePostMerge; | |||
| import com.xueyi.system.organize.domain.merge.SysUserPostMerge; | |||
| import com.xueyi.system.organize.domain.vo.SysDeptExt; | |||
| import com.xueyi.system.organize.domain.vo.SysOrganizeTree; | |||
| import com.xueyi.system.organize.manager.ISysDeptManager; | |||
| import com.xueyi.system.organize.manager.ISysOrganizeManager; | |||
| @@ -23,7 +23,12 @@ import com.xueyi.system.organize.mapper.merge.SysUserPostMergeMapper; | |||
| import org.springframework.beans.factory.annotation.Autowired; | |||
| import org.springframework.stereotype.Component; | |||
| import java.util.*; | |||
| import java.util.ArrayList; | |||
| import java.util.Arrays; | |||
| import java.util.Collection; | |||
| import java.util.HashSet; | |||
| import java.util.List; | |||
| import java.util.Set; | |||
| import java.util.stream.Collectors; | |||
| /** | |||