diff --git a/pom.xml b/pom.xml index 12a8bae..642b6a3 100644 --- a/pom.xml +++ b/pom.xml @@ -221,6 +221,22 @@ spring-boot-starter-websocket + + com.tencentcloudapi + tencentcloud-sdk-java + 3.1.322 + + + + org.springframework.boot + spring-boot-starter-cache + + + + net.sf.ehcache + ehcache + + diff --git a/src/main/java/com/subsidy/MeishuApplication.java b/src/main/java/com/subsidy/MeishuApplication.java index f94c800..1a151d9 100644 --- a/src/main/java/com/subsidy/MeishuApplication.java +++ b/src/main/java/com/subsidy/MeishuApplication.java @@ -3,6 +3,7 @@ package com.subsidy; import org.mybatis.spring.annotation.MapperScan; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.cache.annotation.EnableCaching; import org.springframework.scheduling.annotation.EnableAsync; import org.springframework.scheduling.annotation.EnableScheduling; import org.springframework.web.bind.annotation.RestController; @@ -11,6 +12,7 @@ import org.springframework.web.bind.annotation.RestController; @SpringBootApplication @MapperScan(basePackages = {"com.subsidy.mapper"}) @EnableScheduling +@EnableCaching @EnableAsync public class MeishuApplication { diff --git a/src/main/java/com/subsidy/common/constant/VodConstant.java b/src/main/java/com/subsidy/common/constant/VodConstant.java new file mode 100644 index 0000000..12fe119 --- /dev/null +++ b/src/main/java/com/subsidy/common/constant/VodConstant.java @@ -0,0 +1,31 @@ +package com.subsidy.common.constant; + +import lombok.Getter; + +@Getter +public class VodConstant { + + /* 流量 */ + public final static String FLUX = "Flux"; + + /* 带宽 */ + public final static String BANDWIDTH = "Bandwidth"; + + /* 请求数 */ + public final static String REQUESTS = "Requests"; + + /* 请求命中率 */ + public final static String HITRATE = "Hitrate"; + + /* IP访问次数 */ + public final static String IP_VISITS = "Ip_visits"; + + /* 带宽缓存key */ + public final static String BANDWIDTH_CACHE_KEY = "CDNStatBandwidthCache"; + + /* 流量缓存key */ + public final static String FLUX_CACHE_KEY = "CDNStatFluxCache"; + + /* 自定义缓存名称(ehcache.xml中的自定义规则名称) */ + public final static String CDN_STAT_DETAILS_CACHE_NAME = "CDNStatDetails"; +} diff --git a/src/main/java/com/subsidy/dto/company/DataOverviewDTO.java b/src/main/java/com/subsidy/dto/company/DataOverviewDTO.java new file mode 100644 index 0000000..cc7a7f8 --- /dev/null +++ b/src/main/java/com/subsidy/dto/company/DataOverviewDTO.java @@ -0,0 +1,9 @@ +package com.subsidy.dto.company; + +import lombok.Data; + +@Data +public class DataOverviewDTO { + + private Long companyId; +} diff --git a/src/main/java/com/subsidy/mapper/ClassDictMapper.java b/src/main/java/com/subsidy/mapper/ClassDictMapper.java index b33a537..32d2680 100644 --- a/src/main/java/com/subsidy/mapper/ClassDictMapper.java +++ b/src/main/java/com/subsidy/mapper/ClassDictMapper.java @@ -53,4 +53,6 @@ public interface ClassDictMapper extends BaseMapper { * 班级信息 -- 获取课程信息 + 公司信息 * */ ClassAndCompanyInfoVO getClassAndCompanyInfoVO(Long classId); + + Integer getClassCount(); } diff --git a/src/main/java/com/subsidy/mapper/VodPlayHistoryMapper.java b/src/main/java/com/subsidy/mapper/VodPlayHistoryMapper.java index 815deb6..32d52f5 100644 --- a/src/main/java/com/subsidy/mapper/VodPlayHistoryMapper.java +++ b/src/main/java/com/subsidy/mapper/VodPlayHistoryMapper.java @@ -97,4 +97,9 @@ public interface VodPlayHistoryMapper extends BaseMapper { List getVodPlayDay(Long classId, Long memberId, Date endDate); + double getStudyTotal(); + + double getSubsidyStudyTotal(); + + int getStudyHistoryNum(); } diff --git a/src/main/java/com/subsidy/service/CompanyDictService.java b/src/main/java/com/subsidy/service/CompanyDictService.java index de47137..44d817a 100644 --- a/src/main/java/com/subsidy/service/CompanyDictService.java +++ b/src/main/java/com/subsidy/service/CompanyDictService.java @@ -6,8 +6,9 @@ import com.subsidy.dto.administer.OperatorsDTO; import com.subsidy.dto.company.AddCompanyDTO; import com.subsidy.dto.company.GetCompanyMembersDTO; import com.subsidy.model.CompanyDictDO; -import com.subsidy.model.MemberDO; import com.subsidy.vo.administer.OperatorsVO; +import com.subsidy.vo.company.CDNStatDetailsVO; +import com.subsidy.vo.company.DataOverviewVO; import com.subsidy.vo.company.GetAllCompanyVO; import com.subsidy.vo.company.GetCompanyMembersVO; import com.subsidy.vo.company.MemberSummaryVO; @@ -38,4 +39,9 @@ public interface CompanyDictService extends IService { MemberSummaryVO memberSummary(GetCompanyMembersDTO getCompanyMembersDTO); + DataOverviewVO getCompanyDataOverview(); + + List getCDNBandwidthStatDetails(); + + List getCDNFluxStatDetails(); } diff --git a/src/main/java/com/subsidy/service/impl/AdministerServiceImpl.java b/src/main/java/com/subsidy/service/impl/AdministerServiceImpl.java index 7a16a08..3dd0bb7 100644 --- a/src/main/java/com/subsidy/service/impl/AdministerServiceImpl.java +++ b/src/main/java/com/subsidy/service/impl/AdministerServiceImpl.java @@ -44,7 +44,6 @@ import com.subsidy.model.MemberDepartmentMappingDO; import com.subsidy.model.OprAdmDictDO; import com.subsidy.model.PaperDictDO; import com.subsidy.model.RoleAdministerMappingDO; -import com.subsidy.model.RoleDictDO; import com.subsidy.model.SignInRecordDO; import com.subsidy.model.VodDictDO; import com.subsidy.service.AdministerService; @@ -86,12 +85,12 @@ import org.apache.poi.xssf.streaming.SXSSFWorkbook; import org.apache.poi.xssf.usermodel.XSSFWorkbook; import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.cache.annotation.Cacheable; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.ServletRequestAttributes; import org.springframework.web.multipart.MultipartFile; - import javax.servlet.ServletOutputStream; import javax.servlet.http.HttpServletResponse; import java.io.BufferedInputStream; @@ -115,7 +114,6 @@ import java.util.concurrent.atomic.AtomicInteger; import java.util.zip.ZipEntry; import java.util.zip.ZipOutputStream; - /** *

* 管理平台用户 服务实现类 @@ -175,9 +173,6 @@ public class AdministerServiceImpl extends ServiceImpl operators(OperatorsDTO operatorsDTO) { Page pager = new Page(operatorsDTO.getPageNum(), operatorsDTO.getPageSize()); @@ -252,6 +288,55 @@ public class CompanyDictServiceImpl extends ServiceImpl()); + /* 机构数量 */ + dataOverviewVO.setCompanyNum(companyNum); + + List memberList = memberMapper.selectList(new QueryWrapper<>()); + if(CollectionUtils.isNotEmpty(memberList)) { + int realNameNum = (int) memberList.stream().filter(m -> StringUtils.isNotBlank(m.getIdCard())).count(); + /* 注册人数 */ + dataOverviewVO.setRegistrantsNum(memberList.size()); + /* 实名注册人数 */ + dataOverviewVO.setRealNameNum(realNameNum); + } + + /* 培训项目数量 */ + int classNum = classDictMapper.getClassCount(); + dataOverviewVO.setClassNum(classNum); + + List courseList = courseDictMapper.selectList(new QueryWrapper<>()); + if(CollectionUtils.isNotEmpty(courseList)) { + /* 资源数量 */ + dataOverviewVO.setCourseNum(courseList.size()); + + /* 专项资源数量 */ + int subsidyCourseNum = (int) courseList.stream().filter(courseDictDO -> StringUtils.isNotBlank(courseDictDO.getCourseType()) && + courseDictDO.getCourseType().equals("补贴培训")).count(); + dataOverviewVO.setSubsidyCourseNum(subsidyCourseNum); + } + + /* 累计学习时长(小时) */ + double studyTotal = vodPlayHistoryMapper.getStudyTotal(); + if(studyTotal > 0) { + dataOverviewVO.setStudyTotal(new BigDecimal(studyTotal).divide(new BigDecimal(Math.pow(60, 2)), 2, BigDecimal.ROUND_UP).doubleValue()); + } + + /* 专项资源时(小时) */ + double subsidyStudyTotal = vodPlayHistoryMapper.getSubsidyStudyTotal(); + if(subsidyStudyTotal > 0) { + dataOverviewVO.setSubsidyStudyTotal(new BigDecimal(subsidyStudyTotal).divide(new BigDecimal(Math.pow(60,2)), 2, BigDecimal.ROUND_UP).doubleValue()); + } + + /* 学习过程记录人次 */ + int studyHistoryNum = vodPlayHistoryMapper.getStudyHistoryNum(); + dataOverviewVO.setStudyHistoryNum(studyHistoryNum); + return dataOverviewVO; + } + public MemberSummaryVO memberSummary(GetCompanyMembersDTO getCompanyMembersDTO){ MemberSummaryVO memberSummaryVO = new MemberSummaryVO(); @@ -273,4 +358,59 @@ public class CompanyDictServiceImpl extends ServiceImpl getCDNBandwidthStatDetails() { + /* + * 根据今天时间查询七天前的数据 + * 先从缓存中获取数据,如果缓存中没有数据,从远程请求中获取, 避免频繁请求 + * 缓存28800秒(8小时)失效,重新远程请求更新数据 + */ + List data = new ArrayList<>(); + if(EhCacheUtil.getEhCache(VodConstant.CDN_STAT_DETAILS_CACHE_NAME, VodConstant.BANDWIDTH_CACHE_KEY) != null) { + return (List) EhCacheUtil.getEhCache(VodConstant.CDN_STAT_DETAILS_CACHE_NAME, VodConstant.BANDWIDTH_CACHE_KEY); + } else { + String startDate =LocalDateTime.now().minusDays(6).withNano(0)+"+08:00"; + String endDate = LocalDateTime.now().withNano(0)+"+08:00"; + StatDataItem[] statDataItems = VodUtil.DescribeCDNStatDetails(vodConfig, VodConstant.BANDWIDTH ,startDate, endDate); + for (StatDataItem statDataItem : statDataItems) { + CDNStatDetailsVO sd = new CDNStatDetailsVO(); + LocalDateTime localDateTime = LocalDateTime.parse(statDataItem.getTime().replace("+08:00","")); + Date date = DateFormatUtil.localDateTimeToDate(localDateTime); + sd.setTime(DateFormatUtil.format(date, DateFormatUtil.FMT_sdf_yMd)); + BigDecimal bigDecimal = new BigDecimal(statDataItem.getValue()).divide(new BigDecimal(1000000)); + sd.setValue(bigDecimal.setScale(2, BigDecimal.ROUND_UP)); + data.add(sd); + } + EhCacheUtil.putEhCache(VodConstant.CDN_STAT_DETAILS_CACHE_NAME, VodConstant.BANDWIDTH_CACHE_KEY, data); + return data; + } + } + + @Override + public List getCDNFluxStatDetails() { + /* + * 根据今天时间查询七天前的数据 + * 先从缓存中获取数据,如果缓存中没有数据,从远程请求中获取,避免频繁请求 + * 缓存28800秒(8小时)失效,重新远程请求更新数据 + */ + List data = new ArrayList<>(); + if(EhCacheUtil.getEhCache(VodConstant.CDN_STAT_DETAILS_CACHE_NAME, VodConstant.FLUX_CACHE_KEY) != null) { + return (List) EhCacheUtil.getEhCache(VodConstant.CDN_STAT_DETAILS_CACHE_NAME, VodConstant.FLUX_CACHE_KEY); + } else { + String startDate =LocalDateTime.now().minusDays(6).withNano(0)+"+08:00"; + String endDate = LocalDateTime.now().withNano(0)+"+08:00"; + StatDataItem[] statDataItems = VodUtil.DescribeCDNStatDetails(vodConfig, VodConstant.FLUX ,startDate, endDate); + for (StatDataItem statDataItem : statDataItems) { + CDNStatDetailsVO sd = new CDNStatDetailsVO(); + LocalDateTime localDateTime = LocalDateTime.parse(statDataItem.getTime().replace("+08:00","")); + Date date = DateFormatUtil.localDateTimeToDate(localDateTime); + sd.setTime(DateFormatUtil.format(date, DateFormatUtil.FMT_sdf_yMd)); + BigDecimal bigDecimal = new BigDecimal(statDataItem.getValue()).divide(new BigDecimal(Math.pow(1000, 3))); + sd.setValue(bigDecimal.setScale(2, BigDecimal.ROUND_UP)); + data.add(sd); + } + EhCacheUtil.putEhCache(VodConstant.CDN_STAT_DETAILS_CACHE_NAME, VodConstant.FLUX_CACHE_KEY, data); + return data; + } + } } diff --git a/src/main/java/com/subsidy/service/impl/VodDictServiceImpl.java b/src/main/java/com/subsidy/service/impl/VodDictServiceImpl.java index efa8cd4..b8168e1 100644 --- a/src/main/java/com/subsidy/service/impl/VodDictServiceImpl.java +++ b/src/main/java/com/subsidy/service/impl/VodDictServiceImpl.java @@ -66,9 +66,9 @@ public class VodDictServiceImpl extends ServiceImpl im if(null == vod) { throw new HttpException(18000); } - this.baseMapper.deleteById(vodDictDO.getId()); - VodUtil.deleteMedia(vodDictDO.getVodCode()); + this.baseMapper.deleteById(vodDictDO.getId()); + VodUtil.deleteMedia(vodConfig, vodDictDO.getVodCode()); } @Override @@ -85,12 +85,13 @@ public class VodDictServiceImpl extends ServiceImpl im orderNo = vod.getOrderNo() + 1; } } + vodDictDO.setOrderNo(orderNo); this.baseMapper.insert(vodDictDO); //测试环境就不转码了 if (env.equals("prod")){ - VodUtil.processMedia(vodDictDO.getVodCode()); + VodUtil.processMedia(vodConfig, vodDictDO.getVodCode()); } } diff --git a/src/main/java/com/subsidy/util/EhCacheUtil.java b/src/main/java/com/subsidy/util/EhCacheUtil.java new file mode 100644 index 0000000..45dba17 --- /dev/null +++ b/src/main/java/com/subsidy/util/EhCacheUtil.java @@ -0,0 +1,53 @@ +package com.subsidy.util; + +import net.sf.ehcache.Cache; +import net.sf.ehcache.CacheManager; +import net.sf.ehcache.Element; +import org.springframework.util.ClassUtils; + +/** + *

