xiatian %!s(int64=5) %!d(string=hai) anos
pai
achega
d9c76dafed
Modificáronse 43 ficheiros con 1364 adicións e 227 borrados
  1. 2 2
      examcloud-core-reports-api-provider/src/main/java/cn/com/qmth/examcloud/core/reports/api/controller/ExamStudentCountController.java
  2. 5 8
      examcloud-core-reports-api-provider/src/main/java/cn/com/qmth/examcloud/core/reports/api/controller/StudentCountController.java
  3. 30 0
      examcloud-core-reports-api-provider/src/main/java/cn/com/qmth/examcloud/core/reports/api/controller/StudentCumulativeCountController.java
  4. 38 0
      examcloud-core-reports-api-provider/src/main/java/cn/com/qmth/examcloud/core/reports/api/controller/StudentTotalCountController.java
  5. 2 2
      examcloud-core-reports-api-provider/src/main/java/cn/com/qmth/examcloud/core/reports/api/controller/UserCountController.java
  6. 115 0
      examcloud-core-reports-api-provider/src/main/java/cn/com/qmth/examcloud/core/reports/api/listener/KafkaConsumerListener.java
  7. 13 0
      examcloud-core-reports-api-provider/src/main/java/cn/com/qmth/examcloud/core/reports/api/listener/RocketMqConsumerListener.java
  8. 6 21
      examcloud-core-reports-api-provider/src/main/java/cn/com/qmth/examcloud/core/reports/api/provider/ExamStudentCountCloudServiceProvider.java
  9. 6 18
      examcloud-core-reports-api-provider/src/main/java/cn/com/qmth/examcloud/core/reports/api/provider/StudentCountCloudServiceProvider.java
  10. 35 0
      examcloud-core-reports-api-provider/src/main/java/cn/com/qmth/examcloud/core/reports/api/provider/StudentCumulativeCountCloudServiceProvider.java
  11. 36 0
      examcloud-core-reports-api-provider/src/main/java/cn/com/qmth/examcloud/core/reports/api/provider/StudentTotalCountCloudServiceProvider.java
  12. 6 18
      examcloud-core-reports-api-provider/src/main/java/cn/com/qmth/examcloud/core/reports/api/provider/UserCountCloudServiceProvider.java
  13. 10 0
      examcloud-core-reports-base/pom.xml
  14. 45 0
      examcloud-core-reports-base/src/main/java/cn/com/qmth/examcloud/core/reports/base/bean/StudentCountBean.java
  15. 29 0
      examcloud-core-reports-base/src/main/java/cn/com/qmth/examcloud/core/reports/base/bean/StudentCumulativeCountBean.java
  16. 52 0
      examcloud-core-reports-base/src/main/java/cn/com/qmth/examcloud/core/reports/base/util/BatchGetDataUtil.java
  17. 167 0
      examcloud-core-reports-base/src/main/java/cn/com/qmth/examcloud/core/reports/base/util/online/ActiveDataUtil.java
  18. 35 0
      examcloud-core-reports-base/src/main/java/cn/com/qmth/examcloud/core/reports/base/util/online/ExamStudentActive.java
  19. 26 0
      examcloud-core-reports-base/src/main/java/cn/com/qmth/examcloud/core/reports/base/util/online/OnlineCount.java
  20. 28 0
      examcloud-core-reports-base/src/main/java/cn/com/qmth/examcloud/core/reports/base/util/online/StudentActive.java
  21. 28 0
      examcloud-core-reports-base/src/main/java/cn/com/qmth/examcloud/core/reports/base/util/online/StudentLogin.java
  22. 28 0
      examcloud-core-reports-base/src/main/java/cn/com/qmth/examcloud/core/reports/base/util/online/UserActive.java
  23. 7 1
      examcloud-core-reports-dao/src/main/java/cn/com/qmth/examcloud/core/reports/dao/ExamStudentCountRepo.java
  24. 15 1
      examcloud-core-reports-dao/src/main/java/cn/com/qmth/examcloud/core/reports/dao/StudentCountRepo.java
  25. 12 0
      examcloud-core-reports-dao/src/main/java/cn/com/qmth/examcloud/core/reports/dao/StudentCumulativeCountRepo.java
  26. 16 0
      examcloud-core-reports-dao/src/main/java/cn/com/qmth/examcloud/core/reports/dao/StudentTotalCountRepo.java
  27. 7 1
      examcloud-core-reports-dao/src/main/java/cn/com/qmth/examcloud/core/reports/dao/UserCountRepo.java
  28. 14 36
      examcloud-core-reports-dao/src/main/java/cn/com/qmth/examcloud/core/reports/dao/entity/ExamStudentCountEntity.java
  29. 9 30
      examcloud-core-reports-dao/src/main/java/cn/com/qmth/examcloud/core/reports/dao/entity/StudentCountEntity.java
  30. 51 0
      examcloud-core-reports-dao/src/main/java/cn/com/qmth/examcloud/core/reports/dao/entity/StudentCumulativeCountEntity.java
  31. 38 0
      examcloud-core-reports-dao/src/main/java/cn/com/qmth/examcloud/core/reports/dao/entity/StudentTotalCountEntity.java
  32. 2 25
      examcloud-core-reports-dao/src/main/java/cn/com/qmth/examcloud/core/reports/dao/entity/UserCountEntity.java
  33. 1 3
      examcloud-core-reports-service/src/main/java/cn/com/qmth/examcloud/core/reports/service/ExamStudentCountService.java
  34. 6 3
      examcloud-core-reports-service/src/main/java/cn/com/qmth/examcloud/core/reports/service/StudentCountService.java
  35. 10 0
      examcloud-core-reports-service/src/main/java/cn/com/qmth/examcloud/core/reports/service/StudentCumulativeCountService.java
  36. 12 0
      examcloud-core-reports-service/src/main/java/cn/com/qmth/examcloud/core/reports/service/StudentTotalCountService.java
  37. 1 3
      examcloud-core-reports-service/src/main/java/cn/com/qmth/examcloud/core/reports/service/UserCountService.java
  38. 32 16
      examcloud-core-reports-service/src/main/java/cn/com/qmth/examcloud/core/reports/service/impl/ExamStudentCountServiceImpl.java
  39. 48 20
      examcloud-core-reports-service/src/main/java/cn/com/qmth/examcloud/core/reports/service/impl/StudentCountServiceImpl.java
  40. 139 0
      examcloud-core-reports-service/src/main/java/cn/com/qmth/examcloud/core/reports/service/impl/StudentCumulativeCountServiceImpl.java
  41. 125 0
      examcloud-core-reports-service/src/main/java/cn/com/qmth/examcloud/core/reports/service/impl/StudentTotalCountServiceImpl.java
  42. 36 19
      examcloud-core-reports-service/src/main/java/cn/com/qmth/examcloud/core/reports/service/impl/UserCountServiceImpl.java
  43. 41 0
      examcloud-core-reports-starter/src/main/java/cn/com/qmth/examcloud/core/reports/starter/config/MqConsumerListenerStartup.java

+ 2 - 2
examcloud-core-reports-api-provider/src/main/java/cn/com/qmth/examcloud/core/reports/api/controller/ExamStudentCountController.java

@@ -1,7 +1,7 @@
 package cn.com.qmth.examcloud.core.reports.api.controller;
 
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.GetMapping;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RequestParam;
 import org.springframework.web.bind.annotation.RestController;
