You've already forked FrameTour-BE
对景区摄像头进行统计
This commit is contained in:
@ -0,0 +1,23 @@
|
|||||||
|
package com.ycwl.basic.controller.pc;
|
||||||
|
|
||||||
|
import com.ycwl.basic.model.pc.scenicDeviceStats.req.DeviceStatsReq;
|
||||||
|
import com.ycwl.basic.model.pc.scenicDeviceStats.resp.ScenicDeviceStatsListResp;
|
||||||
|
import com.ycwl.basic.utils.ApiResponse;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.web.bind.annotation.PathVariable;
|
||||||
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestBody;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/api/deviceStats/v1")
|
||||||
|
public class DeviceStatsController {
|
||||||
|
@Autowired
|
||||||
|
private com.ycwl.basic.service.pc.DeviceStatsService service;
|
||||||
|
|
||||||
|
@PostMapping("/{scenicId}")
|
||||||
|
public ApiResponse<ScenicDeviceStatsListResp> queryByScenic(@PathVariable("scenicId") Long scenicId, @RequestBody DeviceStatsReq req) {
|
||||||
|
return ApiResponse.success(service.queryByScenicId(scenicId, req.getStartTime(), req.getEndTime()));
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,25 @@
|
|||||||
|
package com.ycwl.basic.mapper;
|
||||||
|
|
||||||
|
import com.ycwl.basic.model.pc.scenicDeviceStats.entity.ScenicDeviceStatsEntity;
|
||||||
|
import com.ycwl.basic.model.pc.scenicDeviceStats.resp.ScenicDeviceStatsResp;
|
||||||
|
import org.apache.ibatis.annotations.Param;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 景区设备统计Mapper接口
|
||||||
|
*/
|
||||||
|
public interface ScenicDeviceStatsMapper {
|
||||||
|
/**
|
||||||
|
* 插入景区设备统计记录
|
||||||
|
* @param stats 景区设备统计对象
|
||||||
|
* @return 影响行数
|
||||||
|
*/
|
||||||
|
int insert(@Param("stats") ScenicDeviceStatsEntity stats);
|
||||||
|
|
||||||
|
List<ScenicDeviceStatsEntity> countDeviceStats(Date start, Date end);
|
||||||
|
|
||||||
|
List<ScenicDeviceStatsResp> countCachedStatsByScenicId(Long scenicId, Date start, Date end);
|
||||||
|
List<ScenicDeviceStatsResp> countRealtimeStatsByScenicId(Long scenicId, Date start, Date end);
|
||||||
|
}
|
@ -0,0 +1,16 @@
|
|||||||
|
package com.ycwl.basic.model.pc.scenicDeviceStats.entity;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 景区设备统计实体类
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class ScenicDeviceStatsEntity {
|
||||||
|
private Long scenicId;
|
||||||
|
private Long deviceId;
|
||||||
|
private Date date;
|
||||||
|
private Integer count;
|
||||||
|
}
|
@ -0,0 +1,11 @@
|
|||||||
|
package com.ycwl.basic.model.pc.scenicDeviceStats.req;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class DeviceStatsReq {
|
||||||
|
private Date startTime;
|
||||||
|
private Date endTime;
|
||||||
|
}
|
@ -0,0 +1,11 @@
|
|||||||
|
package com.ycwl.basic.model.pc.scenicDeviceStats.resp;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class ScenicDeviceStatsListResp {
|
||||||
|
private List<ScenicDeviceStatsResp> data;
|
||||||
|
private boolean realtime;
|
||||||
|
}
|
@ -0,0 +1,17 @@
|
|||||||
|
package com.ycwl.basic.model.pc.scenicDeviceStats.resp;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class ScenicDeviceStatsResp {
|
||||||
|
private Long scenicId;
|
||||||
|
private String scenicName;
|
||||||
|
private Long deviceId;
|
||||||
|
private String deviceName;
|
||||||
|
private Integer count;
|
||||||
|
private BigDecimal rate;
|
||||||
|
}
|
@ -0,0 +1,9 @@
|
|||||||
|
package com.ycwl.basic.service.pc;
|
||||||
|
|
||||||
|
import com.ycwl.basic.model.pc.scenicDeviceStats.resp.ScenicDeviceStatsListResp;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
public interface DeviceStatsService {
|
||||||
|
ScenicDeviceStatsListResp queryByScenicId(Long scenicId, Date start, Date end);
|
||||||
|
}
|
@ -0,0 +1,46 @@
|
|||||||
|
package com.ycwl.basic.service.pc.impl;
|
||||||
|
|
||||||
|
import cn.hutool.core.date.DateUtil;
|
||||||
|
import com.ycwl.basic.mapper.ScenicDeviceStatsMapper;
|
||||||
|
import com.ycwl.basic.model.pc.scenicDeviceStats.resp.ScenicDeviceStatsListResp;
|
||||||
|
import com.ycwl.basic.model.pc.scenicDeviceStats.resp.ScenicDeviceStatsResp;
|
||||||
|
import com.ycwl.basic.service.pc.DeviceStatsService;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.math.RoundingMode;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class DeviceStatsServiceImpl implements DeviceStatsService {
|
||||||
|
@Autowired
|
||||||
|
private ScenicDeviceStatsMapper mapper;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ScenicDeviceStatsListResp queryByScenicId(Long scenicId, Date start, Date end) {
|
||||||
|
if (start == null) {
|
||||||
|
start = DateUtil.beginOfDay(new Date());
|
||||||
|
}
|
||||||
|
if (end == null) {
|
||||||
|
end = DateUtil.endOfDay(new Date());
|
||||||
|
}
|
||||||
|
ScenicDeviceStatsListResp resp = new ScenicDeviceStatsListResp();
|
||||||
|
if (DateUtil.isIn(start, DateUtil.tomorrow(), DateUtil.yesterday()) && DateUtil.isIn(start, DateUtil.tomorrow(), DateUtil.yesterday())) {
|
||||||
|
resp.setRealtime(true);
|
||||||
|
List<ScenicDeviceStatsResp> data = mapper.countRealtimeStatsByScenicId(scenicId, start, end);
|
||||||
|
resp.setData(data);
|
||||||
|
} else {
|
||||||
|
resp.setRealtime(false);
|
||||||
|
List<ScenicDeviceStatsResp> data = mapper.countCachedStatsByScenicId(scenicId, start, end);
|
||||||
|
resp.setData(data);
|
||||||
|
}
|
||||||
|
resp.getData().stream().mapToInt(ScenicDeviceStatsResp::getCount).max().ifPresent((max) -> {
|
||||||
|
resp.getData().forEach(item -> {
|
||||||
|
item.setRate(BigDecimal.valueOf(item.getCount()).divide(BigDecimal.valueOf(max), 6, RoundingMode.HALF_UP).multiply(BigDecimal.valueOf(100)));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
return resp;
|
||||||
|
}
|
||||||
|
}
|
41
src/main/java/com/ycwl/basic/task/ScenicDeviceStatsTask.java
Normal file
41
src/main/java/com/ycwl/basic/task/ScenicDeviceStatsTask.java
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
package com.ycwl.basic.task;
|
||||||
|
|
||||||
|
import cn.hutool.core.date.DateUtil;
|
||||||
|
import com.ycwl.basic.mapper.ScenicDeviceStatsMapper;
|
||||||
|
import com.ycwl.basic.model.pc.scenicDeviceStats.entity.ScenicDeviceStatsEntity;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.scheduling.annotation.EnableScheduling;
|
||||||
|
import org.springframework.scheduling.annotation.Scheduled;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
@EnableScheduling
|
||||||
|
public class ScenicDeviceStatsTask {
|
||||||
|
@Autowired
|
||||||
|
private ScenicDeviceStatsMapper mapper;
|
||||||
|
@Scheduled(cron = "0 10 0 * * *")
|
||||||
|
public void countDeviceStats() {
|
||||||
|
Date yesterdayStart = DateUtil.beginOfDay(DateUtil.yesterday());
|
||||||
|
Date yesterdayEnd = DateUtil.endOfDay(yesterdayStart);
|
||||||
|
Date twoDaysBeforeStart = DateUtil.beginOfDay(DateUtil.offsetDay(DateUtil.yesterday(), -1));
|
||||||
|
Date twoDaysBeforeEnd = DateUtil.endOfDay(twoDaysBeforeStart);
|
||||||
|
// 前天的数据
|
||||||
|
List<ScenicDeviceStatsEntity> list = mapper.countDeviceStats(twoDaysBeforeStart, twoDaysBeforeEnd);
|
||||||
|
if (!list.isEmpty()) {
|
||||||
|
list.forEach(stats -> {
|
||||||
|
stats.setDate(twoDaysBeforeStart);
|
||||||
|
mapper.insert(stats);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
list = mapper.countDeviceStats(yesterdayStart, yesterdayEnd);
|
||||||
|
if (!list.isEmpty()) {
|
||||||
|
list.forEach(stats -> {
|
||||||
|
stats.setDate(yesterdayStart);
|
||||||
|
mapper.insert(stats);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
73
src/main/resources/mapper/ScenicDeviceStatsMapper.xml
Normal file
73
src/main/resources/mapper/ScenicDeviceStatsMapper.xml
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||||
|
<mapper namespace="com.ycwl.basic.mapper.ScenicDeviceStatsMapper">
|
||||||
|
<!-- 插入景区设备统计记录 -->
|
||||||
|
<insert id="insert" useGeneratedKeys="true" keyProperty="stats.id">
|
||||||
|
REPLACE scenic_device_stats (
|
||||||
|
scenic_id,
|
||||||
|
device_id,
|
||||||
|
date,
|
||||||
|
count
|
||||||
|
) VALUES (
|
||||||
|
#{stats.scenicId},
|
||||||
|
#{stats.deviceId},
|
||||||
|
#{stats.date},
|
||||||
|
#{stats.count}
|
||||||
|
)
|
||||||
|
</insert>
|
||||||
|
<select id="countDeviceStats"
|
||||||
|
resultType="com.ycwl.basic.model.pc.scenicDeviceStats.entity.ScenicDeviceStatsEntity">
|
||||||
|
select scenic_id, device_id, count(1) as count
|
||||||
|
from (
|
||||||
|
select s.scenic_id, s.device_id
|
||||||
|
from member_source ms
|
||||||
|
left join source s on ms.source_id = s.id
|
||||||
|
where ms.type = 1
|
||||||
|
and s.create_time >= #{start}
|
||||||
|
and s.create_time <= #{end}
|
||||||
|
group by s.scenic_id, s.device_id, ms.face_id
|
||||||
|
)a
|
||||||
|
group by scenic_id, device_id
|
||||||
|
</select>
|
||||||
|
<select id="countCachedStatsByScenicId"
|
||||||
|
resultType="com.ycwl.basic.model.pc.scenicDeviceStats.resp.ScenicDeviceStatsResp">
|
||||||
|
select
|
||||||
|
ds.scenic_id as scenicId,
|
||||||
|
s.name as scenicName,
|
||||||
|
ds.device_id as deviceId,
|
||||||
|
d.name as deviceName,
|
||||||
|
IFNULL(sum(ds.count), 0) as count
|
||||||
|
from scenic_device_stats ds
|
||||||
|
left join scenic s on ds.scenic_id = s.id
|
||||||
|
left join device d on ds.device_id = d.id
|
||||||
|
where s.id = #{scenicId}
|
||||||
|
and ds.date >= #{start}
|
||||||
|
and ds.date <= #{end}
|
||||||
|
group by ds.scenic_id, ds.device_id
|
||||||
|
</select>
|
||||||
|
<select id="countRealtimeStatsByScenicId"
|
||||||
|
resultType="com.ycwl.basic.model.pc.scenicDeviceStats.resp.ScenicDeviceStatsResp">
|
||||||
|
select
|
||||||
|
ds.scenic_id as scenicId,
|
||||||
|
s.name as scenicName,
|
||||||
|
ds.device_id as deviceId,
|
||||||
|
d.name as deviceName,
|
||||||
|
ds.count
|
||||||
|
from (
|
||||||
|
select scenic_id, device_id, count(1) as count
|
||||||
|
from (
|
||||||
|
select s.scenic_id, s.device_id
|
||||||
|
from member_source ms
|
||||||
|
left join source s on ms.source_id = s.id
|
||||||
|
where ms.type = 1
|
||||||
|
and s.create_time >= #{start}
|
||||||
|
and s.create_time <= #{end}
|
||||||
|
group by s.scenic_id, s.device_id, ms.face_id
|
||||||
|
)a
|
||||||
|
group by scenic_id, device_id
|
||||||
|
) ds
|
||||||
|
left join scenic s on ds.scenic_id = s.id
|
||||||
|
left join device d on ds.device_id = d.id
|
||||||
|
where s.id = #{scenicId}
|
||||||
|
</select>
|
||||||
|
</mapper>
|
@ -0,0 +1,24 @@
|
|||||||
|
package com.ycwl.basic.task;
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.boot.test.context.SpringBootTest;
|
||||||
|
import org.springframework.test.context.junit4.SpringRunner;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
@SpringBootTest
|
||||||
|
@RunWith(SpringRunner.class)
|
||||||
|
public class ScenicDeviceStatsTaskTest {
|
||||||
|
@Autowired
|
||||||
|
private ScenicDeviceStatsTask task;
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testA() {
|
||||||
|
task.countDeviceStats();
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue
Block a user