+ * Ehcache + *

+ * + * @author DengMin + * @since 2022/8/1 + */ +public class EhCacheUtil { + + static CacheManager cacheManager = CacheManager.newInstance(ClassUtils.getDefaultClassLoader().getResource("").getPath()+"ehcache.xml"); + + /** + * 添加缓存 + * @param cacheName + * @param key + * @param value + */ + public static void putEhCache(String cacheName, String key, Object value) { + Cache cache = cacheManager.getCache(cacheName); + Element element = new Element(key, value); + cache.put(element); + } + + /** + * 获取缓存数据 + * @param cacheName + * @param key + * @return + */ + public static Object getEhCache(String cacheName, String key) { + Cache cache = cacheManager.getCache(cacheName); + Element element = cache.get(key); + return element == null ? null : element.getObjectValue(); + } + + /** + * 删除缓存 + * @param cacheName + * @param key + */ + public static void deleteEhCache(String cacheName, String key) { + Cache cache = cacheManager.getCache(cacheName); + cache.remove(key); + } +} diff --git a/src/main/java/com/subsidy/util/VodUtil.java b/src/main/java/com/subsidy/util/VodUtil.java index 9676482..79c3da0 100644 --- a/src/main/java/com/subsidy/util/VodUtil.java +++ b/src/main/java/com/subsidy/util/VodUtil.java @@ -6,21 +6,28 @@ import com.tencentcloudapi.common.Credential; import com.tencentcloudapi.common.exception.TencentCloudSDKException; import com.tencentcloudapi.common.profile.ClientProfile; import com.tencentcloudapi.common.profile.HttpProfile; -import com.tencentcloudapi.cvm.v20170312.models.DescribeZonesResponse; import com.tencentcloudapi.vod.v20180717.VodClient; import com.tencentcloudapi.vod.v20180717.models.DeleteMediaRequest; +import com.tencentcloudapi.vod.v20180717.models.DescribeCDNUsageDataRequest; +import com.tencentcloudapi.vod.v20180717.models.DescribeCDNUsageDataResponse; import com.tencentcloudapi.vod.v20180717.models.MediaProcessTaskInput; import com.tencentcloudapi.vod.v20180717.models.ProcessMediaRequest; import com.tencentcloudapi.vod.v20180717.models.ProcessMediaResponse; +import com.tencentcloudapi.vod.v20180717.models.StatDataItem; import com.tencentcloudapi.vod.v20180717.models.TranscodeTaskInput; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; +/** + *

+ * 腾讯云 - 云点播API + *

+ * + * @author DengMin + * @since 2022/8/1 + */ +@Component public class VodUtil { - @Autowired - private static VODConfig vodConfig; - private static String endpoint = "vod.tencentcloudapi.com"; /** @@ -28,7 +35,7 @@ public class VodUtil { * @param vodCode * @return */ - public static ProcessMediaResponse processMedia(String vodCode) { + public static ProcessMediaResponse processMedia(VODConfig vodConfig, String vodCode) { try { //上传后直接转码 Credential cred = new Credential(vodConfig.getSecretId(), vodConfig.getSecretKey()); @@ -59,7 +66,7 @@ public class VodUtil { * 删除腾讯云上原视频 * @param vodCode */ - public static void deleteMedia(String vodCode) { + public static void deleteMedia(VODConfig vodConfig, String vodCode) { try { //删除原视频 Credential cred = new Credential(vodConfig.getSecretId(), vodConfig.getSecretKey()); @@ -76,6 +83,41 @@ public class VodUtil { // 返回的resp是一个DeleteMediaResponse的实例,与请求对象对应 client.DeleteMedia(req); } catch (TencentCloudSDKException e) { + throw new HttpException(99999, e.getMessage()); + } + } + + /** + * 云点播域名的CDN统计数据 + * @param vodConfig + * @param DataType + * @param startTime + * @param endTime + * @return + */ + public static StatDataItem[] DescribeCDNStatDetails(VODConfig vodConfig, String DataType, String startTime, String endTime) { + try { + Credential cred = new Credential(vodConfig.getSecretId(), vodConfig.getSecretKey()); + // 实例化一个http选项,可选的,没有特殊需求可以跳过 + HttpProfile httpProfile = new HttpProfile(); + httpProfile.setEndpoint(endpoint); + // 实例化一个client选项,可选的,没有特殊需求可以跳过 + ClientProfile clientProfile = new ClientProfile(); + clientProfile.setHttpProfile(httpProfile); + // 实例化要请求产品的client对象,clientProfile是可选的 + VodClient client = new VodClient(cred, "", clientProfile); + // 实例化一个请求对象,每个接口都会对应一个request对象 + DescribeCDNUsageDataRequest req = new DescribeCDNUsageDataRequest(); + req.setStartTime(startTime); + req.setEndTime(endTime); + req.setDataType(DataType); + // 返回的resp是一个DescribeCDNUsageDataResponse的实例,与请求对象对应 + DescribeCDNUsageDataResponse resp = client.DescribeCDNUsageData(req); + // 返回的resp是一个DescribeCDNStatDetailsResponse的实例,与请求对象对应 + return resp.getData(); + } catch (TencentCloudSDKException e) { + e.printStackTrace(); + throw new HttpException(99999, e.getMessage()); } } } diff --git a/src/main/java/com/subsidy/util/websocket/WebSocketUtil.java b/src/main/java/com/subsidy/util/websocket/WebSocketUtil.java index f9d6cc5..ca5b097 100644 --- a/src/main/java/com/subsidy/util/websocket/WebSocketUtil.java +++ b/src/main/java/com/subsidy/util/websocket/WebSocketUtil.java @@ -40,6 +40,10 @@ public class WebSocketUtil implements WebSocketHandler { @Autowired private OprMemDictMapper oprMemDictMapper; + private int heartbeatMin = 1; // 断连最小心跳次数 + private int heartbeatMax = 3; // 断连最大心跳次数 + private int reconnectionSeconds = 60; //每次断连间隔重新连接秒 + /** * 存放建立连接webSocket对象 */ @@ -58,14 +62,13 @@ public class WebSocketUtil implements WebSocketHandler { Long id = Long.valueOf(params.split("=")[1]); if(null != webSocketMap && webSocketMap.get(id) != null) { if(webSocketMap.get(id).isOpen()) { - /* - 相同账户进行挤号,发送消息给前者WebSocket通知账户已在其他地方登录 - */ + /* 相同账户进行挤号,发送消息给WebSocket通知账户已在其他地方登录 */ webSocketMap.get(id).sendMessage(new TextMessage(JSONObject.toJSONString(ResponseData.generateCreatedResponse(1011)))); webSocketMap.get(id).close(); } else { /* - * 如果上次连接的WebSocket状态是关闭,并且上一次记录时间大于60秒的,则判断为这次登陆是免密码登陆的重新记录上线时间 + * 如果上次连接的WebSocket状态是关闭, + * 并且上一次记录时间大于 { heartbeatMax * reconnectionSeconds } 秒(心跳检测机制),则判断为这次登陆是免密码登陆的重新记录上线时间 */ List list = oprMemDictMapper.selectList(new QueryWrapper() .lambda() @@ -74,7 +77,7 @@ public class WebSocketUtil implements WebSocketHandler { Calendar calendar = Calendar.getInstance(); calendar.setTime(DateFormatUtil.localDateTimeToDate(list.get(0).getCreateDate())); - calendar.add(Calendar.SECOND,60); + calendar.add(Calendar.SECOND,heartbeatMax * reconnectionSeconds); if(calendar.getTime().after(DateFormatUtil.localDateTimeToDate(list.get(0).getCreateDate()))) { if(list.get(0).getOprType().equals("登出")) { OprMemDictDO oprMemDictDO = new OprMemDictDO(); @@ -127,9 +130,6 @@ public class WebSocketUtil implements WebSocketHandler { @Override public void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) throws Exception{ if(null != session) { - /* - 断开连接后不会马上判断为下线状态,而是进入60秒的心跳检测机制,如果60秒内没有进行重连,则判断为下线,记录下线时间和状态 - */ if(null != webSocketMap) { String params = session.getUri().getQuery(); Long id = Long.valueOf(params.split("=")[1]); @@ -141,29 +141,36 @@ public class WebSocketUtil implements WebSocketHandler { } /** - * 断开连接后60秒后进行判断是否重新连接了,如果没有连接成功则判断为下线 + * 断开连接后进行三次心跳验证判断是否重新连接了,如果没有连接成功则判断为下线 * * @param session */ public void heartbeat(WebSocketSession session) { ScheduledExecutorService service = Executors.newScheduledThreadPool(1); ScheduledFuture scheduledFuture = service.scheduleAtFixedRate(new Runnable() { + int beatsNum = heartbeatMin; @SneakyThrows @Override public void run() { if(null != session && !session.isOpen()) { - String params = session.getUri().getQuery(); - Long id = Long.valueOf(params.split("=")[1]); - OprMemDictDO oprMemDictDO = new OprMemDictDO(); - oprMemDictDO.setUserId(id); - oprMemDictDO.setResult(1); - oprMemDictDO.setOprType("登出"); - oprMemDictDO.setIpAddress(session.getRemoteAddress().getHostName()); - oprMemDictMapper.insert(oprMemDictDO); + while (beatsNum > heartbeatMax) { + String params = session.getUri().getQuery(); + Long id = Long.valueOf(params.split("=")[1]); + OprMemDictDO oprMemDictDO = new OprMemDictDO(); + oprMemDictDO.setUserId(id); + oprMemDictDO.setResult(1); + oprMemDictDO.setOprType("登出"); + oprMemDictDO.setIpAddress(session.getRemoteAddress().getHostName()); + oprMemDictMapper.insert(oprMemDictDO); + taskMap.get(session.getId()).cancel(true); + } + beatsNum++; + } else if (null != session && session.isOpen()) { + /* 时间段内重新连接了结束验证 */ taskMap.get(session.getId()).cancel(true); } } - }, 1, 1, TimeUnit.MINUTES); + }, 0, reconnectionSeconds, TimeUnit.SECONDS); taskMap.put(session.getId(), scheduledFuture); } diff --git a/src/main/java/com/subsidy/vo/company/CDNStatDetailsVO.java b/src/main/java/com/subsidy/vo/company/CDNStatDetailsVO.java new file mode 100644 index 0000000..e44bd66 --- /dev/null +++ b/src/main/java/com/subsidy/vo/company/CDNStatDetailsVO.java @@ -0,0 +1,13 @@ +package com.subsidy.vo.company; + +import lombok.Data; +import java.io.Serializable; +import java.math.BigDecimal; + +@Data +public class CDNStatDetailsVO implements Serializable { + + private String time; + + private BigDecimal value; +} diff --git a/src/main/java/com/subsidy/vo/company/DataOverviewVO.java b/src/main/java/com/subsidy/vo/company/DataOverviewVO.java new file mode 100644 index 0000000..41be8a7 --- /dev/null +++ b/src/main/java/com/subsidy/vo/company/DataOverviewVO.java @@ -0,0 +1,53 @@ +package com.subsidy.vo.company; + +import lombok.Data; + +@Data +public class DataOverviewVO { + + /** + * 机构数 + */ + private Integer companyNum; + + /** + * 注册人数 + */ + private Integer registrantsNum; + + /** + * 实名制注册人数 + */ + private Integer realNameNum; + + /** + * 培训项目数量 + */ + private Integer classNum; + + /** + * 资源数量 + */ + private Integer courseNum; + + /** + * 学习过程记录人次 + */ + private Integer studyHistoryNum; + + /** + * 累计学习时长 + */ + private Double studyTotal; + + /** + * 专项资源数量 + */ + + private Integer subsidyCourseNum; + + /** + * 专项资源时长 + */ + private Double subsidyStudyTotal; +} diff --git a/src/main/resources/application-dev.properties b/src/main/resources/application-dev.properties index eda7c57..cbbe544 100644 --- a/src/main/resources/application-dev.properties +++ b/src/main/resources/application-dev.properties @@ -2,7 +2,7 @@ spring.server.port=23457 # 数据源配置 -spring.datasource.url=jdbc:mysql://47.97.19.66:3306/subsidy_test?autoReconnect=true&useUnicode=true&characterEncoding=utf8&serverTimezone=GMT%2B8 +spring.datasource.url=jdbc:mysql://116.62.57.92:3306/subsidy_test?autoReconnect=true&useUnicode=true&characterEncoding=utf8&serverTimezone=GMT%2B8 #spring.datasource.url=jdbc:mysql://rm-uf6rab73w0qg843opxo.mysql.rds.aliyuncs.com:3306/subsidy_test?autoReconnect=true&useUnicode=true&characterEncoding=utf8&serverTimezone=GMT%2B8 spring.datasource.type=com.alibaba.druid.pool.DruidDataSource spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 1a694d2..5c5c4fa 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -34,6 +34,9 @@ mybatis-plus.global-config.db-config.logic-delete-value=NOW() mybatis-plus.global-config.db-config.logic-not-delete-value=NULL #日志配置 logging.config=classpath:logback-spring.xml +#ehcache缓存配置 +spring.cache.type=ehcache +spring.cache.ehcache.config=classpath:ehcache.xml # 阿里云短信 sms.product=Dysmsapi sms.domain=dysmsapi.aliyuncs.com diff --git a/src/main/resources/ehcache.xml b/src/main/resources/ehcache.xml new file mode 100644 index 0000000..7a297bc --- /dev/null +++ b/src/main/resources/ehcache.xml @@ -0,0 +1,44 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/resources/mapper/ClassDictMapper.xml b/src/main/resources/mapper/ClassDictMapper.xml index 5b0726d..c4599b6 100644 --- a/src/main/resources/mapper/ClassDictMapper.xml +++ b/src/main/resources/mapper/ClassDictMapper.xml @@ -169,4 +169,16 @@ AND cd.delete_date IS NULL AND d.delete_date IS NULL + + diff --git a/src/main/resources/mapper/VodPlayHistoryMapper.xml b/src/main/resources/mapper/VodPlayHistoryMapper.xml index e9c63b4..c19dd46 100644 --- a/src/main/resources/mapper/VodPlayHistoryMapper.xml +++ b/src/main/resources/mapper/VodPlayHistoryMapper.xml @@ -398,4 +398,36 @@ t.create_date + + + + + +