@@ -19,7 +19,7 @@ public class ExamStudentCountController extends ControllerSupport {
 	@Autowired
 	private ExamStudentCountService examStudentCountService;
 	
-	@PostMapping("/getOnlineCount")
+	@GetMapping("/getOnlineCount")
 	@ApiOperation(value = "获取在线人数")
 	public Long getOnlineCount(@RequestParam(required = false) Long orgId,@RequestParam(required = false) Long examId) {
 		User user = getAccessUser();

+ 5 - 8
examcloud-core-reports-api-provider/src/main/java/cn/com/qmth/examcloud/core/reports/api/controller/StudentCountController.java

@@ -1,12 +1,10 @@
 package cn.com.qmth.examcloud.core.reports.api.controller;
 
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.GetMapping;
 import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RequestParam;
 import org.springframework.web.bind.annotation.RestController;
 
-import cn.com.qmth.examcloud.api.commons.security.bean.User;
 import cn.com.qmth.examcloud.core.reports.service.StudentCountService;
 import cn.com.qmth.examcloud.web.support.ControllerSupport;
 import io.swagger.annotations.Api;
@@ -19,10 +17,9 @@ public class StudentCountController extends ControllerSupport {
 	@Autowired
 	private StudentCountService studentCountService;
 
-	@PostMapping("/getOnlineCount")
-	@ApiOperation(value = "获取在线人数")
-	public Long getOnlineCount(@RequestParam(required = false) Long orgId) {
-		User user = getAccessUser();
-		return studentCountService.getOnlineCount(user.getRootOrgId(), orgId);
+	@GetMapping("/getSumOnlineCount")
+	@ApiOperation(value = "获取总在线人数")
+	public Long getSumOnlineCount() {
+		return studentCountService.getSumOnlineCount();
 	}
 }

+ 30 - 0
examcloud-core-reports-api-provider/src/main/java/cn/com/qmth/examcloud/core/reports/api/controller/StudentCumulativeCountController.java

@@ -0,0 +1,30 @@
+package cn.com.qmth.examcloud.core.reports.api.controller;
+
+import java.util.List;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+import cn.com.qmth.examcloud.core.reports.base.bean.StudentCumulativeCountBean;
+import cn.com.qmth.examcloud.core.reports.service.StudentCumulativeCountService;
+import cn.com.qmth.examcloud.web.support.ControllerSupport;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import io.swagger.annotations.ApiParam;
+
+@RestController
+@Api(tags = "学生累计在线人数")
+@RequestMapping("${$rmp.ctr.reports}/" + "studentCumulativeCount")
+public class StudentCumulativeCountController extends ControllerSupport {
+	@Autowired
+	private StudentCumulativeCountService studentCumulativeCountService;
+
+	@GetMapping("/getLastNdayOnlineCount")
+	@ApiOperation(value = "获取近N日在线人数")
+	public List<StudentCumulativeCountBean> getLastNdayOnlineCount(@RequestParam @ApiParam(value = "nday 1~100") Integer nday) {
+		return studentCumulativeCountService.getLastNdayOnlineCount(nday);
+	}
+}

+ 38 - 0
examcloud-core-reports-api-provider/src/main/java/cn/com/qmth/examcloud/core/reports/api/controller/StudentTotalCountController.java

@@ -0,0 +1,38 @@
+package cn.com.qmth.examcloud.core.reports.api.controller;
+
+import org.springframework.beans.factory.annotation.Autowired;
+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.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+import cn.com.qmth.examcloud.api.commons.exchange.PageInfo;
+import cn.com.qmth.examcloud.core.reports.base.bean.StudentCountBean;
+import cn.com.qmth.examcloud.core.reports.service.StudentTotalCountService;
+import cn.com.qmth.examcloud.web.support.ControllerSupport;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import io.swagger.annotations.ApiParam;
+
+@RestController
+@Api(tags = "学生总人数")
+@RequestMapping("${$rmp.ctr.reports}/" + "studentTotalCount")
+public class StudentTotalCountController extends ControllerSupport {
+	@Autowired
+	private StudentTotalCountService studentTotalCountService;
+
+	@PostMapping("/getSumTotalCount")
+	@ApiOperation(value = "获取总的学生人数")
+	public Long getSumTotalCount() {
+		return studentTotalCountService.getSumTotalCount();
+	}
+	
+	@GetMapping("page/{pageNo}/{pageSize}")
+	@ApiOperation(value = "分页查询学生在线人数和总人数")
+	public PageInfo<StudentCountBean> queryPage(@RequestParam String rootOrgId,
+			@PathVariable @ApiParam(value = "pageNo = 1,2,3...") Integer pageNo, @PathVariable Integer pageSize) {
+		return studentTotalCountService.queryPage(rootOrgId, pageNo, pageSize);
+	}
+}

+ 2 - 2
examcloud-core-reports-api-provider/src/main/java/cn/com/qmth/examcloud/core/reports/api/controller/UserCountController.java

@@ -1,7 +1,7 @@
 package cn.com.qmth.examcloud.core.reports.api.controller;
 
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.GetMapping;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RequestParam;
 import org.springframework.web.bind.annotation.RestController;
@@ -19,7 +19,7 @@ public class UserCountController extends ControllerSupport {
 	@Autowired
 	private UserCountService userCountService;
 
-	@PostMapping("/getOnlineCount")
+	@GetMapping("/getOnlineCount")
 	@ApiOperation(value = "获取在线人数")
 	public Long getOnlineCount(@RequestParam(required = false) Long orgId) {
 		User user = getAccessUser();

+ 115 - 0
examcloud-core-reports-api-provider/src/main/java/cn/com/qmth/examcloud/core/reports/api/listener/KafkaConsumerListener.java

@@ -0,0 +1,115 @@
+package cn.com.qmth.examcloud.core.reports.api.listener;
+
+import java.time.Duration;
+import java.util.List;
+import java.util.Properties;
+
+import org.apache.kafka.clients.consumer.ConsumerRecord;
+import org.apache.kafka.clients.consumer.ConsumerRecords;
+import org.apache.kafka.clients.consumer.KafkaConsumer;
+import org.assertj.core.util.Lists;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.alibaba.fastjson.JSON;
+
+import cn.com.qmth.examcloud.core.reports.base.util.online.ActiveDataUtil;
+import cn.com.qmth.examcloud.core.reports.base.util.online.ExamStudentActive;
+import cn.com.qmth.examcloud.core.reports.base.util.online.StudentActive;
+import cn.com.qmth.examcloud.core.reports.base.util.online.StudentLogin;
+import cn.com.qmth.examcloud.core.reports.base.util.online.UserActive;
+import cn.com.qmth.examcloud.reports.commons.bean.LoginStudentReport;
+import cn.com.qmth.examcloud.reports.commons.bean.OnlineExamStudentReport;
+import cn.com.qmth.examcloud.reports.commons.bean.OnlineStudentReport;
+import cn.com.qmth.examcloud.reports.commons.bean.OnlineUserReport;
+import cn.com.qmth.examcloud.reports.commons.enums.Topic;
+import cn.com.qmth.examcloud.web.bootstrap.PropertyHolder;
+
+public class KafkaConsumerListener {
+	private final static Logger logger = LoggerFactory.getLogger(KafkaConsumerListener.class);
+
+	private static Properties props;
+
+	static {
+		props = new Properties();
+		props.put("group.id", PropertyHolder.getString("spring.kafka.consumer.group-id"));
+		props.put("bootstrap.servers", PropertyHolder.getString("spring.kafka.bootstrap-servers"));
+		props.put("key.deserializer", PropertyHolder.getString("spring.kafka.consumer.key-deserializer"));
+		props.put("value.deserializer", PropertyHolder.getString("spring.kafka.consumer.value-deserializer"));
+	}
+
+	public static void start() {
+		KafkaConsumer<String, String> consumer = new KafkaConsumer<String, String>(props);
+		List<String> subs=Lists.newArrayList();
+		subs.add(Topic.STUDENT.getCode());
+		subs.add(Topic.EXAM_STUDENT.getCode());
+		subs.add(Topic.USER.getCode());
+		subs.add(Topic.STUDENT_LOGIN.getCode());
+		consumer.subscribe(subs);
+		try {
+		   for(;;) {
+		        // 100 是超时时间(ms),在该时间内 poll 会等待服务器返回数据
+		        ConsumerRecords<String, String> records = consumer.poll(Duration.ofMillis(100));
+
+		        // poll 返回一个记录列表。
+		        // 每条记录都包含了记录所属主题的信息、记录所在分区的信息、记录在分区里的偏移量,以及记录的键值对。
+		        for (ConsumerRecord<String, String> record : records) {
+		        	if(Topic.STUDENT.getCode().equals(record.topic())) {
+		        		onMessageStudent(record.value());
+		        	}else if(Topic.EXAM_STUDENT.getCode().equals(record.topic())){
+		        		onMessageExamStudent(record.value());
+		        	}else if(Topic.USER.getCode().equals(record.topic())){
+		        		onMessageUser(record.value());
+		        	}else if(Topic.STUDENT_LOGIN.getCode().equals(record.topic())){
+		        		onMessageLoginStudent(record.value());
+		        	}
+		        }
+		    }
+		} finally {
+		    // 关闭消费者,网络连接和 socket 也会随之关闭,并立即触发一次再均衡
+		    consumer.close();
+		}
+	}
+
+	private static void onMessageStudent(String message) {
+		logger.debug("STUDENT message:" + message);
+		OnlineStudentReport r = JSON.parseObject(message, OnlineStudentReport.class);
+		StudentActive ac = new StudentActive();
+		ac.setActiveTime(r.getReportTime().getTime());
+		ac.setRootOrgId(r.getRootOrgId());
+		ac.setStudentId(r.getStudentId());
+		ActiveDataUtil.updateStudentActive(ac);
+	}
+
+	private static void onMessageExamStudent(String message) {
+		logger.debug("EXAM_STUDENT message:" + message);
+		OnlineExamStudentReport r = JSON.parseObject(message, OnlineExamStudentReport.class);
+		ExamStudentActive ac = new ExamStudentActive();
+		ac.setActiveTime(r.getReportTime().getTime());
+		ac.setRootOrgId(r.getRootOrgId());
+		ac.setExamStudentId(r.getExamStudentId());
+		ac.setExamId(r.getExamId());
+		ActiveDataUtil.updateExamStudentActive(ac);
+	}
+
+	private static void onMessageUser(String message) {
+		logger.debug("USER message:" + message);
+		OnlineUserReport r = JSON.parseObject(message, OnlineUserReport.class);
+		UserActive ac = new UserActive();
+		ac.setActiveTime(r.getReportTime().getTime());
+		ac.setRootOrgId(r.getRootOrgId());
+		ac.setUserId(r.getUserId());
+		ActiveDataUtil.updateUserActive(ac);
+	}
+
+	private static void onMessageLoginStudent(String message) {
+		logger.debug("STUDENT_LOGIN message:" + message);
+		LoginStudentReport r = JSON.parseObject(message, LoginStudentReport.class);
+		StudentLogin sl = new StudentLogin();
+		sl.setActiveTime(r.getReportTime().getTime());
+		sl.setRootOrgId(r.getRootOrgId());
+		sl.setStudentId(r.getStudentId());
+		ActiveDataUtil.updateStudentlogin(sl);
+	}
+
+}

+ 13 - 0
examcloud-core-reports-api-provider/src/main/java/cn/com/qmth/examcloud/core/reports/api/listener/RocketMqConsumerListener.java

@@ -0,0 +1,13 @@
+package cn.com.qmth.examcloud.core.reports.api.listener;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class RocketMqConsumerListener {
+	private final static Logger logger = LoggerFactory.getLogger(RocketMqConsumerListener.class);
+	
+	public static void start() {
+		
+	}
+
+}

+ 6 - 21
examcloud-core-reports-api-provider/src/main/java/cn/com/qmth/examcloud/core/reports/api/provider/ExamStudentCountCloudServiceProvider.java

@@ -2,14 +2,11 @@ package cn.com.qmth.examcloud.core.reports.api.provider;
 
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.PostMapping;
-import org.springframework.web.bind.annotation.RequestBody;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RestController;
 
-import cn.com.qmth.examcloud.commons.exception.StatusException;
 import cn.com.qmth.examcloud.core.reports.api.ExamStudentCountCloudService;
-import cn.com.qmth.examcloud.core.reports.api.request.AddOrUpdateExamStudentCountReq;
-import cn.com.qmth.examcloud.core.reports.api.response.AddOrUpdateExamStudentCountResp;
+import cn.com.qmth.examcloud.core.reports.api.response.SaveExamStudentCountResp;
 import cn.com.qmth.examcloud.core.reports.service.ExamStudentCountService;
 import cn.com.qmth.examcloud.web.support.ControllerSupport;
 import io.swagger.annotations.Api;
@@ -26,23 +23,11 @@ public class ExamStudentCountCloudServiceProvider extends ControllerSupport impl
 	@Autowired
 	private ExamStudentCountService examStudentCountService;
 
-	@ApiOperation(value = "新增或更新在线人数")
-	@PostMapping("/addOrUpdateCount")
+	@ApiOperation(value = "计算在线人数")
+    @PostMapping("/saveCount")
 	@Override
-	public AddOrUpdateExamStudentCountResp addOrUpdateCount(@RequestBody AddOrUpdateExamStudentCountReq req) {
-		if (req.getRootOrgId() == null) {
-			throw new StatusException("1000001", "rootOrgId不能为空");
-		}
-		if (req.getOrgId() == null) {
-			throw new StatusException("1000002", "orgId不能为空");
-		}
-		if (req.getExamId() == null) {
-			throw new StatusException("1000003", "examId不能为空");
-		}
-		if(req.getBatchTime()==null) {
-			throw new StatusException("1000004", "batchTime不能为空");
-		}
-		examStudentCountService.addOrUpdateCount(req);
-		return new AddOrUpdateExamStudentCountResp();
+	public SaveExamStudentCountResp saveCount() {
+		examStudentCountService.saveCount();
+		return new SaveExamStudentCountResp();
 	}
 }

+ 6 - 18
examcloud-core-reports-api-provider/src/main/java/cn/com/qmth/examcloud/core/reports/api/provider/StudentCountCloudServiceProvider.java

@@ -2,14 +2,11 @@ package cn.com.qmth.examcloud.core.reports.api.provider;
 
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.PostMapping;
-import org.springframework.web.bind.annotation.RequestBody;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RestController;
 
-import cn.com.qmth.examcloud.commons.exception.StatusException;
 import cn.com.qmth.examcloud.core.reports.api.StudentCountCloudService;
-import cn.com.qmth.examcloud.core.reports.api.request.AddOrUpdateStudentCountReq;
-import cn.com.qmth.examcloud.core.reports.api.response.AddOrUpdateStudentCountResp;
+import cn.com.qmth.examcloud.core.reports.api.response.SaveStudentCountResp;
 import cn.com.qmth.examcloud.core.reports.service.StudentCountService;
 import cn.com.qmth.examcloud.web.support.ControllerSupport;
 import io.swagger.annotations.Api;
@@ -28,20 +25,11 @@ public class StudentCountCloudServiceProvider extends ControllerSupport implemen
 	@Autowired
 	private StudentCountService studentCountService;
 
-	@ApiOperation(value = "新增或更新在线人数")
-    @PostMapping("/addOrUpdateCount")
+	@ApiOperation(value = "计算在线人数")
+    @PostMapping("/saveCount")
 	@Override
-	public AddOrUpdateStudentCountResp addOrUpdateCount(@RequestBody AddOrUpdateStudentCountReq req) {
-		if(req.getRootOrgId()==null) {
-			throw new StatusException("1000001", "rootOrgId不能为空");
-		}
-		if(req.getOrgId()==null) {
-			throw new StatusException("1000002", "orgId不能为空");
-		}
-		if(req.getBatchTime()==null) {
-			throw new StatusException("1000003", "batchTime不能为空");
-		}
-		studentCountService.addOrUpdateCount(req);
-		return new AddOrUpdateStudentCountResp();
+	public SaveStudentCountResp saveCount() {
+		studentCountService.saveCount();
+		return new SaveStudentCountResp();
 	}
 }

+ 35 - 0
examcloud-core-reports-api-provider/src/main/java/cn/com/qmth/examcloud/core/reports/api/provider/StudentCumulativeCountCloudServiceProvider.java

@@ -0,0 +1,35 @@
+package cn.com.qmth.examcloud.core.reports.api.provider;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import cn.com.qmth.examcloud.core.reports.api.StudentCumulativeCountCloudService;
+import cn.com.qmth.examcloud.core.reports.api.response.SaveStudentCumulativeCountResp;
+import cn.com.qmth.examcloud.core.reports.service.StudentCumulativeCountService;
+import cn.com.qmth.examcloud.web.support.ControllerSupport;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+
+@RestController
+@Api(tags = "学生累计在线人数接口")
+@RequestMapping("${$rmp.cloud.reports}"+"studentCumulativeCount")
+public class StudentCumulativeCountCloudServiceProvider extends ControllerSupport implements StudentCumulativeCountCloudService {
+
+	
+	/**
+	 * 
+	 */
+	private static final long serialVersionUID = 3673284538600937213L;
+	@Autowired
+	private StudentCumulativeCountService studentCumulativeCountService;
+
+	@ApiOperation(value = "计算累计在线人数")
+    @PostMapping("/saveCount")
+	@Override
+	public SaveStudentCumulativeCountResp saveCount() {
+		studentCumulativeCountService.saveCount();
+		return new SaveStudentCumulativeCountResp();
+	}
+}

+ 36 - 0
examcloud-core-reports-api-provider/src/main/java/cn/com/qmth/examcloud/core/reports/api/provider/StudentTotalCountCloudServiceProvider.java

@@ -0,0 +1,36 @@
+package cn.com.qmth.examcloud.core.reports.api.provider;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import cn.com.qmth.examcloud.core.reports.api.StudentTotalCountCloudService;
+import cn.com.qmth.examcloud.core.reports.api.response.StudentTotalCountResp;
+import cn.com.qmth.examcloud.core.reports.service.StudentCountService;
+import cn.com.qmth.examcloud.web.support.ControllerSupport;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+
+@RestController
+@Api(tags = "学生总人数接口")
+@RequestMapping("${$rmp.cloud.reports}"+"studentTotalCount")
+public class StudentTotalCountCloudServiceProvider extends ControllerSupport implements StudentTotalCountCloudService {
+
+	
+	/**
+	 * 
+	 */
+	private static final long serialVersionUID = 3112398369884979088L;
+	@Autowired
+	private StudentCountService studentCountService;
+
+
+	@ApiOperation(value = "计算总人数")
+    @PostMapping("/compute")
+	@Override
+	public StudentTotalCountResp compute() {
+		// TODO Auto-generated method stub
+		return new StudentTotalCountResp();
+	}
+}

+ 6 - 18
examcloud-core-reports-api-provider/src/main/java/cn/com/qmth/examcloud/core/reports/api/provider/UserCountCloudServiceProvider.java

@@ -2,14 +2,11 @@ package cn.com.qmth.examcloud.core.reports.api.provider;
 
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.PostMapping;
-import org.springframework.web.bind.annotation.RequestBody;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RestController;
 
-import cn.com.qmth.examcloud.commons.exception.StatusException;
 import cn.com.qmth.examcloud.core.reports.api.UserCountCloudService;
-import cn.com.qmth.examcloud.core.reports.api.request.AddOrUpdateUserCountReq;
-import cn.com.qmth.examcloud.core.reports.api.response.AddOrUpdateUserCountResp;
+import cn.com.qmth.examcloud.core.reports.api.response.SaveUserCountResp;
 import cn.com.qmth.examcloud.core.reports.service.UserCountService;
 import cn.com.qmth.examcloud.web.support.ControllerSupport;
 import io.swagger.annotations.Api;
@@ -27,21 +24,12 @@ public class UserCountCloudServiceProvider extends ControllerSupport implements
 	@Autowired
 	private UserCountService userCountService;
 	
-	@ApiOperation(value = "新增或更新在线人数")
-    @PostMapping("/addOrUpdateCount")
+	@ApiOperation(value = "计算在线人数")
+    @PostMapping("/saveCount")
 	@Override
-	public AddOrUpdateUserCountResp addOrUpdateCount(@RequestBody AddOrUpdateUserCountReq req) {
-		if(req.getRootOrgId()==null) {
-			throw new StatusException("1000001", "rootOrgId不能为空");
-		}
-		if(req.getOrgId()==null) {
-			throw new StatusException("1000002", "orgId不能为空");
-		}
-		if(req.getBatchTime()==null) {
-			throw new StatusException("1000003", "batchTime不能为空");
-		}
-		userCountService.addOrUpdateCount(req);
-		return new AddOrUpdateUserCountResp();
+	public SaveUserCountResp saveCount() {
+		userCountService.saveCount();
+		return new SaveUserCountResp();
 	}
 
 

+ 10 - 0
examcloud-core-reports-base/pom.xml

@@ -23,6 +23,16 @@
 			<artifactId>examcloud-support</artifactId>
 			<version>${examcloud.version}</version>
 		</dependency>
+		<dependency>
+			<groupId>cn.com.qmth.examcloud.reports</groupId>
+			<artifactId>examcloud-reports-commons</artifactId>
+			<version>${examcloud.version}</version>
+		</dependency>
+		<dependency>
+            <groupId>cn.com.qmth.examcloud.rpc</groupId>
+            <artifactId>examcloud-core-basic-api-client</artifactId>
+            <version>${examcloud.version}</version>
+        </dependency>
 	</dependencies>
 
 </project>

+ 45 - 0
examcloud-core-reports-base/src/main/java/cn/com/qmth/examcloud/core/reports/base/bean/StudentCountBean.java

@@ -0,0 +1,45 @@
+package cn.com.qmth.examcloud.core.reports.base.bean;
+
+import cn.com.qmth.examcloud.api.commons.exchange.JsonSerializable;
+import io.swagger.annotations.ApiModelProperty;
+
+public class StudentCountBean implements JsonSerializable {
+
+	/**
+	 * 
+	 */
+	private static final long serialVersionUID = 7681687345714701612L;
+	@ApiModelProperty(value = "学校名称")
+	private String rootOrgName;
+	@ApiModelProperty(value = "rootOrgId")
+	private Long rootOrgId;
+	@ApiModelProperty(value = "总人数")
+	private Integer totalCount;
+	@ApiModelProperty(value = "在线人数")
+	private Integer onlineCount;
+	public String getRootOrgName() {
+		return rootOrgName;
+	}
+	public void setRootOrgName(String rootOrgName) {
+		this.rootOrgName = rootOrgName;
+	}
+	public Long getRootOrgId() {
+		return rootOrgId;
+	}
+	public void setRootOrgId(Long rootOrgId) {
+		this.rootOrgId = rootOrgId;
+	}
+	public Integer getTotalCount() {
+		return totalCount;
+	}
+	public void setTotalCount(Integer totalCount) {
+		this.totalCount = totalCount;
+	}
+	public Integer getOnlineCount() {
+		return onlineCount;
+	}
+	public void setOnlineCount(Integer onlineCount) {
+		this.onlineCount = onlineCount;
+	}
+
+}

+ 29 - 0
examcloud-core-reports-base/src/main/java/cn/com/qmth/examcloud/core/reports/base/bean/StudentCumulativeCountBean.java

@@ -0,0 +1,29 @@
+package cn.com.qmth.examcloud.core.reports.base.bean;
+
+import cn.com.qmth.examcloud.api.commons.exchange.JsonSerializable;
+import io.swagger.annotations.ApiModelProperty;
+
+public class StudentCumulativeCountBean implements JsonSerializable {
+
+	/**
+	 * 
+	 */
+	private static final long serialVersionUID = -3717372589234196602L;
+	@ApiModelProperty(value = "人数")
+	private Integer totalCount;
+	@ApiModelProperty(value = "日期")
+	private String reportDay;
+	public Integer getTotalCount() {
+		return totalCount;
+	}
+	public void setTotalCount(Integer totalCount) {
+		this.totalCount = totalCount;
+	}
+	public String getReportDay() {
+		return reportDay;
+	}
+	public void setReportDay(String reportDay) {
+		this.reportDay = reportDay;
+	}
+
+}

+ 52 - 0
examcloud-core-reports-base/src/main/java/cn/com/qmth/examcloud/core/reports/base/util/BatchGetDataUtil.java

@@ -0,0 +1,52 @@
+package cn.com.qmth.examcloud.core.reports.base.util;
+
+import java.util.List;
+
+/**
+ *	多次批量获取数据
+ *	需重写getData方法
+ * @author xiatian
+ * @param <R> 结果类
+ * @param <P> 参数类
+ */
+public  class BatchGetDataUtil<R,P> {
+	/**
+	 * @param resultList 全部结果集合
+	 * @param paramList 全部参数集合
+	 * @param batchSize 每批参数数量
+	 */
+	public final void getDataForBatch(List<R> resultList,List<P> paramList,int batchSize) {
+		if(resultList==null||paramList==null||paramList.size()==0) {
+			return;
+		}
+		if(paramList.size()<=batchSize) {
+			List<R> temlist = getData(paramList);
+			if(temlist!=null&&temlist.size()>0) {
+				resultList.addAll(temlist);
+			}
+		}else {
+			int size = paramList.size();
+			int len=batchSize;
+			int count = (size + len - 1) / len;
+
+			for (int i = 0; i < count; i++) {
+				List<P> subList = paramList.subList(i * len, ((i + 1) * len > size ? size : len * (i + 1)));
+				List<R> temlist = getData(subList);
+				if(temlist!=null&&temlist.size()>0) {
+					resultList.addAll(temlist);
+				}
+			}
+		}
+	}
+	/**
+	 * 	Need Override
+	 * 	每批获取数据方法
+	 * @param <R>
+	 * @param <P>
+	 * @param paramList 获取每批数据时参数
+	 * @return
+	 */
+	public  List<R> getData(List<P> paramList) {
+		return null;
+	}
+}

+ 167 - 0
examcloud-core-reports-base/src/main/java/cn/com/qmth/examcloud/core/reports/base/util/online/ActiveDataUtil.java

@@ -0,0 +1,167 @@
+package cn.com.qmth.examcloud.core.reports.base.util.online;
+
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+import cn.com.qmth.examcloud.commons.util.DateUtil;
+
+public class ActiveDataUtil {
+	private final static String spe = "_";
+	private final static Long defTimeOut = 5 * 60 * 1000L;
+	private static String studentLoginDataReportDay=DateUtil.format(new Date(), DateUtil.DatePatterns.YYYY_MM_DD);
+	private final static Map<String, Map<Long, Long>> studentLoginData = new ConcurrentHashMap<String, Map<Long, Long>>();
+	private final static Map<String, Map<Long, Long>> userActiveData = new ConcurrentHashMap<String, Map<Long, Long>>();
+	private final static Map<String, Map<Long, Long>> studentActiveData = new ConcurrentHashMap<String, Map<Long, Long>>();
+	private final static Map<String, Map<Long, Long>> examStudentActiveData = new ConcurrentHashMap<String, Map<Long, Long>>();
+
+	public static void updateUserActive(UserActive ac) {
+		String key = ac.getKey(spe);
+		Map<Long, Long> map = userActiveData.get(key);
+		if (map == null) {
+			map = new ConcurrentHashMap<Long, Long>();
+			userActiveData.put(key, map);
+		}
+		map.put(ac.getUserId(), ac.getActiveTime());
+	}
+
+	public static void updateStudentActive(StudentActive ac) {
+		String key = ac.getKey(spe);
+		Map<Long, Long> map = studentActiveData.get(key);
+		if (map == null) {
+			map = new ConcurrentHashMap<Long, Long>();
+			studentActiveData.put(key, map);
+		}
+		map.put(ac.getStudentId(), ac.getActiveTime());
+	}
+
+	public static void updateExamStudentActive(ExamStudentActive ac) {
+		String key = ac.getKey(spe);
+		Map<Long, Long> map = examStudentActiveData.get(key);
+		if (map == null) {
+			map = new ConcurrentHashMap<Long, Long>();
+			examStudentActiveData.put(key, map);
+		}
+		map.put(ac.getExamStudentId(), ac.getActiveTime());
+	}
+
+	public static void updateStudentlogin(StudentLogin sl) {
+		String key = sl.getKey(spe);
+		Map<Long, Long> map = studentLoginData.get(key);
+		if (map == null) {
+			map = new ConcurrentHashMap<Long, Long>();
+			studentLoginData.put(key, map);
+		}
+		map.put(sl.getStudentId(), sl.getActiveTime());
+	}
+
+	private static void clearTimeOutUserActive(Long timeOut) {
+		if (timeOut == null) {
+			timeOut = defTimeOut;
+		}
+		Date d = new Date();
+		Long now = d.getTime();
+		for (Map<Long, Long> map : userActiveData.values()) {
+			for (Long k : map.keySet()) {
+				if (now - map.get(k) > timeOut) {
+					map.remove(k);
+				}
+			}
+		}
+	}
+
+	private static void clearTimeOutStudentActive(Long timeOut) {
+		if (timeOut == null) {
+			timeOut = defTimeOut;
+		}
+		Date d = new Date();
+		Long now = d.getTime();
+		for (Map<Long, Long> map : studentActiveData.values()) {
+			for (Long k : map.keySet()) {
+				if (now - map.get(k) > timeOut) {
+					map.remove(k);
+				}
+			}
+		}
+	}
+
+	private static void clearTimeOutExamStudentActive(Long timeOut) {
+		if (timeOut == null) {
+			timeOut = defTimeOut;
+		}
+		Date d = new Date();
+		Long now = d.getTime();
+		for (Map<Long, Long> map : examStudentActiveData.values()) {
+			for (Long k : map.keySet()) {
+				if (now - map.get(k) > timeOut) {
+					map.remove(k);
+				}
+			}
+		}
+	}
+
+	public static List<OnlineCount> getUserCount(Long timeOut) {
+		clearTimeOutUserActive(timeOut);
+		List<OnlineCount> ret = new ArrayList<OnlineCount>();
+		for (String key : userActiveData.keySet()) {
+			OnlineCount oc = new OnlineCount();
+			String[] ks = key.split(spe);
+			oc.setRootOrgId(Long.valueOf(ks[0]));
+			oc.setOnlineCount(userActiveData.get(key).size());
+			ret.add(oc);
+		}
+		return ret;
+	}
+
+	public static List<OnlineCount> getStudentCount(Long timeOut) {
+		clearTimeOutStudentActive(timeOut);
+		List<OnlineCount> ret = new ArrayList<OnlineCount>();
+		for (String key : studentActiveData.keySet()) {
+			OnlineCount oc = new OnlineCount();
+			String[] ks = key.split(spe);
+			oc.setRootOrgId(Long.valueOf(ks[0]));
+			oc.setOnlineCount(studentActiveData.get(key).size());
+			ret.add(oc);
+		}
+		return ret;
+	}
+
+	public static List<OnlineCount> getExamStudentCount(Long timeOut) {
+		clearTimeOutExamStudentActive(timeOut);
+		List<OnlineCount> ret = new ArrayList<OnlineCount>();
+		for (String key : examStudentActiveData.keySet()) {
+			OnlineCount oc = new OnlineCount();
+			String[] ks = key.split(spe);
+			oc.setRootOrgId(Long.valueOf(ks[0]));
+			oc.setExamId(Long.valueOf(ks[1]));
+			oc.setOnlineCount(examStudentActiveData.get(key).size());
+			ret.add(oc);
+		}
+		return ret;
+	}
+
+	public static List<OnlineCount> getStudentLoginCount() {
+		List<OnlineCount> ret = new ArrayList<OnlineCount>();
+		for (String key : studentLoginData.keySet()) {
+			OnlineCount oc = new OnlineCount();
+			String[] ks = key.split(spe);
+			oc.setRootOrgId(Long.valueOf(ks[0]));
+			oc.setOnlineCount(studentLoginData.get(key).size());
+			ret.add(oc);
+		}
+		return ret;
+	}
+
+	public static void clearStudentLoginCount() {
+		studentLoginDataReportDay=DateUtil.format(new Date(), DateUtil.DatePatterns.YYYY_MM_DD);
+		studentLoginData.clear();
+	}
+
+	public static String getStudentLoginDataReportDay() {
+		return studentLoginDataReportDay;
+	}
+	
+	
+}

+ 35 - 0
examcloud-core-reports-base/src/main/java/cn/com/qmth/examcloud/core/reports/base/util/online/ExamStudentActive.java

@@ -0,0 +1,35 @@
+package cn.com.qmth.examcloud.core.reports.base.util.online;
+
+public class ExamStudentActive {
+	private Long rootOrgId;
+	private Long examId;
+	private Long examStudentId;
+	private Long activeTime;
+	public Long getRootOrgId() {
+		return rootOrgId;
+	}
+	public void setRootOrgId(Long rootOrgId) {
+		this.rootOrgId = rootOrgId;
+	}
+	public Long getExamId() {
+		return examId;
+	}
+	public void setExamId(Long examId) {
+		this.examId = examId;
+	}
+	public Long getExamStudentId() {
+		return examStudentId;
+	}
+	public void setExamStudentId(Long examStudentId) {
+		this.examStudentId = examStudentId;
+	}
+	public Long getActiveTime() {
+		return activeTime;
+	}
+	public void setActiveTime(Long activeTime) {
+		this.activeTime = activeTime;
+	}
+	public String getKey(String spe) {
+		return rootOrgId+spe+examId;
+	}
+}

+ 26 - 0
examcloud-core-reports-base/src/main/java/cn/com/qmth/examcloud/core/reports/base/util/online/OnlineCount.java

@@ -0,0 +1,26 @@
+package cn.com.qmth.examcloud.core.reports.base.util.online;
+
+public class OnlineCount {
+	private Long examId;
+	private Long rootOrgId;
+	private Integer onlineCount;
+	public Long getRootOrgId() {
+		return rootOrgId;
+	}
+	public void setRootOrgId(Long rootOrgId) {
+		this.rootOrgId = rootOrgId;
+	}
+	public Integer getOnlineCount() {
+		return onlineCount;
+	}
+	public void setOnlineCount(Integer onlineCount) {
+		this.onlineCount = onlineCount;
+	}
+	public Long getExamId() {
+		return examId;
+	}
+	public void setExamId(Long examId) {
+		this.examId = examId;
+	}
+	
+}

+ 28 - 0
examcloud-core-reports-base/src/main/java/cn/com/qmth/examcloud/core/reports/base/util/online/StudentActive.java

@@ -0,0 +1,28 @@
+package cn.com.qmth.examcloud.core.reports.base.util.online;
+
+public class StudentActive {
+	private Long rootOrgId;
+	private Long studentId;
+	private Long activeTime;
+	public Long getRootOrgId() {
+		return rootOrgId;
+	}
+	public void setRootOrgId(Long rootOrgId) {
+		this.rootOrgId = rootOrgId;
+	}
+	public Long getStudentId() {
+		return studentId;
+	}
+	public void setStudentId(Long studentId) {
+		this.studentId = studentId;
+	}
+	public Long getActiveTime() {
+		return activeTime;
+	}
+	public void setActiveTime(Long activeTime) {
+		this.activeTime = activeTime;
+	}
+	public String getKey(String spe) {
+		return rootOrgId+spe;
+	}
+}

+ 28 - 0
examcloud-core-reports-base/src/main/java/cn/com/qmth/examcloud/core/reports/base/util/online/StudentLogin.java

@@ -0,0 +1,28 @@
+package cn.com.qmth.examcloud.core.reports.base.util.online;
+
+public class StudentLogin {
+	private Long rootOrgId;
+	private Long studentId;
+	private Long activeTime;
+	public Long getRootOrgId() {
+		return rootOrgId;
+	}
+	public void setRootOrgId(Long rootOrgId) {
+		this.rootOrgId = rootOrgId;
+	}
+	public Long getStudentId() {
+		return studentId;
+	}
+	public void setStudentId(Long studentId) {
+		this.studentId = studentId;
+	}
+	public Long getActiveTime() {
+		return activeTime;
+	}
+	public void setActiveTime(Long activeTime) {
+		this.activeTime = activeTime;
+	}
+	public String getKey(String spe) {
+		return rootOrgId+spe;
+	}
+}

+ 28 - 0
examcloud-core-reports-base/src/main/java/cn/com/qmth/examcloud/core/reports/base/util/online/UserActive.java

@@ -0,0 +1,28 @@
+package cn.com.qmth.examcloud.core.reports.base.util.online;
+
+public class UserActive {
+	private Long rootOrgId;
+	private Long userId;
+	private Long activeTime;
+	public Long getRootOrgId() {
+		return rootOrgId;
+	}
+	public void setRootOrgId(Long rootOrgId) {
+		this.rootOrgId = rootOrgId;
+	}
+	public Long getUserId() {
+		return userId;
+	}
+	public void setUserId(Long userId) {
+		this.userId = userId;
+	}
+	public Long getActiveTime() {
+		return activeTime;
+	}
+	public void setActiveTime(Long activeTime) {
+		this.activeTime = activeTime;
+	}
+	public String getKey(String spe) {
+		return rootOrgId+spe;
+	}
+}

+ 7 - 1
examcloud-core-reports-dao/src/main/java/cn/com/qmth/examcloud/core/reports/dao/ExamStudentCountRepo.java

@@ -2,10 +2,16 @@ package cn.com.qmth.examcloud.core.reports.dao;
 
 import org.springframework.data.jpa.repository.JpaRepository;
 import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
+import org.springframework.data.jpa.repository.Modifying;
+import org.springframework.data.jpa.repository.Query;
 
 import cn.com.qmth.examcloud.core.reports.dao.entity.ExamStudentCountEntity;
 
 public interface ExamStudentCountRepo extends JpaRepository<ExamStudentCountEntity, Long>,
 		JpaSpecificationExecutor<ExamStudentCountEntity> {
-	public ExamStudentCountEntity findByRootOrgIdAndOrgIdAndExamId(Long rootOrgId,Long orgId,Long examId);
+	public ExamStudentCountEntity findByRootOrgIdAndExamId(Long rootOrgId,Long examId);
+	
+	@Modifying
+	@Query(value = "update ec_r_exam_student_count set online_count=0", nativeQuery = true)
+	public void resetAllCount();
 }

+ 15 - 1
examcloud-core-reports-dao/src/main/java/cn/com/qmth/examcloud/core/reports/dao/StudentCountRepo.java

@@ -1,11 +1,25 @@
 package cn.com.qmth.examcloud.core.reports.dao;
 
+import java.util.List;
+
 import org.springframework.data.jpa.repository.JpaRepository;
 import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
+import org.springframework.data.jpa.repository.Modifying;
+import org.springframework.data.jpa.repository.Query;
 
 import cn.com.qmth.examcloud.core.reports.dao.entity.StudentCountEntity;
 
 public interface StudentCountRepo extends JpaRepository<StudentCountEntity, Long>,
 		JpaSpecificationExecutor<StudentCountEntity> {
-	public StudentCountEntity findByRootOrgIdAndOrgId(Long rootOrgId,Long orgId);
+	public StudentCountEntity findByRootOrgId(Long rootOrgId);
+	
+	@Modifying
+	@Query(value = "update ec_r_student_count set online_count=0", nativeQuery = true)
+	public void resetAllCount();
+	
+	@Query(value = "select * from ec_r_student_count where root_org_id in(?1)", nativeQuery = true)
+	public List<StudentCountEntity> getCountByRootOrgIds(List<Long> rootOrgIds);
+	
+	@Query(value = "select sum(online_count) from ec_r_student_count", nativeQuery = true)
+	public long getSumOnlineCount();
 }

+ 12 - 0
examcloud-core-reports-dao/src/main/java/cn/com/qmth/examcloud/core/reports/dao/StudentCumulativeCountRepo.java

@@ -0,0 +1,12 @@
+package cn.com.qmth.examcloud.core.reports.dao;
+
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
+
+import cn.com.qmth.examcloud.core.reports.dao.entity.StudentCumulativeCountEntity;
+
+public interface StudentCumulativeCountRepo extends JpaRepository<StudentCumulativeCountEntity, Long>,
+		JpaSpecificationExecutor<StudentCumulativeCountEntity> {
+	public StudentCumulativeCountEntity findByRootOrgIdAndReportDay(Long rootOrgId,String reportDay);
+	
+}

+ 16 - 0
examcloud-core-reports-dao/src/main/java/cn/com/qmth/examcloud/core/reports/dao/StudentTotalCountRepo.java

@@ -0,0 +1,16 @@
+package cn.com.qmth.examcloud.core.reports.dao;
+
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
+import org.springframework.data.jpa.repository.Query;
+
+import cn.com.qmth.examcloud.core.reports.dao.entity.StudentTotalCountEntity;
+
+public interface StudentTotalCountRepo extends JpaRepository<StudentTotalCountEntity, Long>,
+		JpaSpecificationExecutor<StudentTotalCountEntity> {
+	public StudentTotalCountEntity findByRootOrgId(Long rootOrgId);
+	
+	@Query(value = "select sum(total_count) from ec_r_student_total_count", nativeQuery = true)
+	public long getSumTotalCount();
+	
+}

+ 7 - 1
examcloud-core-reports-dao/src/main/java/cn/com/qmth/examcloud/core/reports/dao/UserCountRepo.java

@@ -2,10 +2,16 @@ package cn.com.qmth.examcloud.core.reports.dao;
 
 import org.springframework.data.jpa.repository.JpaRepository;
 import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
+import org.springframework.data.jpa.repository.Modifying;
+import org.springframework.data.jpa.repository.Query;
 
 import cn.com.qmth.examcloud.core.reports.dao.entity.UserCountEntity;
 
 public interface UserCountRepo extends JpaRepository<UserCountEntity, Long>,
 		JpaSpecificationExecutor<UserCountEntity> {
-	public UserCountEntity findByRootOrgIdAndOrgId(Long rootOrgId,Long orgId);
+	public UserCountEntity findByRootOrgId(Long rootOrgId);
+	
+	@Modifying
+	@Query(value = "update ec_r_user_count set online_count=0", nativeQuery = true)
+	public void resetAllCount();
 }

+ 14 - 36
examcloud-core-reports-dao/src/main/java/cn/com/qmth/examcloud/core/reports/dao/entity/ExamStudentCountEntity.java

@@ -7,66 +7,44 @@ import javax.validation.constraints.NotNull;
 
 import cn.com.qmth.examcloud.core.reports.dao.entity.share.IdEntity;
 
-
 @Entity
-@Table(name = "ec_r_exam_student_count",indexes = {
-		@Index(name = "IDX_R_EXAM_STUDENT_COUNT_01", columnList = "rootOrgId,orgId,examId", unique = true),
-		@Index(name = "IDX_R_EXAM_STUDENT_COUNT_02", columnList = "rootOrgId", unique = false),
-		@Index(name = "IDX_R_EXAM_STUDENT_COUNT_03", columnList = "orgId", unique = false),
-		@Index(name = "IDX_R_EXAM_STUDENT_COUNT_04", columnList = "examId", unique = false),
-		@Index(name = "IDX_R_EXAM_STUDENT_COUNT_05", columnList = "batchTime", unique = false)})
+@Table(name = "ec_r_exam_student_count", indexes = {
+		@Index(name = "IDX_R_EXAM_STUDENT_COUNT_01", columnList = "rootOrgId,examId", unique = true),
+		@Index(name = "IDX_R_EXAM_STUDENT_COUNT_02", columnList = "examId", unique = false) })
 public class ExamStudentCountEntity extends IdEntity {
 
-
-    /**
+	/**
 	 * 
 	 */
 	private static final long serialVersionUID = 8818247713349613850L;
 	@NotNull
-    private Long batchTime;
+	private Long rootOrgId;
 	@NotNull
-    private Long rootOrgId;
-    @NotNull
-    private Long orgId;
-    @NotNull
-    private Long examId;
-    private Integer totalCount;
-    private Integer onlineCount;
+	private Long examId;
+	@NotNull
+	private Integer onlineCount;
+
 	public Long getRootOrgId() {
 		return rootOrgId;
 	}
+
 	public void setRootOrgId(Long rootOrgId) {
 		this.rootOrgId = rootOrgId;
 	}
-	public Long getOrgId() {
-		return orgId;
-	}
-	public void setOrgId(Long orgId) {
-		this.orgId = orgId;
-	}
-	public Integer getTotalCount() {
-		return totalCount;
-	}
-	public void setTotalCount(Integer totalCount) {
-		this.totalCount = totalCount;
-	}
+
 	public Integer getOnlineCount() {
 		return onlineCount;
 	}
+
 	public void setOnlineCount(Integer onlineCount) {
 		this.onlineCount = onlineCount;
 	}
+
 	public Long getExamId() {
 		return examId;
 	}
+
 	public void setExamId(Long examId) {
 		this.examId = examId;
 	}
-	public Long getBatchTime() {
-		return batchTime;
-	}
-	public void setBatchTime(Long batchTime) {
-		this.batchTime = batchTime;
-	}
-	
 }

+ 9 - 30
examcloud-core-reports-dao/src/main/java/cn/com/qmth/examcloud/core/reports/dao/entity/StudentCountEntity.java

@@ -7,54 +7,33 @@ import javax.validation.constraints.NotNull;
 
 import cn.com.qmth.examcloud.core.reports.dao.entity.share.IdEntity;
 
-
 @Entity
-@Table(name = "ec_r_student_count",indexes = {
-		@Index(name = "IDX_R_STUDENT_COUNT_01", columnList = "rootOrgId,orgId", unique = true),
-		@Index(name = "IDX_R_STUDENT_COUNT_02", columnList = "batchTime", unique = false)})
+@Table(name = "ec_r_student_count", indexes = {
+		@Index(name = "IDX_R_STUDENT_COUNT_01", columnList = "rootOrgId", unique = true) })
 public class StudentCountEntity extends IdEntity {
 
-    /**
+	/**
 	 * 
 	 */
 	private static final long serialVersionUID = 6732497600896224190L;
 	@NotNull
-    private Long batchTime;
+	private Long rootOrgId;
 	@NotNull
-    private Long rootOrgId;
-    @NotNull
-    private Long orgId;
-    private Integer totalCount;
-    private Integer onlineCount;
+	private Integer onlineCount;
+
 	public Long getRootOrgId() {
 		return rootOrgId;
 	}
+
 	public void setRootOrgId(Long rootOrgId) {
 		this.rootOrgId = rootOrgId;
 	}
-	public Long getOrgId() {
-		return orgId;
-	}
-	public void setOrgId(Long orgId) {
-		this.orgId = orgId;
-	}
-	public Integer getTotalCount() {
-		return totalCount;
-	}
-	public void setTotalCount(Integer totalCount) {
-		this.totalCount = totalCount;
-	}
+
 	public Integer getOnlineCount() {
 		return onlineCount;
 	}
+
 	public void setOnlineCount(Integer onlineCount) {
 		this.onlineCount = onlineCount;
 	}
-	public Long getBatchTime() {
-		return batchTime;
-	}
-	public void setBatchTime(Long batchTime) {
-		this.batchTime = batchTime;
-	}
-    
 }

+ 51 - 0
examcloud-core-reports-dao/src/main/java/cn/com/qmth/examcloud/core/reports/dao/entity/StudentCumulativeCountEntity.java

@@ -0,0 +1,51 @@
+package cn.com.qmth.examcloud.core.reports.dao.entity;
+
+import javax.persistence.Entity;
+import javax.persistence.Index;
+import javax.persistence.Table;
+import javax.validation.constraints.NotNull;
+
+import cn.com.qmth.examcloud.core.reports.dao.entity.share.IdEntity;
+
+@Entity
+@Table(name = "ec_r_student_cumulative_count", indexes = {
+		@Index(name = "IDX_R_STUDENT_CUMULATIVE_COUNT_01", columnList = "rootOrgId,reportDay", unique = true),
+		@Index(name = "IDX_R_STUDENT_CUMULATIVE_COUNT_02", columnList = "reportDay", unique = false)})
+public class StudentCumulativeCountEntity extends IdEntity {
+	/**
+	 * 
+	 */
+	private static final long serialVersionUID = -7619316177918217328L;
+	@NotNull
+	private Long rootOrgId;
+	@NotNull
+	private Integer totalCount;
+	@NotNull
+	private String reportDay;
+
+	public Long getRootOrgId() {
+		return rootOrgId;
+	}
+
+	public void setRootOrgId(Long rootOrgId) {
+		this.rootOrgId = rootOrgId;
+	}
+
+	public Integer getTotalCount() {
+		return totalCount;
+	}
+
+	public void setTotalCount(Integer totalCount) {
+		this.totalCount = totalCount;
+	}
+
+	public String getReportDay() {
+		return reportDay;
+	}
+
+	public void setReportDay(String reportDay) {
+		this.reportDay = reportDay;
+	}
+	
+	
+}

+ 38 - 0
examcloud-core-reports-dao/src/main/java/cn/com/qmth/examcloud/core/reports/dao/entity/StudentTotalCountEntity.java

@@ -0,0 +1,38 @@
+package cn.com.qmth.examcloud.core.reports.dao.entity;
+
+import javax.persistence.Entity;
+import javax.persistence.Index;
+import javax.persistence.Table;
+import javax.validation.constraints.NotNull;
+
+import cn.com.qmth.examcloud.core.reports.dao.entity.share.IdEntity;
+
+@Entity
+@Table(name = "ec_r_student_total_count", indexes = {
+		@Index(name = "IDX_R_STUDENT_TOTAL_COUNT_01", columnList = "rootOrgId", unique = true) })
+public class StudentTotalCountEntity extends IdEntity {
+	/**
+	 * 
+	 */
+	private static final long serialVersionUID = 4690035104380375292L;
+	@NotNull
+	private Long rootOrgId;
+	@NotNull
+	private Integer totalCount;
+
+	public Long getRootOrgId() {
+		return rootOrgId;
+	}
+
+	public void setRootOrgId(Long rootOrgId) {
+		this.rootOrgId = rootOrgId;
+	}
+
+	public Integer getTotalCount() {
+		return totalCount;
+	}
+
+	public void setTotalCount(Integer totalCount) {
+		this.totalCount = totalCount;
+	}
+}

+ 2 - 25
examcloud-core-reports-dao/src/main/java/cn/com/qmth/examcloud/core/reports/dao/entity/UserCountEntity.java

@@ -10,8 +10,7 @@ import cn.com.qmth.examcloud.core.reports.dao.entity.share.IdEntity;
 
 @Entity
 @Table(name = "ec_r_user_count",indexes = {
-		@Index(name = "IDX_R_USER_COUNT_01", columnList = "rootOrgId,orgId", unique = true),
-		@Index(name = "IDX_R_USER_COUNT_02", columnList = "batchTime", unique = false)})
+		@Index(name = "IDX_R_USER_COUNT_01", columnList = "rootOrgId", unique = true)})
 public class UserCountEntity extends IdEntity {
 
 
@@ -20,13 +19,10 @@ public class UserCountEntity extends IdEntity {
 	 * 
 	 */
 	private static final long serialVersionUID = -6420107706111319346L;
-	@NotNull
-    private Long batchTime;
     @NotNull
     private Long rootOrgId;
+    
     @NotNull
-    private Long orgId;
-    private Integer totalCount;
     private Integer onlineCount;
 	public Long getRootOrgId() {
 		return rootOrgId;
@@ -34,29 +30,10 @@ public class UserCountEntity extends IdEntity {
 	public void setRootOrgId(Long rootOrgId) {
 		this.rootOrgId = rootOrgId;
 	}
-	public Long getOrgId() {
-		return orgId;
-	}
-	public void setOrgId(Long orgId) {
-		this.orgId = orgId;
-	}
-	public Integer getTotalCount() {
-		return totalCount;
-	}
-	public void setTotalCount(Integer totalCount) {
-		this.totalCount = totalCount;
-	}
 	public Integer getOnlineCount() {
 		return onlineCount;
 	}
 	public void setOnlineCount(Integer onlineCount) {
 		this.onlineCount = onlineCount;
 	}
-	public Long getBatchTime() {
-		return batchTime;
-	}
-	public void setBatchTime(Long batchTime) {
-		this.batchTime = batchTime;
-	}
-    
 }

+ 1 - 3
examcloud-core-reports-service/src/main/java/cn/com/qmth/examcloud/core/reports/service/ExamStudentCountService.java

@@ -1,8 +1,6 @@
 package cn.com.qmth.examcloud.core.reports.service;
 
-import cn.com.qmth.examcloud.core.reports.api.request.AddOrUpdateExamStudentCountReq;
-
 public interface ExamStudentCountService {
-	public void addOrUpdateCount(AddOrUpdateExamStudentCountReq req);
+	public void saveCount();
 	public Long getOnlineCount(Long rootOrgId,Long orgId,Long examId);
 }

+ 6 - 3
examcloud-core-reports-service/src/main/java/cn/com/qmth/examcloud/core/reports/service/StudentCountService.java

@@ -1,8 +1,11 @@
 package cn.com.qmth.examcloud.core.reports.service;
 
-import cn.com.qmth.examcloud.core.reports.api.request.AddOrUpdateStudentCountReq;
+import java.util.List;
+
+import cn.com.qmth.examcloud.core.reports.base.bean.StudentCountBean;
 
 public interface StudentCountService {
-	public void addOrUpdateCount(AddOrUpdateStudentCountReq req);
-	public Long getOnlineCount(Long rootOrgId,Long orgId);
+	public void saveCount();
+	public List<StudentCountBean> getCountByRootOrgIds(List<Long> rootOrgIds);
+	public Long getSumOnlineCount();
 }

+ 10 - 0
examcloud-core-reports-service/src/main/java/cn/com/qmth/examcloud/core/reports/service/StudentCumulativeCountService.java

@@ -0,0 +1,10 @@
+package cn.com.qmth.examcloud.core.reports.service;
+
+import java.util.List;
+
+import cn.com.qmth.examcloud.core.reports.base.bean.StudentCumulativeCountBean;
+
+public interface StudentCumulativeCountService {
+	public void saveCount();
+	public List<StudentCumulativeCountBean> getLastNdayOnlineCount(Integer nday);
+}

+ 12 - 0
examcloud-core-reports-service/src/main/java/cn/com/qmth/examcloud/core/reports/service/StudentTotalCountService.java

@@ -0,0 +1,12 @@
+package cn.com.qmth.examcloud.core.reports.service;
+
+import cn.com.qmth.examcloud.api.commons.exchange.PageInfo;
+import cn.com.qmth.examcloud.core.reports.base.bean.StudentCountBean;
+
+public interface StudentTotalCountService {
+	public void compute();
+
+	public Long getSumTotalCount();
+
+	public PageInfo<StudentCountBean> queryPage(String rootOrgId, Integer pageNo, Integer pageSize);
+}

+ 1 - 3
examcloud-core-reports-service/src/main/java/cn/com/qmth/examcloud/core/reports/service/UserCountService.java

@@ -1,8 +1,6 @@
 package cn.com.qmth.examcloud.core.reports.service;
 
-import cn.com.qmth.examcloud.core.reports.api.request.AddOrUpdateUserCountReq;
-
 public interface UserCountService {
-	public void addOrUpdateCount(AddOrUpdateUserCountReq req);
+	public void saveCount();
 	public Long getOnlineCount(Long rootOrgId,Long orgId);
 }

+ 32 - 16
examcloud-core-reports-service/src/main/java/cn/com/qmth/examcloud/core/reports/service/impl/ExamStudentCountServiceImpl.java

@@ -1,10 +1,15 @@
 package cn.com.qmth.examcloud.core.reports.service.impl;
 
+import java.util.Date;
+import java.util.List;
+
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.jdbc.core.JdbcTemplate;
 import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
 
-import cn.com.qmth.examcloud.core.reports.api.request.AddOrUpdateExamStudentCountReq;
+import cn.com.qmth.examcloud.core.reports.base.util.online.ActiveDataUtil;
+import cn.com.qmth.examcloud.core.reports.base.util.online.OnlineCount;
 import cn.com.qmth.examcloud.core.reports.dao.ExamStudentCountRepo;
 import cn.com.qmth.examcloud.core.reports.dao.entity.ExamStudentCountEntity;
 import cn.com.qmth.examcloud.core.reports.service.ExamStudentCountService;
@@ -16,26 +21,11 @@ public class ExamStudentCountServiceImpl implements ExamStudentCountService {
 	@Autowired
 	private JdbcTemplate jdbcTemplate;
 
-	@Override
-	public void addOrUpdateCount(AddOrUpdateExamStudentCountReq req) {
-		ExamStudentCountEntity e = examStudentCountRepo.findByRootOrgIdAndOrgIdAndExamId(req.getRootOrgId(),
-				req.getOrgId(), req.getExamId());
-		if (e == null) {
-			e = new ExamStudentCountEntity();
-			e.setRootOrgId(req.getRootOrgId());
-			e.setOrgId(req.getOrgId());
-			e.setExamId(req.getExamId());
-		}
-		e.setBatchTime(req.getBatchTime());
-		e.setOnlineCount(req.getOnlineCount());
-		examStudentCountRepo.save(e);
-	}
 
 	@Override
 	public Long getOnlineCount(Long rootOrgId, Long orgId, Long examId) {
 		StringBuffer sb = new StringBuffer();
 		sb.append(" select sum(t.online_count) from ec_r_exam_student_count t where t.root_org_id=").append(rootOrgId);
-		sb.append(" and t.batch_time=(select f.batch_time from ec_r_exam_student_count f order by f.batch_time desc limit 1) ");
 		if (orgId != null) {
 			sb.append(" and t.org_id=").append(orgId);
 		}
@@ -48,4 +38,30 @@ public class ExamStudentCountServiceImpl implements ExamStudentCountService {
 		}
 		return count;
 	}
+
+	@Transactional
+	@Override
+	public synchronized void  saveCount() {
+		examStudentCountRepo.resetAllCount();
+		List<OnlineCount> ret=ActiveDataUtil.getExamStudentCount(null);
+		if(ret!=null) {
+			for(OnlineCount oc:ret) {
+				addOrUpdateCount(oc);
+			}
+		}
+	}
+	
+	private void addOrUpdateCount(OnlineCount oc) {
+		ExamStudentCountEntity e = examStudentCountRepo.findByRootOrgIdAndExamId(oc.getRootOrgId(),oc.getExamId());
+		if (e == null) {
+			e = new ExamStudentCountEntity();
+			e.setRootOrgId(oc.getRootOrgId());
+			e.setExamId(oc.getExamId());
+			Date now=new Date();
+			e.setCreationTime(now);
+			e.setUpdateTime(now);
+		}
+		e.setOnlineCount(oc.getOnlineCount());
+		examStudentCountRepo.save(e);
+	}
 }

+ 48 - 20
examcloud-core-reports-service/src/main/java/cn/com/qmth/examcloud/core/reports/service/impl/StudentCountServiceImpl.java

@@ -1,10 +1,18 @@
 package cn.com.qmth.examcloud.core.reports.service.impl;
 
+import java.util.Date;
+import java.util.List;
+
+import org.apache.commons.collections.CollectionUtils;
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.jdbc.core.JdbcTemplate;
 import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import com.google.common.collect.Lists;
 
-import cn.com.qmth.examcloud.core.reports.api.request.AddOrUpdateStudentCountReq;
+import cn.com.qmth.examcloud.core.reports.base.bean.StudentCountBean;
+import cn.com.qmth.examcloud.core.reports.base.util.online.ActiveDataUtil;
+import cn.com.qmth.examcloud.core.reports.base.util.online.OnlineCount;
 import cn.com.qmth.examcloud.core.reports.dao.StudentCountRepo;
 import cn.com.qmth.examcloud.core.reports.dao.entity.StudentCountEntity;
 import cn.com.qmth.examcloud.core.reports.service.StudentCountService;
@@ -13,34 +21,54 @@ import cn.com.qmth.examcloud.core.reports.service.StudentCountService;
 public class StudentCountServiceImpl implements StudentCountService {
 	@Autowired
 	private StudentCountRepo studentCountRepo;
-	@Autowired
-	private JdbcTemplate jdbcTemplate;
 
+
+	@Transactional
 	@Override
-	public void addOrUpdateCount(AddOrUpdateStudentCountReq req) {
-		StudentCountEntity e = studentCountRepo.findByRootOrgIdAndOrgId(req.getRootOrgId(), req.getOrgId());
+	public synchronized void saveCount() {
+		studentCountRepo.resetAllCount();
+		List<OnlineCount> ret = ActiveDataUtil.getStudentCount(null);
+		if (ret != null) {
+			for (OnlineCount oc : ret) {
+				addOrUpdateCount(oc);
+			}
+		}
+	}
+
+	private void addOrUpdateCount(OnlineCount oc) {
+		StudentCountEntity e = studentCountRepo.findByRootOrgId(oc.getRootOrgId());
 		if (e == null) {
 			e = new StudentCountEntity();
-			e.setRootOrgId(req.getRootOrgId());
-			e.setOrgId(req.getOrgId());
+			e.setRootOrgId(oc.getRootOrgId());
+			Date now = new Date();
+			e.setCreationTime(now);
+			e.setUpdateTime(now);
 		}
-		e.setBatchTime(req.getBatchTime());
-		e.setOnlineCount(req.getOnlineCount());
+		e.setOnlineCount(oc.getOnlineCount());
 		studentCountRepo.save(e);
 	}
 
 	@Override
-	public Long getOnlineCount(Long rootOrgId, Long orgId) {
-		StringBuffer sb = new StringBuffer();
-		sb.append(" select sum(t.online_count) from ec_r_student_count t where t.root_org_id=").append(rootOrgId);
-		sb.append(" and t.batch_time=(select f.batch_time from ec_r_student_count f order by f.batch_time desc limit 1) ");
-		if (orgId != null) {
-			sb.append(" and t.org_id=").append(orgId);
+	public List<StudentCountBean> getCountByRootOrgIds(List<Long> rootOrgIds) {
+		if (CollectionUtils.isEmpty(rootOrgIds)) {
+			return null;
+		}
+		List<StudentCountEntity> list = studentCountRepo.getCountByRootOrgIds(rootOrgIds);
+		if (CollectionUtils.isEmpty(list)) {
+			return null;
 		}
-		Long count = jdbcTemplate.queryForObject(sb.toString(), Long.class);
-		if (count == null) {
-			count = 0l;
+		List<StudentCountBean> ret = Lists.newArrayList();
+		for (StudentCountEntity e : list) {
+			StudentCountBean bean = new StudentCountBean();
+			bean.setRootOrgId(e.getRootOrgId());
+			bean.setOnlineCount(e.getOnlineCount());
+			ret.add(bean);
 		}
-		return count;
+		return ret;
+	}
+
+	@Override
+	public Long getSumOnlineCount() {
+		return studentCountRepo.getSumOnlineCount();
 	}
 }

+ 139 - 0
examcloud-core-reports-service/src/main/java/cn/com/qmth/examcloud/core/reports/service/impl/StudentCumulativeCountServiceImpl.java

@@ -0,0 +1,139 @@
+package cn.com.qmth.examcloud.core.reports.service.impl;
+
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.lang3.time.DateUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.jdbc.core.BeanPropertyRowMapper;
+import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.jdbc.core.RowMapper;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import com.google.common.collect.Lists;
+
+import cn.com.qmth.examcloud.commons.exception.StatusException;
+import cn.com.qmth.examcloud.commons.util.DateUtil;
+import cn.com.qmth.examcloud.core.reports.base.bean.StudentCumulativeCountBean;
+import cn.com.qmth.examcloud.core.reports.base.util.online.ActiveDataUtil;
+import cn.com.qmth.examcloud.core.reports.base.util.online.OnlineCount;
+import cn.com.qmth.examcloud.core.reports.dao.StudentCumulativeCountRepo;
+import cn.com.qmth.examcloud.core.reports.dao.entity.StudentCumulativeCountEntity;
+import cn.com.qmth.examcloud.core.reports.service.StudentCumulativeCountService;
+
+@Service
+public class StudentCumulativeCountServiceImpl implements StudentCumulativeCountService {
+	@Autowired
+	private StudentCumulativeCountRepo studentCumulativeCountRepo;
+	@Autowired
+	private JdbcTemplate jdbcTemplate;
+
+	@Transactional
+	@Override
+	public synchronized void saveCount() {
+		// 取当前人数累计数据
+		List<OnlineCount> ret = ActiveDataUtil.getStudentLoginCount();
+		// 判断StudentLoginDataReportDay跟当前系统日期是否一致,不一致说明到了第二天,累计数据需要清空
+		Date now = new Date();
+		Date last = DateUtils.addDays(now, -1);
+		String lastday = DateUtil.format(last, DateUtil.DatePatterns.YYYY_MM_DD);
+		String today = DateUtil.format(now, DateUtil.DatePatterns.YYYY_MM_DD);
+		boolean isTomorrow = !today.equals(ActiveDataUtil.getStudentLoginDataReportDay());
+		if (isTomorrow) {
+			ActiveDataUtil.clearStudentLoginCount();
+		}
+
+		if (ret != null) {
+			for (OnlineCount oc : ret) {
+				addOrUpdateCount(oc, lastday, today, isTomorrow);
+			}
+		}
+	}
+
+	private void addOrUpdateCount(OnlineCount oc, String lastday, String today, boolean isTomorrow) {
+		if (isTomorrow) {
+			// 第二天
+			StudentCumulativeCountEntity oe = studentCumulativeCountRepo.findByRootOrgIdAndReportDay(oc.getRootOrgId(),
+					lastday);
+			if (oe != null) {
+				// 更新昨天的数据
+				oe.setTotalCount(oc.getOnlineCount());
+				studentCumulativeCountRepo.save(oe);
+			}
+			// 插入一条人数为零的今天数据
+			StudentCumulativeCountEntity e = new StudentCumulativeCountEntity();
+			e.setRootOrgId(oc.getRootOrgId());
+			e.setTotalCount(0);
+			e.setReportDay(today);
+			Date now = new Date();
+			e.setCreationTime(now);
+			e.setUpdateTime(now);
+			studentCumulativeCountRepo.save(e);
+		} else {
+			// 今天 插入或更新一条当前人数的今天数据
+			StudentCumulativeCountEntity e = studentCumulativeCountRepo.findByRootOrgIdAndReportDay(oc.getRootOrgId(),
+					today);
+			if (e == null) {
+				e = new StudentCumulativeCountEntity();
+				e.setRootOrgId(oc.getRootOrgId());
+				e.setReportDay(today);
+				Date now = new Date();
+				e.setCreationTime(now);
+				e.setUpdateTime(now);
+			}
+			e.setTotalCount(oc.getOnlineCount());
+			studentCumulativeCountRepo.save(e);
+		}
+	}
+
+	@Override
+	public List<StudentCumulativeCountBean> getLastNdayOnlineCount(Integer nday) {
+		if (nday < 1 || nday > 100) {
+			throw new StatusException("100001", "查询天数1到100之间");
+		}
+		List<String> ds=getDays(nday);
+		StringBuffer sb = new StringBuffer();
+		sb.append(" select sum(t.total_count) totalCount,t.report_day reportDay from ec_r_student_cumulative_count t where t.report_day in ('-1'");
+		for (String d:ds) {
+			sb.append(",'").append(d).append("'");
+		}
+		sb.append(") group by t.report_day");
+		RowMapper<StudentCumulativeCountBean> rowMapper=new BeanPropertyRowMapper<StudentCumulativeCountBean>(StudentCumulativeCountBean.class);
+		List<StudentCumulativeCountBean> ret = jdbcTemplate.query(sb.toString(), rowMapper);
+		
+		List<StudentCumulativeCountBean> initList=getInitList(ds);
+		if (CollectionUtils.isNotEmpty(ret)) {
+			Map<String, Integer> map = ret.stream().collect(Collectors.toMap(StudentCumulativeCountBean::getReportDay,
+					account -> account.getTotalCount(), (key1, key2) -> key2));
+			for(StudentCumulativeCountBean b:initList) {
+				Integer c=map.get(b.getReportDay());
+				b.setTotalCount(c==null?0:c);
+			}
+		}
+		return initList;
+	}
+	private List<StudentCumulativeCountBean> getInitList(List<String> ds) {
+		List<StudentCumulativeCountBean> ret = Lists.newArrayList();
+		for(String d:ds) {
+			StudentCumulativeCountBean sb=new StudentCumulativeCountBean();
+			sb.setReportDay(d);
+			sb.setTotalCount(0);
+			ret.add(sb);
+		}
+		return ret;
+	}
+	private List<String> getDays(Integer nday) {
+		List<String> ds = Lists.newArrayList();
+		Date now = new Date();
+		for (int i = nday; i > 0; i--) {
+			Date day = DateUtils.addDays(now, 1-i);
+			String daystr = DateUtil.format(day, DateUtil.DatePatterns.YYYY_MM_DD);
+			ds.add(daystr);
+		}
+		return ds;
+	}
+}

+ 125 - 0
examcloud-core-reports-service/src/main/java/cn/com/qmth/examcloud/core/reports/service/impl/StudentTotalCountServiceImpl.java

@@ -0,0 +1,125 @@
+package cn.com.qmth.examcloud.core.reports.service.impl;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+import javax.persistence.criteria.Predicate;
+
+import org.apache.commons.collections.CollectionUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.PageRequest;
+import org.springframework.data.domain.Sort;
+import org.springframework.data.domain.Sort.Direction;
+import org.springframework.data.jpa.domain.Specification;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import com.google.common.collect.Lists;
+
+import cn.com.qmth.examcloud.api.commons.exchange.PageInfo;
+import cn.com.qmth.examcloud.core.basic.api.OrgCloudService;
+import cn.com.qmth.examcloud.core.basic.api.bean.OrgBean;
+import cn.com.qmth.examcloud.core.basic.api.request.GetOrgsByIdListReq;
+import cn.com.qmth.examcloud.core.basic.api.response.GetOrgsByIdListResp;
+import cn.com.qmth.examcloud.core.reports.base.bean.StudentCountBean;
+import cn.com.qmth.examcloud.core.reports.base.util.BatchGetDataUtil;
+import cn.com.qmth.examcloud.core.reports.dao.StudentTotalCountRepo;
+import cn.com.qmth.examcloud.core.reports.dao.entity.StudentTotalCountEntity;
+import cn.com.qmth.examcloud.core.reports.service.StudentCountService;
+import cn.com.qmth.examcloud.core.reports.service.StudentTotalCountService;
+
+@Service
+public class StudentTotalCountServiceImpl implements StudentTotalCountService {
+	@Autowired
+	private StudentTotalCountRepo studentTotalCountRepo;
+	@Autowired
+	private StudentCountService studentCountService;
+	@Autowired
+	private OrgCloudService orgCloudService;
+
+	@Transactional
+	@Override
+	public synchronized void compute() {
+		// TODO
+	}
+
+	@Override
+	public Long getSumTotalCount() {
+		return studentTotalCountRepo.getSumTotalCount();
+	}
+
+	@Override
+	public PageInfo<StudentCountBean> queryPage(String rootOrgId, Integer pageNo, Integer pageSize) {
+		Specification<StudentTotalCountEntity> specification = (root, query, cb) -> {
+			List<Predicate> predicates = new ArrayList<>();
+			if (null != rootOrgId) {
+				predicates.add(cb.equal(root.get("rootOrgId"), rootOrgId));
+			}
+
+			return cb.and(predicates.toArray(new Predicate[predicates.size()]));
+		};
+
+		PageRequest pageRequest = PageRequest.of(pageNo - 1, pageSize, new Sort(Direction.DESC, "id"));
+
+		Page<StudentTotalCountEntity> es = studentTotalCountRepo.findAll(specification, pageRequest);
+
+		List<StudentCountBean> ret = Lists.newArrayList();
+
+		for (StudentTotalCountEntity cur : es) {
+			StudentCountBean bean = new StudentCountBean();
+			bean.setTotalCount(cur.getTotalCount());
+			bean.setRootOrgId(cur.getRootOrgId());
+			ret.add(bean);
+		}
+		fillOnlineCount(ret);
+		fillRootOrgName(ret);
+		return new PageInfo<StudentCountBean>(es, ret);
+	}
+
+	private void fillOnlineCount(List<StudentCountBean> ret) {
+		if (CollectionUtils.isEmpty(ret)) {
+			return;
+		}
+		List<Long> temList = ret.stream().map(str -> str.getRootOrgId()).collect(Collectors.toList());
+		List<StudentCountBean> sl = studentCountService.getCountByRootOrgIds(temList);
+		if (CollectionUtils.isEmpty(sl)) {
+			return;
+		}
+		Map<Long, Integer> map = sl.stream().collect(Collectors.toMap(StudentCountBean::getRootOrgId,
+				account -> account.getOnlineCount(), (key1, key2) -> key2));
+		for(StudentCountBean b:ret) {
+			b.setOnlineCount(map.get(b.getRootOrgId()));
+		}
+	}
+
+	private void fillRootOrgName(List<StudentCountBean> ret) {
+		if (CollectionUtils.isEmpty(ret)) {
+			return;
+		}
+		List<Long> param = ret.stream().map(str -> str.getRootOrgId()).collect(Collectors.toList());
+		List<OrgBean> retList=new ArrayList<OrgBean>();
+		GetOrgsByIdListReq req= new GetOrgsByIdListReq();
+		BatchGetDataUtil<OrgBean, Long> tool = new BatchGetDataUtil<OrgBean, Long>() {
+			@Override
+			public List<OrgBean> getData(List<Long> paramList) {
+				
+				req.setOrgIdList(paramList);
+				GetOrgsByIdListResp resp=orgCloudService.getOrgsByIdList(req);
+				return resp.getOrgList();
+			}
+
+		};
+		tool.getDataForBatch(retList, param, 100);
+		if (CollectionUtils.isEmpty(retList)) {
+			return;
+		}
+		Map<Long, String> map = retList.stream().collect(Collectors.toMap(OrgBean::getId,
+				account -> account.getName(), (key1, key2) -> key2));
+		for(StudentCountBean b:ret) {
+			b.setRootOrgName(map.get(b.getRootOrgId()));
+		}
+	}
+}

+ 36 - 19
examcloud-core-reports-service/src/main/java/cn/com/qmth/examcloud/core/reports/service/impl/UserCountServiceImpl.java

@@ -1,10 +1,15 @@
 package cn.com.qmth.examcloud.core.reports.service.impl;
 
+import java.util.Date;
+import java.util.List;
+
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.jdbc.core.JdbcTemplate;
 import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
 
-import cn.com.qmth.examcloud.core.reports.api.request.AddOrUpdateUserCountReq;
+import cn.com.qmth.examcloud.core.reports.base.util.online.ActiveDataUtil;
+import cn.com.qmth.examcloud.core.reports.base.util.online.OnlineCount;
 import cn.com.qmth.examcloud.core.reports.dao.UserCountRepo;
 import cn.com.qmth.examcloud.core.reports.dao.entity.UserCountEntity;
 import cn.com.qmth.examcloud.core.reports.service.UserCountService;
@@ -15,31 +20,43 @@ public class UserCountServiceImpl implements UserCountService {
 	private UserCountRepo userCountRepo;
 	@Autowired
 	private JdbcTemplate jdbcTemplate;
-	@Override
-	public void addOrUpdateCount(AddOrUpdateUserCountReq req) {
-		UserCountEntity e=userCountRepo.findByRootOrgIdAndOrgId(req.getRootOrgId(), req.getOrgId());
-		if(e==null) {
-			e=new UserCountEntity();
-			e.setRootOrgId(req.getRootOrgId());
-			e.setOrgId(req.getOrgId());
-		}
-		e.setBatchTime(req.getBatchTime());
-		e.setOnlineCount(req.getOnlineCount());
-		userCountRepo.save(e);
-	}
 
 	@Override
 	public Long getOnlineCount(Long rootOrgId, Long orgId) {
-		StringBuffer sb=new StringBuffer();
+		StringBuffer sb = new StringBuffer();
 		sb.append(" select sum(t.online_count) from ec_r_user_count t where t.root_org_id=").append(rootOrgId);
-		sb.append(" and t.batch_time=(select f.batch_time from ec_r_user_count f order by f.batch_time desc limit 1) ");
-		if(orgId!=null) {
+		if (orgId != null) {
 			sb.append(" and t.org_id=").append(orgId);
 		}
-		Long count=jdbcTemplate.queryForObject(sb.toString(), Long.class);
-		if(count==null) {
-			count=0l;
+		Long count = jdbcTemplate.queryForObject(sb.toString(), Long.class);
+		if (count == null) {
+			count = 0l;
 		}
 		return count;
 	}
+
+	@Transactional
+	@Override
+	public synchronized void saveCount() {
+		userCountRepo.resetAllCount();
+		List<OnlineCount> ret = ActiveDataUtil.getUserCount(null);
+		if (ret != null) {
+			for (OnlineCount oc : ret) {
+				addOrUpdateCount(oc);
+			}
+		}
+	}
+
+	private void addOrUpdateCount(OnlineCount oc) {
+		UserCountEntity e = userCountRepo.findByRootOrgId(oc.getRootOrgId());
+		if (e == null) {
+			e = new UserCountEntity();
+			e.setRootOrgId(oc.getRootOrgId());
+			Date now=new Date();
+			e.setCreationTime(now);
+			e.setUpdateTime(now);
+		}
+		e.setOnlineCount(oc.getOnlineCount());
+		userCountRepo.save(e);
+	}
 }

+ 41 - 0
examcloud-core-reports-starter/src/main/java/cn/com/qmth/examcloud/core/reports/starter/config/MqConsumerListenerStartup.java

@@ -0,0 +1,41 @@
+package cn.com.qmth.examcloud.core.reports.starter.config;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.boot.ApplicationArguments;
+import org.springframework.boot.ApplicationRunner;
+import org.springframework.core.annotation.Order;
+import org.springframework.stereotype.Component;
+
+import cn.com.qmth.examcloud.core.reports.api.listener.KafkaConsumerListener;
+import cn.com.qmth.examcloud.core.reports.api.listener.RocketMqConsumerListener;
+import cn.com.qmth.examcloud.reports.commons.enums.MqType;
+import cn.com.qmth.examcloud.web.bootstrap.PropertyHolder;
+
+@Component
+@Order(99)
+public class MqConsumerListenerStartup implements ApplicationRunner {
+	private final static Logger logger = LoggerFactory.getLogger(MqConsumerListenerStartup.class);
+	public void start() {
+
+		String mqType = PropertyHolder.getString("$report.mq-type");
+
+		Boolean reportEnable = PropertyHolder.getBoolean("$report.enable", false);
+
+		if (reportEnable) {
+			if(MqType.KAFKA.getCode().equals(mqType)) {
+				KafkaConsumerListener.start();
+			}else if(MqType.ROCKETMQ.getCode().equals(mqType)) {
+				RocketMqConsumerListener.start();
+			}else {
+				logger.error("no $report.mq-type property config!");
+			}
+		}
+
+	}
+
+	@Override
+	public void run(ApplicationArguments args) throws Exception {
+		start();
+	}
+}