Browse Source

Merge remote-tracking branch 'origin/develop' into develop

develop
wangsixiang 1 year ago
parent
commit
fb135dfd0b
  1. 17
      ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysLoginController.java
  2. 7
      ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysMenuController.java
  3. 11
      ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysMenu.java
  4. 2
      ruoyi-common/src/main/java/com/zc/common/core/httpclient/OkHttp.java
  5. 5
      ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysMenuMapper.java
  6. 3
      ruoyi-system/src/main/java/com/ruoyi/system/service/ISysMenuService.java
  7. 19
      ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysMenuServiceImpl.java
  8. 26
      ruoyi-system/src/main/resources/mapper/system/SysMenuMapper.xml
  9. 4
      ruoyi-ui/src/api/menu.js
  10. 4
      ruoyi-ui/src/api/system/menu.js
  11. 2
      ruoyi-ui/src/store/modules/permission.js
  12. 2
      ruoyi-ui/src/utils/auth.js
  13. 4
      ruoyi-ui/src/views/index.vue
  14. 18
      ruoyi-ui/src/views/system/menu/index.vue
  15. 3
      ruoyi-ui/src/views/websocket.vue
  16. 37
      zc-business/src/main/java/com/zc/business/constant/RedisStreamConstants.java
  17. 14
      zc-business/src/main/java/com/zc/business/controller/DcEventController.java
  18. 2
      zc-business/src/main/java/com/zc/business/controller/DcMetricsController.java
  19. 130
      zc-business/src/main/java/com/zc/business/controller/DcTrafficPoliceController.java
  20. 101
      zc-business/src/main/java/com/zc/business/controller/DcTrafficStatisticsController.java
  21. 69
      zc-business/src/main/java/com/zc/business/controller/WordController.java
  22. 89
      zc-business/src/main/java/com/zc/business/domain/DcGantryMetricsStatisticsData.java
  23. 2
      zc-business/src/main/java/com/zc/business/domain/DcGantryStatisticsData.java
  24. 2
      zc-business/src/main/java/com/zc/business/domain/DcRegion.java
  25. 100
      zc-business/src/main/java/com/zc/business/domain/DcStatisticsData.java
  26. 2
      zc-business/src/main/java/com/zc/business/domain/DcTollStationStatisticsData.java
  27. 100
      zc-business/src/main/java/com/zc/business/domain/DcTrafficFlowStatisticsData.java
  28. 101
      zc-business/src/main/java/com/zc/business/domain/DcTrafficPolice.java
  29. 92
      zc-business/src/main/java/com/zc/business/domain/DcTrafficSectionData.java
  30. 52
      zc-business/src/main/java/com/zc/business/domain/MdEvent.java
  31. 38
      zc-business/src/main/java/com/zc/business/enums/ChannelCongestionLevelEnum.java
  32. 52
      zc-business/src/main/java/com/zc/business/enums/StakeMarkRange.java
  33. 72
      zc-business/src/main/java/com/zc/business/enums/TrafficCompositionRateEnum.java
  34. 5
      zc-business/src/main/java/com/zc/business/enums/TrafficDataPeriodTypeEnum.java
  35. 65
      zc-business/src/main/java/com/zc/business/enums/ValueConverter.java
  36. 2
      zc-business/src/main/java/com/zc/business/mapper/DcEventMapper.java
  37. 32
      zc-business/src/main/java/com/zc/business/mapper/DcGantryMetricsStatisticsDataMapper.java
  38. 16
      zc-business/src/main/java/com/zc/business/mapper/DcGantryStatisticsDataMapper.java
  39. 3
      zc-business/src/main/java/com/zc/business/mapper/DcStakeMarkMapper.java
  40. 64
      zc-business/src/main/java/com/zc/business/mapper/DcTrafficPoliceMapper.java
  41. 2
      zc-business/src/main/java/com/zc/business/mapper/DcWarningMapper.java
  42. 29
      zc-business/src/main/java/com/zc/business/message/device/listener/TrafficGantryPlatesListener.java
  43. 29
      zc-business/src/main/java/com/zc/business/message/device/listener/TrafficGantryTransactionsListener.java
  44. 29
      zc-business/src/main/java/com/zc/business/message/device/listener/TrafficTollStationEntranceListener.java
  45. 29
      zc-business/src/main/java/com/zc/business/message/device/listener/TrafficTollStationExitListener.java
  46. 41
      zc-business/src/main/java/com/zc/business/message/device/subscribe/MessageSubscription.java
  47. 10
      zc-business/src/main/java/com/zc/business/service/IDcEventService.java
  48. 1
      zc-business/src/main/java/com/zc/business/service/IDcFacilityService.java
  49. 42
      zc-business/src/main/java/com/zc/business/service/IDcGantryMetricsStatisticsDataService.java
  50. 18
      zc-business/src/main/java/com/zc/business/service/IDcGantryStatisticsDataService.java
  51. 2
      zc-business/src/main/java/com/zc/business/service/IDcTollStationStatisticsDataService.java
  52. 64
      zc-business/src/main/java/com/zc/business/service/IDcTrafficPoliceService.java
  53. 29
      zc-business/src/main/java/com/zc/business/service/IDcTrafficStatisticsService.java
  54. 62
      zc-business/src/main/java/com/zc/business/service/impl/DcEventServiceImpl.java
  55. 13
      zc-business/src/main/java/com/zc/business/service/impl/DcFacilityServiceImpl.java
  56. 81
      zc-business/src/main/java/com/zc/business/service/impl/DcGantryStatisticsDataImpl.java
  57. 18
      zc-business/src/main/java/com/zc/business/service/impl/DcTollStationStatisticsDataImpl.java
  58. 104
      zc-business/src/main/java/com/zc/business/service/impl/DcTrafficPoliceServiceImpl.java
  59. 14
      zc-business/src/main/java/com/zc/business/service/impl/DcTrafficSectionStatisticsServiceImpl.java
  60. 401
      zc-business/src/main/java/com/zc/business/service/impl/DcTrafficStatisticsServiceImpl.java
  61. 8
      zc-business/src/main/java/com/zc/business/service/impl/DcWarningServiceImpl.java
  62. 275
      zc-business/src/main/java/com/zc/business/service/impl/IDcGantryMetricsStatisticsDataServiceImpl.java
  63. 5
      zc-business/src/main/java/com/zc/business/service/impl/OdsTollEtctuDataImpl.java
  64. 2
      zc-business/src/main/java/com/zc/business/service/impl/OdsTollExpassDataServiceImpl.java
  65. 1
      zc-business/src/main/java/com/zc/business/statistics/cache/gantry/DailyTrafficGantryStatisticsCache.java
  66. 147
      zc-business/src/main/java/com/zc/business/statistics/cache/metrics/DailyGantryMetricsStatisticsCache.java
  67. 152
      zc-business/src/main/java/com/zc/business/statistics/cache/metrics/MonthlyGantryMetricsStatisticsCache.java
  68. 154
      zc-business/src/main/java/com/zc/business/statistics/cache/metrics/QuarterlyGantryMetricsStatisticsCache.java
  69. 148
      zc-business/src/main/java/com/zc/business/statistics/cache/metrics/YearlyGantryMetricsStatisticsCache.java
  70. 162
      zc-business/src/main/java/com/zc/business/statistics/handler/TrafficGantryMetricsStatistics.java
  71. 12
      zc-business/src/main/java/com/zc/business/statistics/handler/TrafficGantryStatistics.java
  72. 3
      zc-business/src/main/resources/mapper/business/DcEmergencyPlansMapper.xml
  73. 3
      zc-business/src/main/resources/mapper/business/DcEventMapper.xml
  74. 77
      zc-business/src/main/resources/mapper/business/DcGantryMetricsStatisticsDataMapper.xml
  75. 127
      zc-business/src/main/resources/mapper/business/DcGantryStatisticsDataMapper.xml
  76. 4
      zc-business/src/main/resources/mapper/business/DcStakeMarkMapper.xml
  77. 84
      zc-business/src/main/resources/mapper/business/DcTrafficPoliceMapper.xml
  78. 3
      zc-business/src/main/resources/mapper/business/DcWarningMapper.xml
  79. 10
      zc-business/src/main/resources/mapper/business/MiddleDatabaseMapper.xml

17
ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysLoginController.java

@ -1,24 +1,23 @@
package com.ruoyi.web.controller.system;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import com.ruoyi.common.config.RuoYiConfig;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.entity.SysMenu;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.domain.model.LoginBody;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.framework.web.service.SysLoginService;
import com.ruoyi.framework.web.service.SysPermissionService;
import com.ruoyi.system.service.ISysMenuService;
import com.zc.websocket.WebSocketConfigParam;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import java.util.Set;
import java.util.*;
/**
* 登录验证
@ -97,11 +96,11 @@ public class SysLoginController
*
* @return 路由信息
*/
@GetMapping("getRouters")
public AjaxResult getRouters()
@GetMapping("getRouters/{distinguish}")
public AjaxResult getRouters(@PathVariable Long distinguish)
{
Long userId = SecurityUtils.getUserId();
List<SysMenu> menus = menuService.selectMenuTreeByUserId(userId);
List<SysMenu> menus = menuService.selectMenuTreeByUserId(userId,distinguish);
return AjaxResult.success(menuService.buildMenus(menus));
}
}

7
ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysMenuController.java

@ -67,10 +67,11 @@ public class SysMenuController extends BaseController
/**
* 加载对应角色菜单列表树
*/
@GetMapping(value = "/roleMenuTreeselect/{roleId}")
public AjaxResult roleMenuTreeselect(@PathVariable("roleId") Long roleId)
@GetMapping(value = "/roleMenuTreeselect/{roleId}/{distinguish}")
public AjaxResult roleMenuTreeselect(@PathVariable("roleId") Long roleId,@PathVariable("distinguish") Long distinguish)
{
List<SysMenu> menus = menuService.selectMenuList(getUserId());
// List<SysMenu> menus = menuService.selectMenuList(getUserId());
List<SysMenu> menus = menuService.selectMenuListDistinguish(getUserId(),distinguish);
AjaxResult ajax = AjaxResult.success();
ajax.put("checkedKeys", menuService.selectMenuListByRoleId(roleId));
ajax.put("menus", menuService.buildMenuTreeSelect(menus));

11
ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysMenu.java

@ -66,6 +66,17 @@ public class SysMenu extends BaseEntity
/** 子菜单 */
private List<SysMenu> children = new ArrayList<SysMenu>();
/** 菜单区分标识*/
private Long distinguish;
public Long getDistinguish() {
return distinguish;
}
public void setDistinguish(Long distinguish) {
this.distinguish = distinguish;
}
public Long getMenuId()
{
return menuId;

2
ruoyi-common/src/main/java/com/zc/common/core/httpclient/OkHttp.java

@ -20,7 +20,7 @@ import java.util.concurrent.TimeUnit;
*/
public class OkHttp
{
private int timeOut = 5; // 默认超时时间 5
private int timeOut = 10; // 默认超时时间 10
private static okhttp3.OkHttpClient okHttpClient;

5
ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysMenuMapper.java

@ -47,6 +47,7 @@ public interface SysMenuMapper
* @return 菜单列表
*/
public List<SysMenu> selectMenuTreeAll();
public List<SysMenu> selectMenuTreeDistinguishAll(Long distinguish);
/**
* 根据用户ID查询菜单
@ -54,7 +55,7 @@ public interface SysMenuMapper
* @param userId 用户ID
* @return 菜单列表
*/
public List<SysMenu> selectMenuTreeByUserId(Long userId);
public List<SysMenu> selectMenuTreeByUserId(@Param("userId") Long userId,@Param("distinguish")Long distinguish);
/**
* 根据角色ID查询菜单树信息
@ -112,5 +113,5 @@ public interface SysMenuMapper
* @param parentId 父菜单ID
* @return 结果
*/
public SysMenu checkMenuNameUnique(@Param("menuName") String menuName, @Param("parentId") Long parentId);
public SysMenu checkMenuNameUnique(@Param("menuName") String menuName, @Param("parentId") Long parentId,@Param("distinguish") Long distinguish);
}

3
ruoyi-system/src/main/java/com/ruoyi/system/service/ISysMenuService.java

@ -19,6 +19,7 @@ public interface ISysMenuService
* @return 菜单列表
*/
public List<SysMenu> selectMenuList(Long userId);
public List<SysMenu> selectMenuListDistinguish(Long userId,Long distinguish);
/**
* 根据用户查询系统菜单列表
@ -43,7 +44,7 @@ public interface ISysMenuService
* @param userId 用户ID
* @return 菜单列表
*/
public List<SysMenu> selectMenuTreeByUserId(Long userId);
public List<SysMenu> selectMenuTreeByUserId(Long userId,Long distinguish);
/**
* 根据角色ID查询菜单树信息

19
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysMenuServiceImpl.java

@ -55,6 +55,13 @@ public class SysMenuServiceImpl implements ISysMenuService
{
return selectMenuList(new SysMenu(), userId);
}
@Override
public List<SysMenu> selectMenuListDistinguish(Long userId,Long distinguish)
{
SysMenu sysMenu = new SysMenu();
sysMenu.setDistinguish(distinguish);
return selectMenuList(sysMenu, userId);
}
/**
* 查询系统菜单列表
@ -69,6 +76,7 @@ public class SysMenuServiceImpl implements ISysMenuService
// 管理员显示所有菜单信息
if (SysUser.isAdmin(userId))
{
menu.setDistinguish(menu.getDistinguish());
menuList = menuMapper.selectMenuList(menu);
}
else
@ -107,16 +115,19 @@ public class SysMenuServiceImpl implements ISysMenuService
* @return 菜单列表
*/
@Override
public List<SysMenu> selectMenuTreeByUserId(Long userId)
public List<SysMenu> selectMenuTreeByUserId(Long userId,Long distinguish)
{
List<SysMenu> menus = null;
if (SecurityUtils.isAdmin(userId))
{
menus = menuMapper.selectMenuTreeAll();
// menus = menuMapper.selectMenuTreeAll();
menus = menuMapper.selectMenuTreeDistinguishAll(distinguish);
//menus = menuMapper.selectMenuTreeByUserId(userId,distinguish);
}
else
{
menus = menuMapper.selectMenuTreeByUserId(userId);
menus = menuMapper.selectMenuTreeByUserId(userId,distinguish);
}
return getChildPerms(menus, 0);
}
@ -321,7 +332,7 @@ public class SysMenuServiceImpl implements ISysMenuService
public String checkMenuNameUnique(SysMenu menu)
{
Long menuId = StringUtils.isNull(menu.getMenuId()) ? -1L : menu.getMenuId();
SysMenu info = menuMapper.checkMenuNameUnique(menu.getMenuName(), menu.getParentId());
SysMenu info = menuMapper.checkMenuNameUnique(menu.getMenuName(), menu.getParentId(),menu.getDistinguish());
if (StringUtils.isNotNull(info) && info.getMenuId().longValue() != menuId.longValue())
{
return UserConstants.NOT_UNIQUE;

26
ruoyi-system/src/main/resources/mapper/system/SysMenuMapper.xml

@ -25,10 +25,12 @@
<result property="updateTime" column="update_time" />
<result property="updateBy" column="update_by" />
<result property="remark" column="remark" />
<result property="remark" column="remark" />
<result property="distinguish" column="distinguish" />
</resultMap>
<sql id="selectMenuVo">
select menu_id, menu_name, parent_id, order_num, path, component, `query`, is_frame, is_cache, menu_type, visible, status, ifnull(perms,'') as perms, icon, create_time
select distinguish, menu_id, menu_name, parent_id, order_num, path, component, `query`, is_frame, is_cache, menu_type, visible, status, ifnull(perms,'') as perms, icon, create_time
from sys_menu
</sql>
@ -41,6 +43,9 @@
<if test="visible != null and visible != ''">
AND visible = #{visible}
</if>
<if test="distinguish != null and distinguish != ''">
AND distinguish=#{distinguish}
</if>
<if test="status != null and status != ''">
AND status = #{status}
</if>
@ -49,10 +54,15 @@
</select>
<select id="selectMenuTreeAll" resultMap="SysMenuResult">
select distinct m.menu_id, m.parent_id, m.menu_name, m.path, m.component, m.`query`, m.visible, m.status, ifnull(m.perms,'') as perms, m.is_frame, m.is_cache, m.menu_type, m.icon, m.order_num, m.create_time
select distinct m.distinguish, m.menu_id, m.parent_id, m.menu_name, m.path, m.component, m.`query`, m.visible, m.status, ifnull(m.perms,'') as perms, m.is_frame, m.is_cache, m.menu_type, m.icon, m.order_num, m.create_time
from sys_menu m where m.menu_type in ('M', 'C') and m.status = 0
order by m.parent_id, m.order_num
</select>
<select id="selectMenuTreeDistinguishAll" resultMap="SysMenuResult">
select distinct m.distinguish, m.menu_id, m.parent_id, m.menu_name, m.path, m.component, m.`query`, m.visible, m.status, ifnull(m.perms,'') as perms, m.is_frame, m.is_cache, m.menu_type, m.icon, m.order_num, m.create_time
from sys_menu m where m.menu_type in ('M', 'C') and m.status = 0 AND m.distinguish = #{distinguish}
order by m.parent_id, m.order_num
</select>
<select id="selectMenuListByUserId" parameterType="SysMenu" resultMap="SysMenuResult">
select distinct m.menu_id, m.parent_id, m.menu_name, m.path, m.component, m.`query`, m.visible, m.status, ifnull(m.perms,'') as perms, m.is_frame, m.is_cache, m.menu_type, m.icon, m.order_num, m.create_time
@ -69,18 +79,21 @@
</if>
<if test="status != null and status != ''">
AND m.status = #{status}
</if>
<if test="distinguish != null and distinguish != ''">
AND m.distinguish = #{distinguish}
</if>
order by m.parent_id, m.order_num
</select>
<select id="selectMenuTreeByUserId" parameterType="Long" resultMap="SysMenuResult">
select distinct m.menu_id, m.parent_id, m.menu_name, m.path, m.component, m.`query`, m.visible, m.status, ifnull(m.perms,'') as perms, m.is_frame, m.is_cache, m.menu_type, m.icon, m.order_num, m.create_time
select distinct m.distinguish,m.menu_id, m.parent_id, m.menu_name, m.path, m.component, m.`query`, m.visible, m.status, ifnull(m.perms,'') as perms, m.is_frame, m.is_cache, m.menu_type, m.icon, m.order_num, m.create_time
from sys_menu m
left join sys_role_menu rm on m.menu_id = rm.menu_id
left join sys_user_role ur on rm.role_id = ur.role_id
left join sys_role ro on ur.role_id = ro.role_id
left join sys_user u on ur.user_id = u.user_id
where u.user_id = #{userId} and m.menu_type in ('M', 'C') and m.status = 0 AND ro.status = 0
where u.user_id = #{userId} and m.menu_type in ('M', 'C') and m.status = 0 AND ro.status = 0 and m.distinguish=#{distinguish}
order by m.parent_id, m.order_num
</select>
@ -122,7 +135,7 @@
<select id="checkMenuNameUnique" parameterType="SysMenu" resultMap="SysMenuResult">
<include refid="selectMenuVo"/>
where menu_name=#{menuName} and parent_id = #{parentId} limit 1
where menu_name=#{menuName} and parent_id = #{parentId} and distinguish=#{distinguish} limit 1
</select>
<update id="updateMenu" parameterType="SysMenu">
@ -143,6 +156,7 @@
<if test="icon !=null and icon != ''">icon = #{icon},</if>
<if test="remark != null and remark != ''">remark = #{remark},</if>
<if test="updateBy != null and updateBy != ''">update_by = #{updateBy},</if>
<if test="distinguish != null and distinguish != ''">distinguish = #{distinguish},</if>
update_time = sysdate()
</set>
where menu_id = #{menuId}
@ -166,6 +180,7 @@
<if test="icon != null and icon != ''">icon,</if>
<if test="remark != null and remark != ''">remark,</if>
<if test="createBy != null and createBy != ''">create_by,</if>
<if test="distinguish != null">distinguish,</if>
create_time
)values(
<if test="menuId != null and menuId != 0">#{menuId},</if>
@ -184,6 +199,7 @@
<if test="icon != null and icon != ''">#{icon},</if>
<if test="remark != null and remark != ''">#{remark},</if>
<if test="createBy != null and createBy != ''">#{createBy},</if>
<if test="distinguish != null ">#{distinguish},</if>
sysdate()
)
</insert>

4
ruoyi-ui/src/api/menu.js

@ -3,7 +3,7 @@ import request from '@/utils/request'
// 获取路由
export const getRouters = () => {
return request({
url: '/getRouters',
url: '/getRouters/'+0,
method: 'get'
})
}
}

4
ruoyi-ui/src/api/system/menu.js

@ -28,7 +28,7 @@ export function treeselect() {
// 根据角色ID查询菜单下拉树结构
export function roleMenuTreeselect(roleId) {
return request({
url: '/system/menu/roleMenuTreeselect/' + roleId,
url: '/system/menu/roleMenuTreeselect/' + roleId+'/1',
method: 'get'
})
}
@ -57,4 +57,4 @@ export function delMenu(menuId) {
url: '/system/menu/' + menuId,
method: 'delete'
})
}
}

2
ruoyi-ui/src/store/modules/permission.js

@ -38,7 +38,7 @@ const permission = {
GenerateRoutes({ commit }) {
return new Promise(resolve => {
// 向后端请求路由数据
getRouters().then(res => {
getRouters(1).then(res => {
const sdata = JSON.parse(JSON.stringify(res.data))
const rdata = JSON.parse(JSON.stringify(res.data))
const sidebarRoutes = filterAsyncRouter(sdata)

2
ruoyi-ui/src/utils/auth.js

@ -1,6 +1,6 @@
import Cookies from 'js-cookie'
const TokenKey = 'DC-Token'
const TokenKey = 'DC-Pro-Token'
export function getToken() {
return Cookies.get(TokenKey)

4
ruoyi-ui/src/views/index.vue

@ -701,7 +701,7 @@ export default {
/************************************ 设备消息 **************************************/
/** 时间按钮选项 */
timeDimensionChange() {
if (this.messageMonitorTimeDimension === 'day') {
/*if (this.messageMonitorTimeDimension === 'day') {
this.messageMonitorTimePick = this.getTodayTime()
const params = {
time: '1h',
@ -763,7 +763,7 @@ export default {
this.getMessageMonitorData(params, 'received_message')
this.getMessageMonitorData(params, 'sent_message')
}
}*/
},
/** 设备消息char初始化 */

18
ruoyi-ui/src/views/system/menu/index.vue

@ -65,6 +65,7 @@
<el-table-column prop="orderNum" label="排序" width="60"></el-table-column>
<el-table-column prop="perms" label="权限标识" :show-overflow-tooltip="true"></el-table-column>
<el-table-column prop="component" label="组件路径" :show-overflow-tooltip="true"></el-table-column>
<el-table-column prop="status" label="状态" width="80">
<template slot-scope="scope">
<dict-tag :options="dict.type.sys_normal_disable" :value="scope.row.status"/>
@ -77,7 +78,7 @@
</el-table-column>
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
<template slot-scope="scope">
<el-button
<el-button
size="mini"
type="text"
icon="el-icon-edit"
@ -170,6 +171,18 @@
<el-radio label="0"></el-radio>
<el-radio label="1"></el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="是否dc" prop="distinguish">
<span slot="label">
是否dc后端
</span>
<el-radio-group v-model="form.distinguish">
<el-radio :label=0></el-radio>
<el-radio :label=1></el-radio>
</el-radio-group>
</el-form-item>
</el-col>
<el-col :span="12" v-if="form.menuType != 'F'">
@ -376,7 +389,8 @@ export default {
isFrame: "1",
isCache: "0",
visible: "0",
status: "0"
status: "0",
distinguish:0,
};
this.resetForm("form");
},

3
ruoyi-ui/src/views/websocket.vue

@ -19,7 +19,8 @@ export default {
websocket({ password, path, port, interval}) {
// websocket
this.socket.initialize({
url: 'ws://' + location.hostname + ':' + port + path,
// url: 'ws://' + location.hostname + ':' + port + path,
url: 'wss://' + location.hostname + ':' + window.location.port + '/ws' || 80 + '/ws',
password: password,
tokenSN: this.token,
heartRate: interval

37
zc-business/src/main/java/com/zc/business/constant/RedisStreamConstants.java

@ -69,41 +69,4 @@ public class RedisStreamConstants {
public final static String CONSUMER = "consumer1";
}
/**
* 门架交易流水
*/
public static class TrafficGantryTransactions {
public final static String KEY = "traffic:gantry:transactions";
public final static String GROUP = "group1";
public final static String CONSUMER = "consumer1";
}
/**
* 门架牌识
*/
public static class TrafficGantryPlates {
public final static String KEY = "traffic:gantry:plates";
public final static String GROUP = "group1";
public final static String CONSUMER = "consumer1";
}
/**
* 收费入口数据
*/
public static class TrafficTollStationEntrance {
public final static String KEY = "traffic:tollStation:entrance";
public final static String GROUP = "group1";
public final static String CONSUMER = "consumer1";
}
/**
* 收费出口数据
*/
public static class TrafficTollStationExit {
public final static String KEY = "traffic:tollStation:exit";
public final static String GROUP = "group1";
public final static String CONSUMER = "consumer1";
}
}

14
zc-business/src/main/java/com/zc/business/controller/DcEventController.java

@ -227,4 +227,18 @@ public class DcEventController extends BaseController
public AjaxResult getLinkEvent(@ApiParam(name = "eventId", value = "事件id", required = true) @PathVariable("eventId") String eventId){
return dcEventService.getLinkEvent(eventId);
}
/**
* @Description 获取事件数量
*
* @author liuwenge
* @date 2024/6/6 18:45
* @param type
* @return com.ruoyi.common.core.domain.AjaxResult
*/
@ApiOperation("获取事件数量")
@GetMapping( "/getCountNum/{type}")
public AjaxResult getCountNum(@ApiParam(name = "type", value = "类型 1:告警 2:待确认 3:处置中", required = true) @PathVariable("type") String type){
return dcEventService.getCountNum(type);
}
}

2
zc-business/src/main/java/com/zc/business/controller/DcMetricsController.java

@ -148,7 +148,7 @@ public class DcMetricsController {
// 如果昨天或前天的数据为空,则返回错误信息
if (yesterdayData == null || beforeYesterdayData == null) {
return AjaxResult.error("暂无数据");
return AjaxResult.success(null);
}
// 将数据放入列表并返回

130
zc-business/src/main/java/com/zc/business/controller/DcTrafficPoliceController.java

@ -0,0 +1,130 @@
package com.zc.business.controller;
import java.util.List;
import javax.servlet.http.HttpServletResponse;
import com.zc.business.domain.DcTrafficPolice;
import com.zc.business.service.IDcTrafficPoliceService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.common.core.page.TableDataInfo;
/**
* 交管数据Controller
*
* @author ruoyi
* @date 2024-06-06
*/
@Api(tags = "交警信息管理")
@RestController
@RequestMapping("/system/police")
public class DcTrafficPoliceController extends BaseController
{
@Autowired
private IDcTrafficPoliceService dcTrafficPoliceService;
/**
* 查询交管数据列表
*/
@ApiOperation("查询交警列表")
// @PreAuthorize("@ss.hasPermi('system:police:list')")
@GetMapping("/list")
public TableDataInfo list(DcTrafficPolice dcTrafficPolice)
{
startPage();
List<DcTrafficPolice> list = dcTrafficPoliceService.selectDcTrafficPoliceList(dcTrafficPolice);
return getDataTable(list);
}
/**
* 导出交管数据列表
*/
@ApiOperation("导出交管数据列表")
// @PreAuthorize("@ss.hasPermi('system:police:export')")
@Log(title = "交管数据", businessType = BusinessType.EXPORT)
@PostMapping("/export")
public void export(HttpServletResponse response, DcTrafficPolice dcTrafficPolice)
{
List<DcTrafficPolice> list = dcTrafficPoliceService.selectDcTrafficPoliceList(dcTrafficPolice);
ExcelUtil<DcTrafficPolice> util = new ExcelUtil<>(DcTrafficPolice.class);
util.exportExcel(response, list, "交管数据数据");
}
/**
* 获取交管数据详细信息
*/
@ApiOperation("获取交管数据详细信息")
//@PreAuthorize("@ss.hasPermi('system:police:query')")
@GetMapping(value = "/{id}")
public AjaxResult getInfo(@PathVariable("id") Long id)
{
return AjaxResult.success(dcTrafficPoliceService.selectDcTrafficPoliceById(id));
} /**
* 获取事件所属交管信息
*/
@ApiOperation("获取事件所属交管信息")
@GetMapping("/enent/{make}")
public AjaxResult getInfoEvent(@PathVariable("make") String make)
{
return AjaxResult.success(dcTrafficPoliceService.selectEvent(make));
}
/**
* 新增交管数据
*/
@ApiOperation("新增交管数据")
// @PreAuthorize("@ss.hasPermi('system:police:add')")
@Log(title = "交管数据", businessType = BusinessType.INSERT)
@PostMapping
public AjaxResult add(@RequestBody DcTrafficPolice dcTrafficPolice)
{
return toAjax(dcTrafficPoliceService.insertDcTrafficPolice(dcTrafficPolice));
}
/**
* 修改交管数据
*/
@ApiOperation("修改交管数据")
@PreAuthorize("@ss.hasPermi('system:police:edit')")
@Log(title = "交管数据", businessType = BusinessType.UPDATE)
@PutMapping
public AjaxResult edit(@RequestBody DcTrafficPolice dcTrafficPolice)
{
return toAjax(dcTrafficPoliceService.updateDcTrafficPolice(dcTrafficPolice));
}
/**
* 删除交管数据
*/
@ApiOperation("删除交管数据")
// @PreAuthorize("@ss.hasPermi('system:police:remove')")
@Log(title = "交管数据", businessType = BusinessType.DELETE)
@DeleteMapping("/{ids}")
public AjaxResult remove(@PathVariable Long[] ids)
{
return toAjax(dcTrafficPoliceService.deleteDcTrafficPoliceByIds(ids));
}
}

101
zc-business/src/main/java/com/zc/business/controller/DcTrafficStatisticsController.java

@ -5,10 +5,7 @@ import com.ruoyi.common.core.domain.AjaxResult;
import com.zc.business.domain.*;
import com.zc.business.request.DcTrafficMetricsDataRequest;
import com.zc.business.request.DcTrafficSectionDataRequest;
import com.zc.business.service.IDcGantryStatisticsDataService;
import com.zc.business.service.IDcTollStationStatisticsDataService;
import com.zc.business.service.IDcTrafficSectionStatisticsService;
import com.zc.business.service.IDcTrafficStatisticsService;
import com.zc.business.service.*;
import com.zc.common.core.httpclient.exception.HttpException;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
@ -41,6 +38,9 @@ public class DcTrafficStatisticsController {
@Autowired
private IDcGantryStatisticsDataService dcGantryStatisticsDataService;
@Autowired
private IDcGantryMetricsStatisticsDataService dcGantryMetricsStatisticsDataService;
/**
* 获取当前交通截面数据
*
@ -117,23 +117,6 @@ public class DcTrafficStatisticsController {
return AjaxResult.success(dcTrafficMetricsData);
}
/**
* 获取累计车流量
*
* 本方法用于根据特定条件查询历史车流量数据通过接收一个包含查询条件的请求对象
* 调用服务层方法进行数据查询并将查询结果封装成AjaxResult对象返回
*
* @param request 包含查询条件的请求对象用于获取特定条件下的历史车流量数据请求对象中可能包含了时间范围地点等查询条件
* @return 返回一个AjaxResult对象其中包含了查询到的历史车流量数据列表AjaxResult是本系统中用于封装响应数据的通用对象其中的success方法用于将查询结果封装为成功响应返回
*/
@ApiOperation("获取累计车流量")
@GetMapping("/history/flow")
public AjaxResult historyFlow(DcStatisticsData request){
// 调用服务层方法,根据请求条件查询历史车流量数据
List<DcStatisticsData> dcStatisticsData = dcTrafficStatisticsService.historyFlow(request);
// 将查询结果封装为成功响应并返回
return AjaxResult.success(dcStatisticsData);
}
/**
* 获取收费站统计数据
@ -173,13 +156,41 @@ public class DcTrafficStatisticsController {
*/
@ApiOperation("获取门架统计数据")
@GetMapping("/history/gantry")
public AjaxResult historyTollStation(DcGantryStatisticsData request){
public AjaxResult historyGantryData(DcGantryStatisticsData request){
// 调用服务层方法,根据请求条件查询历史车门架数据
List<DcGantryStatisticsData> dcStatisticsData = dcGantryStatisticsDataService.gantryData(request);
// 将查询结果封装为成功响应并返回
return AjaxResult.success(dcStatisticsData);
}
/**
* 全路段双向实时车流量
* @param startDate 时间
* @param direction 方向
* @param periodType 时间粒子
*/
@ApiOperation("全路段双向实时车流量")
@GetMapping("/history/realTimeTrafficFlow")
public AjaxResult realTimeTrafficFlow(String startDate, String direction,String periodType ){
List<Map<String,String>> mapList = dcGantryStatisticsDataService.realTimeTrafficFlow(startDate,direction,periodType);
// 将查询结果封装为成功响应并返回
return AjaxResult.success(mapList);
}
/**
* 获取门架指标统计数据
*
* @param request 包含查询条件的请求对象用于筛选历史门架指标统计数据
* @return 返回一个AjaxResult对象其中包含了查询到的门架指标统计数据列表
*/
@ApiOperation("获取门架交通特指数数据")
@GetMapping("/history/gantry-metrics")
public AjaxResult historyGantryMetrics(DcGantryMetricsStatisticsData request){
// 调用服务层方法,根据请求条件查询历史车门架数据
List<DcGantryMetricsStatisticsData> dcStatisticsData = dcGantryMetricsStatisticsDataService.gantryMetricsData(request);
// 将查询结果封装为成功响应并返回
return AjaxResult.success(dcStatisticsData);
}
/********************************************* 智慧高速平接口 **************************************************/
@ -246,6 +257,52 @@ public class DcTrafficStatisticsController {
// 将获取到的交通指标数据封装为成功的结果并返回
return AjaxResult.success(jsonArray);
}
/**
* 断面小时车流量分车型
*/
@ApiOperation("断面小时车流量分车型")
@GetMapping("/history/sectionHourlyTrafficFlow")
public AjaxResult sectionHourlyTrafficFlow(String startDate, String endDate) throws HttpException, IOException {
// 调用服务层方法,获取当前交通指标数据
JSONArray jsonArray = dcTrafficStatisticsService.sectionHourlyTrafficFlow(startDate, endDate);
// 将获取到的交通指标数据封装为成功的结果并返回
return AjaxResult.success(jsonArray);
}/**
* 各收费站入口分车型车流量
*/
@ApiOperation("各收费站入口分车型小时车流量")
@GetMapping("/history/trafficFlowAtTollStationEntranceHour")
public AjaxResult trafficFlowAtTollStationEntranceHour(String startDate, String endDate,String stationType) throws HttpException, IOException {
// 调用服务层方法,获取当前交通指标数据
List<Map<String, String>> jsonArray = dcTrafficStatisticsService.trafficFlowAtTollStationEntrance(startDate, endDate, stationType);
// 将获取到的交通指标数据封装为成功的结果并返回
return AjaxResult.success(jsonArray);
}
/**
* 各收费站入口分车型小时车流量
*/
@ApiOperation("各收费站入口分车型车流量")
@GetMapping("/history/trafficFlowAtTollStationEntrance")
public AjaxResult trafficFlowAtTollStationEntrance(String startDate, String endDate,String stationType) throws HttpException, IOException {
// 调用服务层方法,获取当前交通指标数据
JSONArray jsonArray = dcTrafficStatisticsService.trafficFlowAtTollStationEntranceHour(startDate, endDate, stationType);
// 将获取到的交通指标数据封装为成功的结果并返回
return AjaxResult.success(jsonArray);
}
/**
* 全路段双向实时车流量
* @param startDate 时间
* @param direction 方向
*/
@ApiOperation("全路段双向实时车流量")
@GetMapping("/history/realTimeTrafficFlowHour")
public AjaxResult realTimeTrafficFlowHour(String startDate,Long direction) throws HttpException, IOException{
List<Map<String,Object>> mapList = dcTrafficStatisticsService.realTimeTrafficFlowHour(startDate,direction);
// 将查询结果封装为成功响应并返回
return AjaxResult.success(mapList);
}
}

69
zc-business/src/main/java/com/zc/business/controller/WordController.java

@ -2,8 +2,11 @@ package com.zc.business.controller;
import com.ruoyi.common.config.RuoYiConfig;
import com.ruoyi.common.core.domain.AjaxResult;
import com.zc.business.domain.DcTollStationStatisticsData;
import com.zc.business.domain.DcTrafficSectionData;
import com.zc.business.enums.TrafficDataPeriodTypeEnum;
import com.zc.business.mapper.DcTrafficIncidentsMapper;
import com.zc.business.service.IDcTollStationStatisticsDataService;
import com.zc.business.utils.PoiUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
@ -45,6 +48,9 @@ public class WordController {
@Autowired
private DcTrafficIncidentsMapper dcTrafficIncidentsMapper;
@Autowired
private IDcTollStationStatisticsDataService dcTollStationStatisticsDataService;
@PostMapping("/trafficSituationReport")
@ApiOperation("导出通行情况快报")
@ -506,15 +512,60 @@ public class WordController {
List<Map<String,Object>> trafficFlowList = new ArrayList<>();
Map<String,Object> trafficFlow = new HashMap<>();
trafficFlow.put("label","入口");
trafficFlow.put("num","0");
trafficFlowList.add(trafficFlow);
trafficFlow = new HashMap<>();
trafficFlow.put("label","出口");
trafficFlow.put("num","0");
trafficFlowList.add(trafficFlow);
DcTollStationStatisticsData dcTollStationStatisticsData = new DcTollStationStatisticsData();
dcTollStationStatisticsData.setPeriodType(TrafficDataPeriodTypeEnum.DAY);
Calendar startCalendar = Calendar.getInstance();
startCalendar.set(Calendar.HOUR_OF_DAY, 0);
startCalendar.set(Calendar.MINUTE, 0);
startCalendar.set(Calendar.SECOND, 0);
startCalendar.set(Calendar.MILLISECOND, 0);
Date startTime = startCalendar.getTime();
dcTollStationStatisticsData.setStartTime(startTime);
Calendar endCalendar = Calendar.getInstance();
endCalendar.set(Calendar.HOUR_OF_DAY, 23);
endCalendar.set(Calendar.MINUTE, 59);
endCalendar.set(Calendar.SECOND, 59);
endCalendar.set(Calendar.MILLISECOND, 999);
Date emdTime = endCalendar.getTime();
dcTollStationStatisticsData.setEndTime(emdTime);
List<DcTollStationStatisticsData> statisticsDataList = dcTollStationStatisticsDataService.tollStationData(dcTollStationStatisticsData);
if (statisticsDataList != null && statisticsDataList.size() > 0){
Integer entrance = 0; //入口
Integer export = 0; //出口
for (DcTollStationStatisticsData tollStationStatisticsData : statisticsDataList) {
if (tollStationStatisticsData.getAccessType() == 1){
entrance = entrance + tollStationStatisticsData.getTrafficVolume();
} else if (tollStationStatisticsData.getAccessType() == 2){
export = export + tollStationStatisticsData.getTrafficVolume();
}
}
Map<String, Object> trafficFlow = new HashMap<>();
trafficFlow.put("label", "入口");
trafficFlow.put("num", entrance);
trafficFlowList.add(trafficFlow);
trafficFlow = new HashMap<>();
trafficFlow.put("label", "出口");
trafficFlow.put("num", export);
trafficFlowList.add(trafficFlow);
} else {
Map<String, Object> trafficFlow = new HashMap<>();
trafficFlow.put("label", "入口");
trafficFlow.put("num", "0");
trafficFlowList.add(trafficFlow);
trafficFlow = new HashMap<>();
trafficFlow.put("label", "出口");
trafficFlow.put("num", "0");
trafficFlowList.add(trafficFlow);
}
if (trafficFlowList != null && trafficFlowList.size() > 0) {

89
zc-business/src/main/java/com/zc/business/domain/DcGantryMetricsStatisticsData.java

@ -0,0 +1,89 @@
package com.zc.business.domain;
import cn.hutool.core.date.DateUtil;
import lombok.Getter;
import lombok.Setter;
import org.apache.commons.codec.digest.DigestUtils;
import java.util.Objects;
/**
* 门架交通特征指数
* @author xiepufeng
*/
@Getter
@Setter
public class DcGantryMetricsStatisticsData extends DcStatisticsData {
/**
* 门架编号
*/
private String gantryCode;
/**
* 拥堵度
* 1-畅通
* 2-基本畅通
* 3-轻度拥堵
* 4-中度拥堵
* 5-重度拥堵
*/
private Integer crowdingRate;
/**
* 交通组成特征指数大车占比
* 1-
* 2-
* 3-
*/
private Integer trafficCompositionRate;
/**
* 饱和度指数
*/
private Double saturationRate;
/**
* 重写equals方法用于比较两个DcGantryStatisticsData对象是否相等
*
* @param o 要与当前对象比较的对象
* @return 如果两个对象相等则返回true否则返回false
*/
@Override
public boolean equals(Object o) {
if (this == o) return true; // 比较是否为同一对象,是则直接返回true
if (o == null || getClass() != o.getClass()) return false; // 比较对象是否为空或类型是否不同,是则返回false
DcGantryMetricsStatisticsData that = (DcGantryMetricsStatisticsData) o; // 类型转换
// 使用Objects.equals方法比较对象的各个属性值
return Objects.equals(gantryCode, that.getGantryCode()) &&
Objects.equals(getReportTime(), that.getReportTime()) &&
Objects.equals(getPeriodType(), that.getPeriodType());
}
/**
* 重写hashCode方法基于对象的属性生成哈希码
* @return 对象的哈希码值
*/
@Override
public int hashCode() {
return Objects.hash(gantryCode, getReportTime(), getPeriodType());
}
/**
* 生成唯一标识符
* 该方法通过将多个属性结合然后对结合后的字符串进行MD5哈希处理来生成一个唯一标识符
* 结合的属性包括门架站点标识统计日期道路方向统计粒度和出入类型
*/
@Override
public void generateUniqueId() {
// 将多个属性按照指定格式组合成一个字符串
String combinedAttributes = gantryCode + "_" + DateUtil.format(getStatisticalDate(), "yyyyMMdd_HHmmss") + "_" + getPeriodType();
// 对组合后的字符串进行MD5哈希处理,生成唯一标识符,并赋值给当前对象的id属性
this.setId(DigestUtils.md5Hex(combinedAttributes));
}
}

2
zc-business/src/main/java/com/zc/business/domain/DcGantryStatisticsData.java

@ -12,7 +12,7 @@ import java.util.Objects;
* @author xiepufeng
*/
@Data
public class DcGantryStatisticsData extends DcStatisticsData implements Serializable {
public class DcGantryStatisticsData extends DcTrafficFlowStatisticsData implements Serializable {
private static final long serialVersionUID = 1L;

2
zc-business/src/main/java/com/zc/business/domain/DcRegion.java

@ -18,4 +18,6 @@ public class DcRegion {
private String longitude;
@ApiModelProperty("纬度")
private String latitude;
@ApiModelProperty("桩号")
private String stakeNum;
}

100
zc-business/src/main/java/com/zc/business/domain/DcStatisticsData.java

@ -2,16 +2,18 @@ package com.zc.business.domain;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.ruoyi.common.core.domain.BaseEntity;
import com.zc.business.enums.TrafficDataPeriodTypeEnum;
import lombok.Data;
import lombok.Getter;
import lombok.Setter;
import org.springframework.format.annotation.DateTimeFormat;
import java.io.Serializable;
import java.util.Date;
@Data
@Getter
@Setter
public class DcStatisticsData implements Serializable {
private static final long serialVersionUID = 1L;
@ -19,6 +21,7 @@ public class DcStatisticsData implements Serializable {
/**
* 主键
*/
@TableId
private String id;
/**
@ -34,17 +37,13 @@ public class DcStatisticsData implements Serializable {
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone="GMT+8")
private Date reportTime;
/**
* 车流量
*/
private Integer trafficVolume;
/**
* 统计粒度
* 1-
* 2-
* 3-
* 4-
* 5-
*/
private Byte periodType;
@ -58,86 +57,6 @@ public class DcStatisticsData implements Serializable {
*/
private Date updateTime;
/**
* 1型客车车流量
*/
private Integer type1PassengerFlow;
/**
* 2型客车车流量
*/
private Integer type2PassengerFlow;
/**
* 3型客车车流量
*/
private Integer type3PassengerFlow;
/**
* 4型客车车流量
*/
private Integer type4PassengerFlow;
/**
* 1型货车车流量
*/
private Integer type1TruckFlow;
/**
* 2型货车车流量
*/
private Integer type2TruckFlow;
/**
* 3型货车车流量
*/
private Integer type3TruckFlow;
/**
* 4型货车车流量
*/
private Integer type4TruckFlow;
/**
* 5型货车车流量
*/
private Integer type5TruckFlow;
/**
* 6型货车车流量
*/
private Integer type6TruckFlow;
/**
* 1型专项作业车车流量
*/
private Integer type1SpecialVehicleFlow;
/**
* 2型专项作业车车流量
*/
private Integer type2SpecialVehicleFlow;
/**
* 3型专项作业车车流量
*/
private Integer type3SpecialVehicleFlow;
/**
* 4型专项作业车车流量
*/
private Integer type4SpecialVehicleFlow;
/**
* 5型专项作业车车流量
*/
private Integer type5SpecialVehicleFlow;
/**
* 6型专项作业车车流量
*/
private Integer type6SpecialVehicleFlow;
/**
* 开始时间
*/
@ -152,6 +71,7 @@ public class DcStatisticsData implements Serializable {
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date endTime;
public void setPeriodType(Byte periodType) {
this.periodType = periodType;
}
@ -171,6 +91,10 @@ public class DcStatisticsData implements Serializable {
*/
public void setStatisticalDate(Date statisticalDate, TrafficDataPeriodTypeEnum typeEnum) {
switch (typeEnum) {
case HOUR:
// 设置为当年的起始日期
this.statisticalDate = DateUtil.beginOfHour(statisticalDate);
break;
case DAY:
// 设置为当天的起始时间
this.statisticalDate = DateUtil.beginOfDay(statisticalDate);

2
zc-business/src/main/java/com/zc/business/domain/DcTollStationStatisticsData.java

@ -12,7 +12,7 @@ import java.util.Objects;
* @author xiepufeng
*/
@Data
public class DcTollStationStatisticsData extends DcStatisticsData implements Serializable {
public class DcTollStationStatisticsData extends DcTrafficFlowStatisticsData implements Serializable {
private static final long serialVersionUID = 1L;

100
zc-business/src/main/java/com/zc/business/domain/DcTrafficFlowStatisticsData.java

@ -0,0 +1,100 @@
package com.zc.business.domain;
import com.baomidou.mybatisplus.annotation.TableField;
import lombok.Getter;
import lombok.Setter;
import org.springframework.format.annotation.DateTimeFormat;
import java.util.Date;
@Getter
@Setter
public class DcTrafficFlowStatisticsData extends DcStatisticsData {
private static final long serialVersionUID = 1L;
/**
* 车流量
*/
private Integer trafficVolume;
/**
* 1型客车车流量
*/
private Integer type1PassengerFlow;
/**
* 2型客车车流量
*/
private Integer type2PassengerFlow;
/**
* 3型客车车流量
*/
private Integer type3PassengerFlow;
/**
* 4型客车车流量
*/
private Integer type4PassengerFlow;
/**
* 1型货车车流量
*/
private Integer type1TruckFlow;
/**
* 2型货车车流量
*/
private Integer type2TruckFlow;
/**
* 3型货车车流量
*/
private Integer type3TruckFlow;
/**
* 4型货车车流量
*/
private Integer type4TruckFlow;
/**
* 5型货车车流量
*/
private Integer type5TruckFlow;
/**
* 6型货车车流量
*/
private Integer type6TruckFlow;
/**
* 1型专项作业车车流量
*/
private Integer type1SpecialVehicleFlow;
/**
* 2型专项作业车车流量
*/
private Integer type2SpecialVehicleFlow;
/**
* 3型专项作业车车流量
*/
private Integer type3SpecialVehicleFlow;
/**
* 4型专项作业车车流量
*/
private Integer type4SpecialVehicleFlow;
/**
* 5型专项作业车车流量
*/
private Integer type5SpecialVehicleFlow;
/**
* 6型专项作业车车流量
*/
private Integer type6SpecialVehicleFlow;
}

101
zc-business/src/main/java/com/zc/business/domain/DcTrafficPolice.java

@ -0,0 +1,101 @@
package com.zc.business.domain;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import com.ruoyi.common.annotation.Excel;
import com.ruoyi.common.core.domain.BaseEntity;
/**
* 交管数据对象 dc_traffic_police
*
* @author ruoyi
* @date 2024-06-06
*/
@ApiModel("交警信息对象")
public class DcTrafficPolice extends BaseEntity
{
private static final long serialVersionUID = 1L;
/** $column.columnComment */
@ApiModelProperty("ID")
private Long id;
/** $column.columnComment */
@ApiModelProperty("名称")
@Excel(name = "${comment}", readConverterExp = "$column.readConverterExp()")
private String name;
@ApiModelProperty("电话")
/** 电话 */
@Excel(name = "电话")
private String phone;
@ApiModelProperty("开始桩号")
/** $column.columnComment */
@Excel(name = "${comment}", readConverterExp = "$column.readConverterExp()")
private String stakeMake;
/** $column.columnComment */
@ApiModelProperty("结束桩号")
@Excel(name = "${comment}", readConverterExp = "$column.readConverterExp()")
private String endMake;
public void setId(Long id)
{
this.id = id;
}
public Long getId()
{
return id;
}
public void setName(String name)
{
this.name = name;
}
public String getName()
{
return name;
}
public void setPhone(String phone)
{
this.phone = phone;
}
public String getPhone()
{
return phone;
}
public void setStakeMake(String stakeMake)
{
this.stakeMake = stakeMake;
}
public String getStakeMake()
{
return stakeMake;
}
public void setEndMake(String endMake)
{
this.endMake = endMake;
}
public String getEndMake()
{
return endMake;
}
@Override
public String toString() {
return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
.append("id", getId())
.append("name", getName())
.append("phone", getPhone())
.append("stakeMake", getStakeMake())
.append("endMake", getEndMake())
.append("createTime", getCreateTime())
.append("updateTime", getUpdateTime())
.toString();
}
}

92
zc-business/src/main/java/com/zc/business/domain/DcTrafficSectionData.java

@ -1,14 +1,9 @@
package com.zc.business.domain;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.zc.business.enums.TrafficDataPeriodTypeEnum;
import lombok.Data;
import org.apache.commons.codec.digest.DigestUtils;
import java.util.Date;
import java.util.Objects;
/**
@ -16,13 +11,7 @@ import java.util.Objects;
* @author xiepufeng
*/
@Data
public class DcTrafficSectionData {
/**
* 主键
*/
@TableId
private String id;
public class DcTrafficSectionData extends DcStatisticsData {
/**
* 车流量
@ -44,30 +33,11 @@ public class DcTrafficSectionData {
*/
private Long deviceId;
/**
* 统计时间
*/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone="GMT+8")
private Date statisticalDate;
/**
* 上报时间
*/
@TableField(exist = false)
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone="GMT+8")
private Date reportTime;
/**
* 道路方向
*/
private Byte direction;
/**
* 时段类型
* 1- 2- 3- 4-
*/
private Byte periodType;
/**
* 所在桩号
@ -80,28 +50,6 @@ public class DcTrafficSectionData {
private Integer deviceType;
/** 创建时间 */
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone="GMT+8")
private Date createTime;
/** 更新时间 */
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone="GMT+8")
private Date updateTime;
public void setPeriodType(Byte periodType) {
this.periodType = periodType;
}
/**
* 设置交通数据的统计周期类型
* @param periodType 统计周期类型的枚举值
*/
public void setPeriodType(TrafficDataPeriodTypeEnum periodType) {
this.periodType = periodType.getCode(); // 将枚举类型转换为代码值存储
}
/**
* 重写equals方法用于比较两个对象是否相等
* @param o 要与当前对象比较的对象
@ -113,9 +61,9 @@ public class DcTrafficSectionData {
if (o == null || getClass() != o.getClass()) return false; // 对象为空或类型不同,返回false
DcTrafficSectionData that = (DcTrafficSectionData) o; // 类型转换
return Objects.equals(deviceId, that.deviceId) &&
Objects.equals(reportTime, that.reportTime) &&
Objects.equals(getReportTime(), that.getReportTime()) &&
Objects.equals(direction, that.direction) &&
Objects.equals(periodType, that.periodType) &&
Objects.equals(getPeriodType(), that.getPeriodType()) &&
Objects.equals(stakeMark, that.stakeMark); // 比较各属性值
}
@ -125,44 +73,16 @@ public class DcTrafficSectionData {
*/
@Override
public int hashCode() {
return Objects.hash(deviceId, reportTime, direction, periodType, stakeMark);
return Objects.hash(deviceId, getReportTime(), direction, getPeriodType(), stakeMark);
}
/**
* 根据给定的统计周期类型和日期设置统计日期为相应周期的起始日期
* @param statisticalDate 原始统计日期
* @param typeEnum 统计周期类型
*/
public void setStatisticalDate(Date statisticalDate, TrafficDataPeriodTypeEnum typeEnum) {
switch (typeEnum) {
case DAY:
// 设置为当天的起始时间
this.statisticalDate = DateUtil.beginOfDay(statisticalDate);
break;
case MONTH:
// 设置为当月的起始日期
this.statisticalDate = DateUtil.beginOfMonth(statisticalDate);
break;
case QUARTER:
// 设置为当季度的起始日期
this.statisticalDate = DateUtil.beginOfQuarter(statisticalDate);
break;
case YEAR:
// 设置为当年的起始日期
this.statisticalDate = DateUtil.beginOfYear(statisticalDate);
break;
default:
// 如果不是预定义的周期类型,则不做任何处理
this.statisticalDate = statisticalDate;
}
}
/**
* 根据设备ID统计时间方向时段类型桩号生成一个唯一ID
*/
public void generateUniqueId() {
String combinedAttributes = deviceId + "_" + DateUtil.format(statisticalDate, "yyyyMMdd_HHmmss") + "_" + direction + "_" + periodType + "_" + stakeMark;
this.id = DigestUtils.md5Hex(combinedAttributes);
String combinedAttributes = deviceId + "_" + DateUtil.format(getStatisticalDate(), "yyyyMMdd_HHmmss") + "_" + direction + "_" + getPeriodType() + "_" + stakeMark;
this.setId(DigestUtils.md5Hex(combinedAttributes));
}
}

52
zc-business/src/main/java/com/zc/business/domain/MdEvent.java

@ -4,6 +4,7 @@ import java.math.BigDecimal;
import java.util.Date;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.ruoyi.common.utils.StringUtils;
import com.zc.business.enums.ValueConverter;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import com.ruoyi.common.annotation.Excel;
@ -33,6 +34,10 @@ public class MdEvent
@Excel(name = "交通事件类型")
private String eventTypeCode;
/** 交通事件类型名称 */
@Excel(name = "交通事件类型名称")
private String eventTypeName;
/** 交通事件详情 */
@Excel(name = "交通事件详情")
private String eventDesc;
@ -99,6 +104,10 @@ public class MdEvent
@Excel(name = "交通事件类型子类")
private String eventTypeCode2;
/** 交通事件类型子类名称 */
@Excel(name = "交通事件类型子类名称")
private String eventTypeName2;
/** 交通事件原因 */
@Excel(name = "交通事件原因")
private String eventCause;
@ -534,6 +543,22 @@ public class MdEvent
return deletionTime;
}
public String getEventTypeName() {
return eventTypeName;
}
public void setEventTypeName(String eventTypeName) {
this.eventTypeName = eventTypeName;
}
public String getEventTypeName2() {
return eventTypeName2;
}
public void setEventTypeName2(String eventTypeName2) {
this.eventTypeName2 = eventTypeName2;
}
@Override
public String toString() {
return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
@ -576,6 +601,8 @@ public class MdEvent
.append("isDeleted", getIsDeleted())
.append("deleterUserId", getDeleterUserId())
.append("deletionTime", getDeletionTime())
.append("eventTypeName", getEventTypeName())
.append("eventTypeName2", getEventTypeName2())
.toString();
}
@ -604,6 +631,7 @@ public class MdEvent
// 11-其他事件
String eventType = dcEvent.getEventType().toString();
this.eventTypeCode = eventType;
this.eventTypeName = ValueConverter.eventTypeName(eventType);
if ("1".equals(eventType)){
DcEventAccident dcEventAccident = dcEvent.getDcEventAccident();
if (dcEventAccident != null){
@ -675,25 +703,14 @@ public class MdEvent
this.lane = dcEvent.getLang();
//方向:1-上 2-中 3-下
this.direction = dcEvent.getDirection();
//经纬度
this.longitude = dcEvent.getLongitude();
this.latitude = dcEvent.getDimension();
//事件来源编码
this.eventSourceCode = dcEvent.getEventSource();
//事件来源编码 1-96659,2-交警转接,3-道路巡查,4-视频巡查,5-视频AI,6-一键救援,7-其他
if (dcEvent.getEventSource() != null && dcEvent.getEventSource() > 0){
if (dcEvent.getEventSource() == 1){
this.eventSource = "96659";
} else if (dcEvent.getEventSource() == 2){
this.eventSource = "交警转接";
} else if (dcEvent.getEventSource() == 3){
this.eventSource = "道路巡查";
} else if (dcEvent.getEventSource() == 4){
this.eventSource = "视频巡查";
} else if (dcEvent.getEventSource() == 5){
this.eventSource = "视频AI";
} else if (dcEvent.getEventSource() == 6){
this.eventSource = "一键救援";
} else if (dcEvent.getEventSource() == 7){
this.eventSource = "其他";
}
this.eventSource = ValueConverter.eventSourceName(dcEvent.getEventSource().toString());
}
//事件状态:0-待确认,1-处理中,2-已完成
this.eventStatus = dcEvent.getEventState();
@ -704,7 +721,10 @@ public class MdEvent
this.sectionId = dcEvent.getRoadId().toString();
}
//交通事件类型子类
this.eventTypeCode2 = dcEvent.getEventSubclass();
if (StringUtils.isNotEmpty(dcEvent.getEventSubclass())) {
this.eventTypeCode2 = dcEvent.getEventSubclass();
this.eventTypeName2 = ValueConverter.eventSubclassName(dcEvent.getEventSubclass());
}
//事件原因
this.eventCause = dcEvent.getEventCause();
}

38
zc-business/src/main/java/com/zc/business/enums/ChannelCongestionLevelEnum.java

@ -12,27 +12,27 @@ public enum ChannelCongestionLevelEnum {
/**
* 表示通道畅通速度阈值为70 km/h
*/
FLOWING(70, 0, "畅通"),
FLOWING(70, 0, 1,"畅通"),
/**
* 表示通道基本畅通速度阈值为50 km/h
*/
BASIC_FLOWING(50, 0, "基本畅通"),
BASIC_FLOWING(50, 0, 2, "基本畅通"),
/**
* 表示通道轻度拥堵速度阈值为40 km/h
*/
LIGHT_CONGESTION(40, 1000, "轻度拥堵"),
LIGHT_CONGESTION(40, 1000, 3, "轻度拥堵"),
/**
* 表示通道中度拥堵速度阈值为20 km/h
*/
MEDIUM_CONGESTION(20, 2000, "中度拥堵"),
MEDIUM_CONGESTION(20, 2000, 4, "中度拥堵"),
/**
* 使用负数作为默认值表示无限小始终小于其他速度阈值表示通道严重拥堵
*/
SEVERE_CONGESTION(-1, 4000, "严重拥堵");
SEVERE_CONGESTION(-1, 4000, 5, "严重拥堵");
/**
* 速度阈值用于判断通道拥挤程度
@ -44,6 +44,11 @@ public enum ChannelCongestionLevelEnum {
*/
private final int defaultCongestionDistance;
/**
* 等级
*/
private final int level;
/**
* 对拥挤度等级的描述
*/
@ -55,9 +60,10 @@ public enum ChannelCongestionLevelEnum {
* @param speedThreshold 速度阈值
* @param description 等级描述
*/
ChannelCongestionLevelEnum(int speedThreshold, int defaultCongestionDistance, String description) {
ChannelCongestionLevelEnum(int speedThreshold, int defaultCongestionDistance, int level, String description) {
this.speedThreshold = speedThreshold;
this.defaultCongestionDistance = defaultCongestionDistance;
this.level = level;
this.description = description;
}
@ -164,4 +170,24 @@ public enum ChannelCongestionLevelEnum {
ChannelCongestionLevelEnum currentLevel = fromSpeed(speed);
return currentLevel == level;
}
/**
* 根据描述获取频道拥堵级别枚举值
* 该方法遍历所有ChannelCongestionLevelEnum的实例通过匹配描述来寻找对应的枚举值
* 如果找不到匹配的枚举值则抛出IllegalArgumentException
*
* @param description 频道拥堵级别的描述字符串
* @return 匹配描述的频道拥堵级别枚举值
* @throws IllegalArgumentException 如果描述不匹配任何枚举值则抛出此异常
*/
public static ChannelCongestionLevelEnum fromDescription(String description) {
for (ChannelCongestionLevelEnum value : values()) {
if (value.getDescription().equals(description)) {
return value;
}
}
throw new IllegalArgumentException("无效的指数值: " + description);
}
}

52
zc-business/src/main/java/com/zc/business/enums/StakeMarkRange.java

@ -0,0 +1,52 @@
package com.zc.business.enums;
/**
*
*/
public enum StakeMarkRange {
ONE(54394, 59289, 1,"殷家林枢纽"),
TWO(59289, 72847,2, "大学城立交"),
THREE(72847, 83835,3, "长清立交"),
FOUR(83835, 86499,4, "松竹枢纽"),
FIVE(86499, 99750,5, "孝里立交"),
SIX(99750, 105904, 6,"平阴北立交"),
SEVEN(105904, 117878,7, "平阴立交"),
EIGHT(117878, 126233,8, "孔村枢纽"),
NINE(126233, 145933, 9,"平阴南立交"),
TEN(145933, 155652, 10,"东平立交"),
DONGPING_LAKE_HUB(155652,173950,11,"东平湖枢纽"),
LIANGSHANDONG_INTERCHANGE(173950,179396,12,"梁山东立交"),
LIANGSHAN_INTERCHANGE(179396,190495,13,"梁山立交"),
JIAXIANG_WEST_INTERCHANGE(190495,202979,14,"嘉祥西立交");
private final int stakeMark;
private final int endMark;
private final int identification;
private final String description;
public int getStakeMark() {
return stakeMark;
}
public int getEndMark() {
return endMark;
}
public String getDescription() {
return description;
}
public int getIdentification() {
return identification;
}
StakeMarkRange(int stakeMark, int endMark, int identification, String description) {
this.stakeMark = stakeMark;
this.endMark = endMark;
this.identification = identification;
this.description = description;
}
}

72
zc-business/src/main/java/com/zc/business/enums/TrafficCompositionRateEnum.java

@ -0,0 +1,72 @@
package com.zc.business.enums;
import lombok.Getter;
/**
* 交通组成特征指数大车占比枚举类
* 包括低高三类
* @author xiepufeng
*/
@Getter
public enum TrafficCompositionRateEnum {
// 低交通组成率
LOW(1, "低"),
// 中交通组成率
MEDIUM(2, "中"),
// 高交通组成率
HIGH(3, "高");
// 码值,代表每个枚举值的唯一标识
private final int code;
// 描述,对每个枚举值的级别进行文字描述
private final String description;
/**
* 构造方法初始化枚举值的码值和描述
*
* @param code 码值
* @param description 描述
*/
TrafficCompositionRateEnum(int code, String description) {
this.code = code;
this.description = description;
}
/**
* 根据码值获取枚举值
*
* @param code 码值
* @return 对应码值的枚举常量
* @throws IllegalArgumentException 如果码值无效则抛出此异常
*/
// 根据索引值获取枚举值,提供一个静态方法
public static TrafficCompositionRateEnum fromCode(int code) {
for (TrafficCompositionRateEnum value : values()) {
if (value.getCode() == code) {
return value;
}
}
throw new IllegalArgumentException("无效的指数值: " + code);
}
/**
* 根据描述字符串获取交通组成比率枚举值
* 该方法遍历所有TrafficCompositionRateEnum枚举常量找到其描述与输入字符串匹配的枚举值
* 如果找到匹配的枚举值则返回该枚举值如果没有匹配的枚举值则抛出IllegalArgumentException异常
* 这个方法的存在是为了提供一种通过枚举的描述而不是枚举名称来获取枚举常量的方法
*
* @param description 描述字符串用于匹配枚举值的描述
* @return 匹配描述的TrafficCompositionRateEnum枚举值
* @throws IllegalArgumentException 如果没有找到匹配的枚举值则抛出此异常
*/
public static TrafficCompositionRateEnum fromDescription(String description) {
for (TrafficCompositionRateEnum value : values()) {
if (value.getDescription().equals(description)) {
return value;
}
}
throw new IllegalArgumentException("无效的指数值: " + description);
}
}

5
zc-business/src/main/java/com/zc/business/enums/TrafficDataPeriodTypeEnum.java

@ -17,7 +17,10 @@ public enum TrafficDataPeriodTypeEnum {
MONTH((byte) 3, "月"),
// 枚举成员:日,关联字节型代码 4 和描述 "日"
DAY((byte) 4, "日");
DAY((byte) 4, "日"),
// 枚举成员:小时,关联字节型代码 4 和描述 "小时"
HOUR((byte) 5, "小时");
// 每个枚举成员的属性:代码,存储对应的字节型数值
private final Byte code;

65
zc-business/src/main/java/com/zc/business/enums/ValueConverter.java

@ -26,6 +26,8 @@ public class ValueConverter {
private static final Map<String, String> eventSourceName = new HashMap<>();
// 事件类型名称
private static final Map<String, String> eventTypeName = new HashMap<>();
// 事件子类名称
private static final Map<String, String> eventSubclassName = new HashMap<>();
// 事件字段
private static final Map<String, String> eventLabel = new HashMap<>();
@ -121,6 +123,60 @@ public class ValueConverter {
eventTypeName.put("10","异常天气");
eventTypeName.put("11","其他事件");
eventSubclassName.put("1-1","追尾");
eventSubclassName.put("1-2","侧翻");
eventSubclassName.put("1-3","撞护栏");
eventSubclassName.put("1-4","自然");
eventSubclassName.put("1-5","其他事故");
eventSubclassName.put("2-1","车辆故障");
eventSubclassName.put("3-1","主线封闭和限行");
eventSubclassName.put("3-2","收费站封闭和限行");
eventSubclassName.put("3-3","立交封闭和限行");
eventSubclassName.put("3-4","服务区封闭和限行");
eventSubclassName.put("4-1","道路拥堵");
eventSubclassName.put("4-2","立交拥堵");
eventSubclassName.put("4-3","收费站拥堵");
eventSubclassName.put("4-4","服务区拥堵");
eventSubclassName.put("5-1","行人");
eventSubclassName.put("5-2","非机动车");
eventSubclassName.put("5-3","摩托车");
eventSubclassName.put("5-4","其他");
eventSubclassName.put("6-1","烟雾");
eventSubclassName.put("6-2","倒伏树木");
eventSubclassName.put("6-3","撒落物");
eventSubclassName.put("6-4","动物");
eventSubclassName.put("6-5","其他");
eventSubclassName.put("7-1","道路养护施工");
eventSubclassName.put("7-2","收费站养护施工");
eventSubclassName.put("7-3","服务区养护施工");
eventSubclassName.put("7-4","枢纽立交匝道养护施工");
eventSubclassName.put("7-5","地方道路养护施工");
eventSubclassName.put("7-6","道路工程建设施工");
eventSubclassName.put("7-7","收费站工程建设施工");
eventSubclassName.put("7-8","服务区工程建设施工");
eventSubclassName.put("7-9","枢纽立交匝道工程建设施工");
eventSubclassName.put("7-10","地方道路工程建设施工");
eventSubclassName.put("8-1","封闭、暂停营业");
eventSubclassName.put("8-2","重要设施停用");
eventSubclassName.put("8-3","服务区其他异常");
eventSubclassName.put("9-1","摄像机");
eventSubclassName.put("9-2","护栏");
eventSubclassName.put("9-3","隔离栅");
eventSubclassName.put("9-4","情报板");
eventSubclassName.put("9-5","防炫板");
eventSubclassName.put("9-6","其他");
eventSubclassName.put("10-1","雨");
eventSubclassName.put("10-2","雪");
eventSubclassName.put("10-3","雾");
eventSubclassName.put("10-4","大风");
eventSubclassName.put("10-5","低温寒潮");
eventSubclassName.put("10-6","路面积雪");
eventSubclassName.put("10-7","路面结冰");
eventSubclassName.put("10-8","路面积水");
eventSubclassName.put("10-9","其他");
eventSubclassName.put("11-1","其他事件");
eventLabel.put("id","事件编号");
eventLabel.put("deptId","所属部门");
eventLabel.put("stakeMark","桩号");
@ -255,6 +311,11 @@ public class ValueConverter {
public static Map<String, String> getEventLabel() {
return ValueMappingHolder.eventLabel;
}
public static Map<String, String> getEventSubclassName() {
return ValueMappingHolder.eventSubclassName;
}
/**
* 根据输入值返回转换后的值
* 如果输入值不在映射中则返回输入值本身
@ -288,6 +349,10 @@ public class ValueConverter {
Map<String, String> mapping = getEventLabel();
return mapping.getOrDefault(inputValue, "");
}
public static String eventSubclassName(String inputValue) {
Map<String, String> mapping = getEventSubclassName();
return mapping.getOrDefault(inputValue, inputValue);
}
//测试
// @Test

2
zc-business/src/main/java/com/zc/business/mapper/DcEventMapper.java

@ -121,6 +121,8 @@ public interface DcEventMapper extends BaseMapper<DcEvent>
int selectClearInfo(String eventId);
List<DcEvent> dispatchRecordEventList(DcEvent dcEvent);
Long selectEventNumByStatus(@Param("status") String status);
}

32
zc-business/src/main/java/com/zc/business/mapper/DcGantryMetricsStatisticsDataMapper.java

@ -0,0 +1,32 @@
package com.zc.business.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.zc.business.domain.DcGantryMetricsStatisticsData;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
/**
* 门架指标数据统计Mapper接口
*
* @author xiepufeng
*/
@Mapper
public interface DcGantryMetricsStatisticsDataMapper extends BaseMapper<DcGantryMetricsStatisticsData> {
/**
* 插入或更新门架指标数据
*
* @param gantryTrafficMetricsData 门架指标数据对象包含需要插入或更新的数据
* @return 返回一个布尔值表示操作是否成功true表示插入或更新成功false表示失败
*/
boolean insertOrUpdate(DcGantryMetricsStatisticsData gantryTrafficMetricsData);
/**
* 批量插入或更新新门架指标数据
*
* @param gantryTrafficMetricsDataList 要插入或更新的新门架指标数据对象列表
* @return 影响的记录数通常对于批量操作这个值可能不准确因为每个 INSERT/UPDATE 可能影响不同的记录数
*/
int insertOrUpdateBatch(List<DcGantryMetricsStatisticsData> gantryTrafficMetricsDataList);
}

16
zc-business/src/main/java/com/zc/business/mapper/DcGantryStatisticsDataMapper.java

@ -3,8 +3,11 @@ package com.zc.business.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.zc.business.domain.DcGantryStatisticsData;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.Date;
import java.util.List;
import java.util.Map;
/**
* 这是一个接口的注释用于描述门架数据统计的Mapper
@ -23,11 +26,24 @@ public interface DcGantryStatisticsDataMapper extends BaseMapper<DcGantryStatist
*/
boolean insertOrUpdate(DcGantryStatisticsData gantryStatisticsData);
/**
* 批量插入或更新门架数据统计
*
* @param dcGantryStatisticsDataList 门架数据统计对象列表包含需要插入或更新的数据
* @return 返回一个整数表示插入或更新操作影响的行数
*/
int insertOrUpdateBatch(List<DcGantryStatisticsData> dcGantryStatisticsDataList);
/**
* 获取最大的统计日期
*
* @return 返回最大的统计日期
*/
Date getMaxStatisticalDate();
/**
* 全路段双向实时车流量
*/
List<Map<String, String>> realTimeTrafficFlow(@Param("startDate") String startDate, @Param("direction")String direction, @Param("periodType")String periodType );
}

3
zc-business/src/main/java/com/zc/business/mapper/DcStakeMarkMapper.java

@ -4,6 +4,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.zc.business.domain.DcDevice;
import com.zc.business.domain.DcStakeMark;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
@ -18,4 +19,6 @@ public interface DcStakeMarkMapper extends BaseMapper<DcStakeMark> {
boolean batchInsert(List<DcStakeMark> dcStakeMarkList);
DcStakeMark selectByDirection(@Param("stakeMark") String stakeMark,@Param("direction") String direction);
}

64
zc-business/src/main/java/com/zc/business/mapper/DcTrafficPoliceMapper.java

@ -0,0 +1,64 @@
package com.zc.business.mapper;
import com.zc.business.domain.DcTrafficPolice;
import java.util.List;
/**
* 交管数据Mapper接口
*
* @author ruoyi
* @date 2024-06-06
*/
public interface DcTrafficPoliceMapper
{
/**
* 查询交管数据
*
* @param id 交管数据主键
* @return 交管数据
*/
public DcTrafficPolice selectDcTrafficPoliceById(Long id);
/**
* 查询交管数据列表
*
* @param dcTrafficPolice 交管数据
* @return 交管数据集合
*/
List<DcTrafficPolice> selectDcTrafficPoliceList(DcTrafficPolice dcTrafficPolice);
/**
* 新增交管数据
*
* @param dcTrafficPolice 交管数据
* @return 结果
*/
int insertDcTrafficPolice(DcTrafficPolice dcTrafficPolice);
/**
* 修改交管数据
*
* @param dcTrafficPolice 交管数据
* @return 结果
*/
int updateDcTrafficPolice(DcTrafficPolice dcTrafficPolice);
/**
* 删除交管数据
*
* @param id 交管数据主键
* @return 结果
*/
int deleteDcTrafficPoliceById(Long id);
/**
* 批量删除交管数据
*
* @param ids 需要删除的数据主键集合
* @return 结果
*/
int deleteDcTrafficPoliceByIds(Long[] ids);
public DcTrafficPolice selectEvent(String make);
}

2
zc-business/src/main/java/com/zc/business/mapper/DcWarningMapper.java

@ -150,4 +150,6 @@ public interface DcWarningMapper
public String organizationName(Long id);
//事件id查询调度记录id
public HashMap selectDispatchId(@Param("eventId")String eventId);
Long selectWarningNum();
}

29
zc-business/src/main/java/com/zc/business/message/device/listener/TrafficGantryPlatesListener.java

@ -1,29 +0,0 @@
package com.zc.business.message.device.listener;
import com.zc.common.core.redis.stream.RedisStream;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.data.redis.connection.stream.ObjectRecord;
import org.springframework.data.redis.connection.stream.RecordId;
import org.springframework.data.redis.stream.StreamListener;
import org.springframework.stereotype.Component;
/**
* 门架牌识
*/
@Component
public class TrafficGantryPlatesListener implements StreamListener<String, ObjectRecord<String, String>>
{
@Autowired
@Qualifier("iotRedisStream")
private RedisStream redisStream;
@Override
public void onMessage(ObjectRecord<String, String> message) {
String streamKay = message.getStream();
RecordId recordId = message.getId();
// 消费完后直接删除消息
redisStream.del(streamKay, String.valueOf(recordId));
}
}

29
zc-business/src/main/java/com/zc/business/message/device/listener/TrafficGantryTransactionsListener.java

@ -1,29 +0,0 @@
package com.zc.business.message.device.listener;
import com.zc.common.core.redis.stream.RedisStream;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.data.redis.connection.stream.ObjectRecord;
import org.springframework.data.redis.connection.stream.RecordId;
import org.springframework.data.redis.stream.StreamListener;
import org.springframework.stereotype.Component;
/**
* 门架交易流水消息监听
*/
@Component
public class TrafficGantryTransactionsListener implements StreamListener<String, ObjectRecord<String, String>>
{
@Autowired
@Qualifier("iotRedisStream")
private RedisStream redisStream;
@Override
public void onMessage(ObjectRecord<String, String> message) {
String streamKay = message.getStream();
RecordId recordId = message.getId();
// 消费完后直接删除消息
redisStream.del(streamKay, String.valueOf(recordId));
}
}

29
zc-business/src/main/java/com/zc/business/message/device/listener/TrafficTollStationEntranceListener.java

@ -1,29 +0,0 @@
package com.zc.business.message.device.listener;
import com.zc.common.core.redis.stream.RedisStream;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.data.redis.connection.stream.ObjectRecord;
import org.springframework.data.redis.connection.stream.RecordId;
import org.springframework.data.redis.stream.StreamListener;
import org.springframework.stereotype.Component;
/**
* 收费入口数据
*/
@Component
public class TrafficTollStationEntranceListener implements StreamListener<String, ObjectRecord<String, String>>
{
@Autowired
@Qualifier("iotRedisStream")
private RedisStream redisStream;
@Override
public void onMessage(ObjectRecord<String, String> message) {
String streamKay = message.getStream();
RecordId recordId = message.getId();
// 消费完后直接删除消息
redisStream.del(streamKay, String.valueOf(recordId));
}
}

29
zc-business/src/main/java/com/zc/business/message/device/listener/TrafficTollStationExitListener.java

@ -1,29 +0,0 @@
package com.zc.business.message.device.listener;
import com.zc.common.core.redis.stream.RedisStream;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.data.redis.connection.stream.ObjectRecord;
import org.springframework.data.redis.connection.stream.RecordId;
import org.springframework.data.redis.stream.StreamListener;
import org.springframework.stereotype.Component;
/**
* 收费出口数据
*/
@Component
public class TrafficTollStationExitListener implements StreamListener<String, ObjectRecord<String, String>>
{
@Autowired
@Qualifier("iotRedisStream")
private RedisStream redisStream;
@Override
public void onMessage(ObjectRecord<String, String> message) {
String streamKay = message.getStream();
RecordId recordId = message.getId();
// 消费完后直接删除消息
redisStream.del(streamKay, String.valueOf(recordId));
}
}

41
zc-business/src/main/java/com/zc/business/message/device/subscribe/MessageSubscription.java

@ -49,18 +49,6 @@ public class MessageSubscription implements CommandLineRunner {
@Resource
private DeviceFunctionReplyListener deviceFunctionReplyListener;
@Resource
private TrafficGantryTransactionsListener trafficGantryTransactionsListener;
@Resource
private TrafficGantryPlatesListener trafficGantryPlatesListener;
@Resource
private TrafficTollStationEntranceListener trafficTollStationEntranceListener;
@Resource
private TrafficTollStationExitListener trafficTollStationExitListener;
@Override
public void run(String... args) {
@ -113,34 +101,5 @@ public class MessageSubscription implements CommandLineRunner {
RedisStreamConstants.DeviceFunctionReply.CONSUMER,
deviceFunctionReplyListener);
// 门架交易流水
redisStream.subscriptionAutoAck(
RedisStreamConstants.TrafficGantryTransactions.KEY,
RedisStreamConstants.TrafficGantryTransactions.GROUP,
RedisStreamConstants.TrafficGantryTransactions.CONSUMER,
trafficGantryTransactionsListener);
// 门架牌识
iotRedisStream.subscriptionAutoAck(
RedisStreamConstants.TrafficGantryPlates.KEY,
RedisStreamConstants.TrafficGantryPlates.GROUP,
RedisStreamConstants.TrafficGantryPlates.CONSUMER,
trafficGantryPlatesListener);
// 收费入口数据
redisStream.subscriptionAutoAck(
RedisStreamConstants.TrafficTollStationEntrance.KEY,
RedisStreamConstants.TrafficTollStationEntrance.GROUP,
RedisStreamConstants.TrafficTollStationEntrance.CONSUMER,
trafficTollStationEntranceListener);
// 收费出口数据
redisStream.subscriptionAutoAck(
RedisStreamConstants.TrafficTollStationExit.KEY,
RedisStreamConstants.TrafficTollStationExit.GROUP,
RedisStreamConstants.TrafficTollStationExit.CONSUMER,
trafficTollStationExitListener);
}
}

10
zc-business/src/main/java/com/zc/business/service/IDcEventService.java

@ -139,4 +139,14 @@ public interface IDcEventService
AjaxResult getLinkEvent(String eventId);
List<DcEvent> dispatchRecordEventList(DcEvent dcEvent);
/**
* @Description 获取事件数量
*
* @author liuwenge
* @date 2024/6/6 18:45
* @param type 类型 1:告警 2:待确认 3:处置中
* @return com.ruoyi.common.core.domain.AjaxResult
*/
AjaxResult getCountNum(String type);
}

1
zc-business/src/main/java/com/zc/business/service/IDcFacilityService.java

@ -60,4 +60,5 @@ public interface IDcFacilityService extends IService<DcFacility> {
* @return 设备信息
*/
DcFacility getFacility(String id);
DcFacility getfacilityCode(String id);
}

42
zc-business/src/main/java/com/zc/business/service/IDcGantryMetricsStatisticsDataService.java

@ -0,0 +1,42 @@
package com.zc.business.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.zc.business.domain.DcGantryMetricsStatisticsData;
import com.zc.business.domain.DcGantryMetricsStatisticsData;
import com.zc.business.domain.DcGantryMetricsStatisticsData;
import java.util.List;
/**
* 门架指标统计服务接口提供处理交通数据的相关方法
* @author xiepufeng
*/
public interface IDcGantryMetricsStatisticsDataService extends IService<DcGantryMetricsStatisticsData> {
/**
* 获取过去一小时的DcGantryMetricsStatisticsData数据列表
*
* <p>此方法不接受任何参数返回一个包含过去一小时所有符合条件的DcGantryMetricsStatisticsData对象的列表
* 该列表可用于进一步的数据分析和处理
*
* @return List<DcGantryMetricsStatisticsData> - 过去一小时的DcGantryMetricsStatisticsData数据列表
*/
List<DcGantryMetricsStatisticsData> lastHourData();
/**
* 获取当月的DcGantryMetricsStatisticsData数据列表
*
* <p>此方法不接受任何参数返回一个包含当月所有符合条件的DcGantryMetricsStatisticsData对象的列表
* 该列表可用于进一步的数据分析和处理
*
* @return List<DcGantryMetricsStatisticsData> - 当月的DcGantryMetricsStatisticsData数据列表
*/
List<DcGantryMetricsStatisticsData> currentMonthData();
/**
* 根据请求条件获取门架指标统计数据
* @param request 请求条件
* @return 门架指标统计数据列表
*/
List<DcGantryMetricsStatisticsData> gantryMetricsData(DcGantryMetricsStatisticsData request);
}

18
zc-business/src/main/java/com/zc/business/service/IDcGantryStatisticsDataService.java

@ -2,10 +2,9 @@ package com.zc.business.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.zc.business.domain.DcGantryStatisticsData;
import com.zc.business.domain.DcStatisticsData;
import com.zc.business.domain.DcTollStationStatisticsData;
import java.util.List;
import java.util.Map;
/**
* 门架数据统计接口该接口扩展了IService接口用于对DcGantryStatisticsData类型的实体进行数据库操作
@ -25,6 +24,16 @@ public interface IDcGantryStatisticsDataService extends IService<DcGantryStatist
*/
List<DcGantryStatisticsData> lastHourData();
/**
* 获取当月的门架统计数据列表
*
* <p>此方法不接受任何参数返回一个包含当月所有符合条件的DcGantryStatisticsData对象的列表
* 该列表可用于进一步的数据分析和处理
*
* @return List<DcGantryStatisticsData> - 当月的DcGantryStatisticsData数据列表
*/
List<DcGantryStatisticsData> currentMonthData();
/**
* 进行门架数据统计的函数
* 该方法接收一个DcGantryStatisticsData类型的对象作为输入参数用来包含门架统计所需的各项数据
@ -34,4 +43,9 @@ public interface IDcGantryStatisticsDataService extends IService<DcGantryStatist
* @return 返回一个DcGantryStatisticsData对象的列表包含统计后的结果
*/
List<DcGantryStatisticsData> gantryData(DcGantryStatisticsData dcGantryStatisticsData);
/**
* 全路段双向实时车流量
*/
List<Map<String, String>> realTimeTrafficFlow(String startDate, String direction,String periodType );
}

2
zc-business/src/main/java/com/zc/business/service/IDcTollStationStatisticsDataService.java

@ -1,8 +1,6 @@
package com.zc.business.service;
import com.alibaba.fastjson.JSONArray;
import com.baomidou.mybatisplus.extension.service.IService;
import com.zc.business.domain.DcStatisticsData;
import com.zc.business.domain.DcTollStationStatisticsData;
import java.util.List;

64
zc-business/src/main/java/com/zc/business/service/IDcTrafficPoliceService.java

@ -0,0 +1,64 @@
package com.zc.business.service;
import com.zc.business.domain.DcTrafficPolice;
import java.util.List;
/**
* 交管数据Service接口
*
* @author ruoyi
* @date 2024-06-06
*/
public interface IDcTrafficPoliceService
{
/**
* 查询交管数据
*
* @param id 交管数据主键
* @return 交管数据
*/
public DcTrafficPolice selectDcTrafficPoliceById(Long id);
/**
* 查询交管数据列表
*
* @param dcTrafficPolice 交管数据
* @return 交管数据集合
*/
List<DcTrafficPolice> selectDcTrafficPoliceList(DcTrafficPolice dcTrafficPolice);
/**
* 新增交管数据
*
* @param dcTrafficPolice 交管数据
* @return 结果
*/
int insertDcTrafficPolice(DcTrafficPolice dcTrafficPolice);
/**
* 修改交管数据
*
* @param dcTrafficPolice 交管数据
* @return 结果
*/
int updateDcTrafficPolice(DcTrafficPolice dcTrafficPolice);
/**
* 批量删除交管数据
*
* @param ids 需要删除的交管数据主键集合
* @return 结果
*/
int deleteDcTrafficPoliceByIds(Long[] ids);
/**
* 删除交管数据信息
*
* @param id 交管数据主键
* @return 结果
*/
int deleteDcTrafficPoliceById(Long id);
public DcTrafficPolice selectEvent(String make);
}

29
zc-business/src/main/java/com/zc/business/service/IDcTrafficStatisticsService.java

@ -2,7 +2,6 @@ package com.zc.business.service;
import com.alibaba.fastjson.JSONArray;
import com.zc.business.domain.DcRoadSectionCongestion;
import com.zc.business.domain.DcStatisticsData;
import com.zc.common.core.httpclient.exception.HttpException;
import java.io.IOException;
@ -11,14 +10,6 @@ import java.util.Map;
public interface IDcTrafficStatisticsService {
/**
* 根据传入的统计请求数据查询历史累计车流量数据
*
* @param request 包含统计查询条件的DcStatisticsData对象用于指定查询的历史流量数据的细节如时间范围等
* @return 返回一个DcStatisticsData列表
*/
List<DcStatisticsData> historyFlow(DcStatisticsData request);
/**
* 获取在途车辆流量分车型
*/
@ -43,4 +34,24 @@ public interface IDcTrafficStatisticsService {
* 获取车道占有率信息
*/
JSONArray laneOccupancy(String startDate, String endDate) throws HttpException, IOException;
/**
* 获取门架指标数据
*/
JSONArray gantryMetrics(String startTime, String endTime) throws HttpException, IOException;
/**
* 断面小时车流量分车型
*/
JSONArray sectionHourlyTrafficFlow(String startDate, String endDate) throws HttpException, IOException;
/**
* 各收费站入口分车型小时车流量
*/
List<Map<String, String>>trafficFlowAtTollStationEntrance(String startDate, String endDate, String stationType) throws HttpException, IOException;
JSONArray trafficFlowAtTollStationEntranceHour(String startDate, String endDate, String stationType)throws HttpException, IOException;
List<Map<String, Object>> realTimeTrafficFlowHour(String startDate,Long direction) throws HttpException, IOException;
}

62
zc-business/src/main/java/com/zc/business/service/impl/DcEventServiceImpl.java

@ -85,6 +85,9 @@ public class DcEventServiceImpl extends ServiceImpl<DcEventMapper, DcEvent> impl
@Autowired
private DcPublishManageMapper dcPublishManageMapper;
@Autowired
private DcStakeMarkMapper dcStakeMarkMapper;
private final String HAPPEN = "发生";
private final String EVENT = "事件";
private final String SUBEVENT = "0";
@ -584,8 +587,17 @@ public class DcEventServiceImpl extends ServiceImpl<DcEventMapper, DcEvent> impl
//设置事件Id UUID无下划线格式32
String uuid = dcEvent.getId();
int i7 = dcEventMapper.insertDcEvent(dcEvent);
if (i7 > 0) {
//中间库
if (StringUtils.isNotEmpty(dcEvent.getStakeMark()) && StringUtils.isNotEmpty(dcEvent.getDirection())){
DcStakeMark dcStakeMark = dcStakeMarkMapper.selectByDirection(dcEvent.getStakeMark(),dcEvent.getDirection());
if (dcStakeMark != null){
dcEvent.setLongitude(dcStakeMark.getLongitude());
dcEvent.setDimension(dcStakeMark.getLatitude());
}
}
MdEvent mdEvent = new MdEvent(dcEvent);
middleDatabaseService.insertMiddleDatabaseEvent(mdEvent);
@ -734,6 +746,13 @@ public class DcEventServiceImpl extends ServiceImpl<DcEventMapper, DcEvent> impl
List<DcEventProcess> dcEventProcessList = new ArrayList<>();
for (DcEvent dcEvent : dcEventList) {
if (StringUtils.isNotEmpty(dcEvent.getStakeMark()) && StringUtils.isNotEmpty(dcEvent.getDirection())){
DcStakeMark dcStakeMark = dcStakeMarkMapper.selectByDirection(dcEvent.getStakeMark(),dcEvent.getDirection());
if (dcStakeMark != null){
dcEvent.setLongitude(dcStakeMark.getLongitude());
dcEvent.setDimension(dcStakeMark.getLatitude());
}
}
MdEvent mdEvent = new MdEvent(dcEvent);
mdEventList.add(mdEvent);
@ -883,6 +902,13 @@ public class DcEventServiceImpl extends ServiceImpl<DcEventMapper, DcEvent> impl
//中间库
if (StringUtils.isNotEmpty(dcEvent.getStakeMark()) && StringUtils.isNotEmpty(dcEvent.getDirection())){
DcStakeMark dcStakeMark = dcStakeMarkMapper.selectByDirection(dcEvent.getStakeMark(),dcEvent.getDirection());
if (dcStakeMark != null){
dcEvent.setLongitude(dcStakeMark.getLongitude());
dcEvent.setDimension(dcStakeMark.getLatitude());
}
}
MdEvent mdEvent = new MdEvent(dcEvent);
middleDatabaseService.updateMiddleDatabaseEvent(mdEvent);
@ -1200,6 +1226,13 @@ public class DcEventServiceImpl extends ServiceImpl<DcEventMapper, DcEvent> impl
DcEvent dcEvent = dcEventMapper.selectDcEventMainById(id);
//中间库
if (StringUtils.isNotEmpty(dcEvent.getStakeMark()) && StringUtils.isNotEmpty(dcEvent.getDirection())){
DcStakeMark dcStakeMark = dcStakeMarkMapper.selectByDirection(dcEvent.getStakeMark(),dcEvent.getDirection());
if (dcStakeMark != null){
dcEvent.setLongitude(dcStakeMark.getLongitude());
dcEvent.setDimension(dcStakeMark.getLatitude());
}
}
MdEvent mdEvent = new MdEvent(dcEvent);
middleDatabaseService.insertMiddleDatabaseEvent(mdEvent);
@ -1891,4 +1924,33 @@ public class DcEventServiceImpl extends ServiceImpl<DcEventMapper, DcEvent> impl
}
/**
* @Description 获取事件数量
*
* @author liuwenge
* @date 2024/6/6 18:45
* @param type 类型 1:告警 2:待确认 3:处置中
* @return com.ruoyi.common.core.domain.AjaxResult
*/
@Override
public AjaxResult getCountNum(String type){
if (StringUtils.isEmpty(type)){
return AjaxResult.error("类型不能为空");
}
Long num = 0L;
//告警
if (type.equals("1")){
num = dcWarningMapper.selectWarningNum();
} else if (type.equals("2")){
num = dcEventMapper.selectEventNumByStatus("0");
} else if (type.equals("3")){
num = dcEventMapper.selectEventNumByStatus("1");
}
return AjaxResult.success(num);
}
}

13
zc-business/src/main/java/com/zc/business/service/impl/DcFacilityServiceImpl.java

@ -8,6 +8,7 @@ import com.ruoyi.common.utils.PageUtils;
import com.zc.business.domain.DcFacility;
import com.zc.business.mapper.DcFacilityMapper;
import com.zc.business.service.IDcFacilityService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
@ -23,7 +24,8 @@ import java.util.Objects;
@Service
public class DcFacilityServiceImpl extends ServiceImpl<DcFacilityMapper, DcFacility> implements IDcFacilityService {
@Autowired
private DcFacilityMapper dcFacilityMapper;
public LambdaQueryWrapper<DcFacility> facilityQueryWrapper(DcFacility dcFacility) {
LambdaQueryWrapper<DcFacility> queryWrapper = new LambdaQueryWrapper<>();
@ -140,5 +142,14 @@ public class DcFacilityServiceImpl extends ServiceImpl<DcFacilityMapper, DcFacil
return getById(id);
}
@Override
public DcFacility getfacilityCode(String id) {
LambdaQueryWrapper<DcFacility> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(DcFacility::getFacilityCode, id);
return dcFacilityMapper.selectOne(queryWrapper);
}
}

81
zc-business/src/main/java/com/zc/business/service/impl/DcGantryStatisticsDataImpl.java

@ -4,6 +4,7 @@ import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.common.exception.ServiceException;
import com.zc.business.domain.DcGantryMetricsStatisticsData;
import com.zc.business.domain.DcGantryStatisticsData;
import com.zc.business.domain.OdsTollEtctuData;
import com.zc.business.enums.TrafficDataPeriodTypeEnum;
@ -15,12 +16,14 @@ import com.zc.business.statistics.cache.gantry.QuarterlyTrafficGantryStatisticsC
import com.zc.business.statistics.cache.gantry.YearlyTrafficGantryStatisticsCache;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;
import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.util.Date;
import java.util.List;
import java.util.Map;
/**
* 门架数据统计服务实现类
@ -38,6 +41,12 @@ public class DcGantryStatisticsDataImpl extends ServiceImpl<DcGantryStatisticsDa
@Resource
private IOdsTollEtctuDataService odsTollEtctuDataService;
@Resource
private ThreadPoolTaskExecutor threadPoolTaskExecutor;
@Resource
private DcGantryStatisticsDataMapper dcGantryStatisticsDataMapper;
/**
* 初始化方法用于在对象创建后恢复各种周期的交通门架缓存
@ -45,10 +54,15 @@ public class DcGantryStatisticsDataImpl extends ServiceImpl<DcGantryStatisticsDa
*/
@PostConstruct
public void init() {
recoveryDailyCache(); // 从数据库中恢复天的缓存数据(当月天的缓存数据)
recoveryMonthlyCache(); // 恢复每月交通门架缓存
recoveryQuarterlyCache(); // 恢复每季度交通门架缓存
recoveryYearlyCache(); // 恢复每年交通门架缓存
threadPoolTaskExecutor.execute(() -> {
// 获取当月门架数据
List<DcGantryStatisticsData> dcGantryStatisticsDataList = currentMonthData();
recoveryHourlyCache(dcGantryStatisticsDataList); // 恢复小时缓存数据
recoveryDailyCache(dcGantryStatisticsDataList); // 从数据库中恢复天的缓存数据(当月天的缓存数据)
recoveryMonthlyCache(); // 恢复每月交通门架缓存
recoveryQuarterlyCache(); // 恢复每季度交通门架缓存
recoveryYearlyCache(); // 恢复每年交通门架缓存
});
}
@ -68,6 +82,22 @@ public class DcGantryStatisticsDataImpl extends ServiceImpl<DcGantryStatisticsDa
return odsTollEtctuDataService.calculateGantryStatistics(odsTollEnpassDataList);
}
/**
* 获取当月的门架统计数据列表
*
* <p>此方法不接受任何参数返回一个包含当月所有符合条件的DcGantryStatisticsData对象的列表
* 该列表可用于进一步的数据分析和处理
*
* @return List<DcGantryStatisticsData> - 当月的DcGantryStatisticsData数据列表
*/
@Override
public List<DcGantryStatisticsData> currentMonthData() {
// 获取门架这个月的数据
List<OdsTollEtctuData> odsTollEnpassDataList = odsTollEtctuDataService.currentMonthData();
return odsTollEtctuDataService.calculateGantryStatistics(odsTollEnpassDataList);
}
/**
* 进行门架数据统计的函数
* 该方法接收一个DcGantryStatisticsData类型的对象作为输入参数用来包含门架统计所需的各项数据
@ -87,41 +117,44 @@ public class DcGantryStatisticsDataImpl extends ServiceImpl<DcGantryStatisticsDa
throw new ServiceException("时段类型不能为空");
}
if (request.getGantryCode() == null) {
throw new ServiceException("门架标识不能为空");
}
LambdaQueryWrapper<DcGantryStatisticsData> queryWrapper = new LambdaQueryWrapper<>();
if (request.getStatisticalDate() != null) {
queryWrapper.eq(DcGantryStatisticsData::getStatisticalDate, request.getStatisticalDate());
}
// 如果请求中包含唯一标识符,则根据唯一标识符进行过滤
if (request.getId() != null) {
queryWrapper.eq(DcGantryStatisticsData::getId, request.getId());
}
// 如果请求中包含统计日期,则根据统计日期进行过滤
if (request.getStatisticalDate() != null) {
queryWrapper.eq(DcGantryStatisticsData::getStatisticalDate, request.getStatisticalDate());
}
queryWrapper.eq(DcGantryStatisticsData::getPeriodType, request.getPeriodType());
queryWrapper.eq(DcGantryStatisticsData::getGantryCode, request.getGantryCode());
queryWrapper.between(DcGantryStatisticsData::getCreateTime, request.getStartTime(), request.getEndTime());
queryWrapper.between(DcGantryStatisticsData::getStatisticalDate, request.getStartTime(), request.getEndTime());
return list(queryWrapper);
}
/**
* 恢复小时缓存数据的方法
* 该方法首先会获取当前月份的门架入口数据
* 然后分别计算每个门架的统计信息并将这些统计信息添加到每日交通门架指标统计缓存中
*/
private void recoveryHourlyCache(List<DcGantryStatisticsData> dcGantryStatisticsDataList) {
if (dcGantryStatisticsDataList == null || dcGantryStatisticsDataList.isEmpty()) {
return;
}
dcGantryStatisticsDataMapper.insertOrUpdateBatch(dcGantryStatisticsDataList);
}
/**
* 恢复日缓存数据的方法
* 该方法首先会获取当前月份的门架入口数据
* 然后分别计算每个门架的统计信息并将这些统计信息添加到每日交通门架统计缓存中
*/
private void recoveryDailyCache() {
// 获取当月门架数据
List<OdsTollEtctuData> odsTollEnpassDataList = odsTollEtctuDataService.currentMonthData();
private void recoveryDailyCache(List<DcGantryStatisticsData> dcGantryStatisticsDataList) {
// 计算每个门架数据的统计信息,并添加到每日门架统计缓存中
odsTollEtctuDataService.calculateGantryStatistics(odsTollEnpassDataList).forEach(DailyTrafficGantryStatisticsCache::addCacheData);
dcGantryStatisticsDataList.forEach(DailyTrafficGantryStatisticsCache::addCacheData);
}
/**
@ -166,5 +199,11 @@ public class DcGantryStatisticsDataImpl extends ServiceImpl<DcGantryStatisticsDa
dcTrafficSectionDataList.forEach(YearlyTrafficGantryStatisticsCache::addCacheData);
}
/**
* 全路段双向实时车流量
*/
@Override
public List<Map<String, String>> realTimeTrafficFlow(String startDate, String direction, String periodType ) {
return dcGantryStatisticsDataMapper.realTimeTrafficFlow(startDate,direction,periodType);
}
}

18
zc-business/src/main/java/com/zc/business/service/impl/DcTollStationStatisticsDataImpl.java

@ -18,6 +18,7 @@ import com.zc.business.statistics.cache.tollstation.QuarterlyTrafficTollStationS
import com.zc.business.statistics.cache.tollstation.YearlyTrafficTollStationStatisticsCache;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;
import javax.annotation.PostConstruct;
@ -50,16 +51,21 @@ public class DcTollStationStatisticsDataImpl extends ServiceImpl<DcTollStationSt
@Resource
private IOdsTollExpassDataService odsTollExpassDataService;
@Resource
private ThreadPoolTaskExecutor threadPoolTaskExecutor;
/**
* 初始化方法用于在对象创建后恢复各种周期的交通收费站站点缓存
* 该方法标注了@PostConstruct注解确保在依赖注入完成后调用
*/
@PostConstruct
public void init() {
recoveryDailyCache(); // 从数据库中恢复天的缓存数据(当月天的缓存数据)
recoveryMonthlyCache(); // 恢复每月交通收费站站点缓存
recoveryQuarterlyCache(); // 恢复每季度交通收费站站点缓存
recoveryYearlyCache(); // 恢复每年交通收费站站点缓存
threadPoolTaskExecutor.execute(() -> {
recoveryDailyCache(); // 从数据库中恢复天的缓存数据(当月天的缓存数据)
recoveryMonthlyCache(); // 恢复每月交通收费站站点缓存
recoveryQuarterlyCache(); // 恢复每季度交通收费站站点缓存
recoveryYearlyCache(); // 恢复每年交通收费站站点缓存
});
}
@ -107,10 +113,6 @@ public class DcTollStationStatisticsDataImpl extends ServiceImpl<DcTollStationSt
throw new ServiceException("时段类型不能为空");
}
if (request.getTollStationCode() == null) {
throw new ServiceException("收费站站点编号不能为空");
}
return query(request);
}

104
zc-business/src/main/java/com/zc/business/service/impl/DcTrafficPoliceServiceImpl.java

@ -0,0 +1,104 @@
package com.zc.business.service.impl;
import java.util.List;
import com.ruoyi.common.utils.DateUtils;
import com.zc.business.domain.DcTrafficPolice;
import com.zc.business.mapper.DcTrafficPoliceMapper;
import com.zc.business.service.IDcTrafficPoliceService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
/**
* 交管数据Service业务层处理
*
* @author ruoyi
* @date 2024-06-06
*/
@Service
public class DcTrafficPoliceServiceImpl implements IDcTrafficPoliceService
{
@Autowired
private DcTrafficPoliceMapper dcTrafficPoliceMapper;
/**
* 查询交管数据
*
* @param id 交管数据主键
* @return 交管数据
*/
@Override
public DcTrafficPolice selectDcTrafficPoliceById(Long id)
{
return dcTrafficPoliceMapper.selectDcTrafficPoliceById(id);
}
/**
* 查询交管数据列表
*
* @param dcTrafficPolice 交管数据
* @return 交管数据
*/
@Override
public List<DcTrafficPolice> selectDcTrafficPoliceList(DcTrafficPolice dcTrafficPolice)
{
return dcTrafficPoliceMapper.selectDcTrafficPoliceList(dcTrafficPolice);
}
/**
* 新增交管数据
*
* @param dcTrafficPolice 交管数据
* @return 结果
*/
@Override
public int insertDcTrafficPolice(DcTrafficPolice dcTrafficPolice)
{
dcTrafficPolice.setCreateTime(DateUtils.getNowDate());
return dcTrafficPoliceMapper.insertDcTrafficPolice(dcTrafficPolice);
}
/**
* 修改交管数据
*
* @param dcTrafficPolice 交管数据
* @return 结果
*/
@Override
public int updateDcTrafficPolice(DcTrafficPolice dcTrafficPolice)
{
dcTrafficPolice.setUpdateTime(DateUtils.getNowDate());
return dcTrafficPoliceMapper.updateDcTrafficPolice(dcTrafficPolice);
}
/**
* 批量删除交管数据
*
* @param ids 需要删除的交管数据主键
* @return 结果
*/
@Override
public int deleteDcTrafficPoliceByIds(Long[] ids)
{
return dcTrafficPoliceMapper.deleteDcTrafficPoliceByIds(ids);
}
/**
* 删除交管数据信息
*
* @param id 交管数据主键
* @return 结果
*/
@Override
public int deleteDcTrafficPoliceById(Long id)
{
return dcTrafficPoliceMapper.deleteDcTrafficPoliceById(id);
}
@Override
public DcTrafficPolice selectEvent(String make) {
return dcTrafficPoliceMapper.selectEvent(make);
}
}

14
zc-business/src/main/java/com/zc/business/service/impl/DcTrafficSectionStatisticsServiceImpl.java

@ -26,6 +26,7 @@ import com.zc.business.utils.StakeMarkUtils;
import com.zc.common.core.httpclient.exception.HttpException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;
import javax.annotation.PostConstruct;
@ -61,16 +62,21 @@ public class DcTrafficSectionStatisticsServiceImpl
@Resource
private TrafficSectionAnalysis trafficSectionAnalysis;
@Resource
private ThreadPoolTaskExecutor threadPoolTaskExecutor;
/**
* 初始化方法用于在对象创建后恢复各种周期的交通数据缓存
* 该方法标注了@PostConstruct注解确保在依赖注入完成后调用
*/
@PostConstruct
public void init() {
recoveryDailyCache(); // 从es中恢复当月交通数据缓存
recoveryMonthlyCache(); // 恢复每月交通数据缓存
recoveryQuarterlyCache(); // 恢复每季度交通数据缓存
recoveryYearlyCache(); // 恢复每年交通数据缓存
threadPoolTaskExecutor.execute(() -> {
recoveryDailyCache(); // 从es中恢复当月交通数据缓存
recoveryMonthlyCache(); // 恢复每月交通数据缓存
recoveryQuarterlyCache(); // 恢复每季度交通数据缓存
recoveryYearlyCache(); // 恢复每年交通数据缓存
});
}
/**

401
zc-business/src/main/java/com/zc/business/service/impl/DcTrafficStatisticsServiceImpl.java

@ -1,14 +1,19 @@
package com.zc.business.service.impl;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.zc.business.domain.*;
import com.zc.business.enums.ChannelCongestionLevelEnum;
import com.zc.business.enums.StakeMarkRange;
import com.zc.business.enums.TrafficCompositionRateEnum;
import com.zc.business.service.IDcFacilityService;
import com.zc.business.service.IDcRoadSectionService;
import com.zc.business.service.IDcTrafficStatisticsService;
import com.zc.business.statistics.cache.metrics.DailyGantryMetricsStatisticsCache;
import com.zc.business.utils.StakeMarkUtils;
import com.zc.common.core.httpclient.OkHttp;
import com.zc.common.core.httpclient.exception.HttpException;
@ -17,25 +22,30 @@ import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.Response;
import okhttp3.ResponseBody;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.time.LocalTime;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@Service
public class DcTrafficStatisticsServiceImpl implements IDcTrafficStatisticsService {
// 日志记录器
protected final Logger logger = LoggerFactory.getLogger(this.getClass());
// 智慧高速平台token
private JSONObject token = null;
private final String sysid = "sdgs_it_hs_jihe";
private String baseUrl = "http://10.166.139.16:8080";
private final String baseUrl = "http://10.166.139.16:8080";
@Resource
private IDcFacilityService facilityService;
@ -51,19 +61,6 @@ public class DcTrafficStatisticsServiceImpl implements IDcTrafficStatisticsServi
refreshAccessToken();
}
/**
* 根据传入的统计请求数据查询历史累计车流量数据
*
* @param request 包含统计查询条件的DcStatisticsData对象用于指定查询的历史流量数据的细节如时间范围等
* @return 返回一个DcStatisticsData列表
*/
@Override
public List<DcStatisticsData> historyFlow(DcStatisticsData request) {
// TODO
return null;
}
/**
* 定时刷新访问令牌的函数
* 该方法使用Cron表达式定时执行即每5小时执行一次
@ -476,7 +473,7 @@ public class DcTrafficStatisticsServiceImpl implements IDcTrafficStatisticsServi
*/
@Override
public JSONArray laneOccupancy(String startDate, String endDate) throws HttpException, IOException {
OkHttp okHttp = new OkHttp(10);
OkHttp okHttp = new OkHttp();
RequestParams requestParams = new RequestParams();
@ -509,5 +506,371 @@ public class DcTrafficStatisticsServiceImpl implements IDcTrafficStatisticsServi
return new JSONArray();
}
/**
* 获取门架指标数据
*
* @param startTime 开始时间
* @param endTime 结束时间
*/
@Override
public JSONArray gantryMetrics(String startTime, String endTime) throws HttpException, IOException {
OkHttp okHttp = new OkHttp();
RequestParams requestParams = new RequestParams();
requestParams.put("sysid", sysid);
JSONObject parameters = new JSONObject() {
{
put("start_time", startTime);
put("end_time", endTime);
}
};
requestParams.put("parameters", parameters.toJSONString());
Map<String, String> headers = new HashMap<>();
headers.put("Authorization", getAccessToken());
Response response // 请求响应
= okHttp
.headers(headers)
.url(baseUrl + "/api/dc/query/rd_jihe_d_evaluateindicator") // 请求地址
.data(requestParams) // 请求参数
.post(); // 请求方法
ResponseBody body = response.body();
if (body != null) {
return JSON.parseArray(body.string());
}
return new JSONArray();
}
/**
* 断面小时车流量分车型
*/
@Override
public JSONArray sectionHourlyTrafficFlow(String startDate, String endDate) throws HttpException, IOException {
OkHttp okHttp = new OkHttp();
RequestParams requestParams = new RequestParams();
requestParams.put("sysid", sysid);
JSONObject parameters = new JSONObject() {
{
put("start_date", startDate);
put("end_date", endDate);
}
};
requestParams.put("parameters", parameters.toJSONString());
Map<String, String> headers = new HashMap<>();
headers.put("Authorization", getAccessToken());
Response response // 请求响应
= okHttp
.headers(headers)
.url(baseUrl + "/api/dc/query/rd_jihe_d_vehtypeflowbydatesection") // 请求地址
.data(requestParams) // 请求参数
.post(); // 请求方法
ResponseBody body = response.body();
if (body != null) {
return JSON.parseArray(body.string());
}
return new JSONArray();
}
/**
* 各收费站入口分车型小时车流量
*/
@Override
public List<Map<String, String>> trafficFlowAtTollStationEntrance(String startDate, String endDate, String stationType) throws HttpException, IOException {
OkHttp okHttp = new OkHttp();
RequestParams requestParams = new RequestParams();
requestParams.put("sysid", sysid);
JSONObject parameters = new JSONObject() {
{
put("start_date", startDate);
put("end_date", endDate);
put("station_type", stationType);
}
};
requestParams.put("parameters", parameters.toJSONString());
Map<String, String> headers = new HashMap<>();
headers.put("Authorization", getAccessToken());
Response response // 请求响应
= okHttp
.headers(headers)
.url(baseUrl + "/api/dc/query/ts_jihe_d_vehtypeflowbyhourstation") // 请求地址
.data(requestParams) // 请求参数
.post(); // 请求方法
ResponseBody body = response.body();
if (body != null) {
JSONArray jsonArray = JSON.parseArray(body.string());
// 使用HashMap来分组并求和
Map<String, Integer> sumByName = new HashMap<>();
List<Map<String, String>> list = new ArrayList();
for (Object item : jsonArray) { // 这里做了微调,直接遍历jsonArray的Object
JSONObject jsonObject = (JSONObject) item;
// 获取当前时间
LocalTime now = LocalTime.now();
// 获取当前小时数(24小时制)
int currentHour = now.getHour();
if (jsonObject.getInteger("data_hour") == currentHour) {
String name = jsonObject.getString("ts_name"); // 更安全的取值方式
int totalFlow = jsonObject.getInteger("total_flow"); // 专门针对Integer类型
sumByName.put(name, totalFlow);
// sumByName.put(name, sumByName.getOrDefault(name, 0) + totalFlow);
}
}
// 输出结果
// 输出结果
// 正确创建新的映射对象并添加到list中
for (Map.Entry<String, Integer> entry : sumByName.entrySet()) {
Map<String, String> singleResult = new HashMap<>(); // 每次循环都创建一个新的映射
singleResult.put("name", entry.getKey());
singleResult.put("value", entry.getValue().toString());
list.add(singleResult);
//System.out.println(entry.getKey() + " 的 total_flow 总和为: " + entry.getValue());
}
return list;
}
return new ArrayList();
}
@Override
public JSONArray trafficFlowAtTollStationEntranceHour(String startDate, String endDate, String stationType) throws HttpException, IOException {
OkHttp okHttp = new OkHttp();
RequestParams requestParams = new RequestParams();
requestParams.put("sysid", sysid);
JSONObject parameters = new JSONObject() {
{
put("start_date", startDate);
put("end_date", endDate);
put("station_type", stationType);
}
};
requestParams.put("parameters", parameters.toJSONString());
Map<String, String> headers = new HashMap<>();
headers.put("Authorization", getAccessToken());
Response response // 请求响应
= okHttp
.headers(headers)
.url(baseUrl + "/api/dc/query/ts_jihe_d_vehtypeflowbyhourstation") // 请求地址
.data(requestParams) // 请求参数
.post(); // 请求方法
ResponseBody body = response.body();
if (body != null) {
return JSON.parseArray(body.string());
}
return new JSONArray();
}
@Override
public List<Map<String, Object>> realTimeTrafficFlowHour(String startDate,Long direction) throws HttpException, IOException {
OkHttp okHttp = new OkHttp();
RequestParams requestParams = new RequestParams();
requestParams.put("sysid", sysid);
JSONObject parameters = new JSONObject() {
{
put("start_date", startDate);
put("end_date", startDate);
}
};
requestParams.put("parameters", parameters.toJSONString());
Map<String, String> headers = new HashMap<>();
headers.put("Authorization", getAccessToken());
Response response // 请求响应
= okHttp
.headers(headers)
.url(baseUrl + "/api/dc/query/gan_jihe_d_vehtypeflow") // 请求地址
.data(requestParams) // 请求参数
.post(); // 请求方法
ResponseBody body = response.body();
if (body != null) {
JSONArray jsonArray = JSON.parseArray(body.string());
// 获取当前时间
LocalTime now = LocalTime.now();
// 获取当前小时数(24小时制)
int currentHour = now.getHour();
// 初始化计数器和描述映射
Map<Integer, Integer> flowCounts = new HashMap<>();
Map<Integer, String> descriptions = new HashMap<>();
for (int i = 1; i <= 14; i++) {
flowCounts.put(i, 0);
descriptions.put(i, "");
}
for (Object item : jsonArray) {
JSONObject jsonObject = (JSONObject) item;
if (jsonObject.getInteger("data_hour") == currentHour) {
int totalFlow = jsonObject.getInteger("total_flow");
String gantryId = jsonObject.getString("gantry_id");
DcFacility dcFacilityAll = new DcFacility();
dcFacilityAll.setFacilityType(10);
dcFacilityAll.setDirection(String.valueOf(direction));
List<DcFacility> dcFacilityList = facilityService.listFacility(dcFacilityAll);
DcFacility dcFacility2 = facilityService.getfacilityCode(gantryId);
if (dcFacility2 != null) {
String stakeMark = dcFacility2.getStakeMark();
boolean exists = dcFacilityList.stream()
.anyMatch(dcFacility -> dcFacility.getId().equals(dcFacility2.getId()));
if (exists) {
int extractedNumber = Integer.parseInt(extract(stakeMark));
int identification = Arrays.stream(StakeMarkRange.values())
.filter(smRange -> extractedNumber >= smRange.getStakeMark() && extractedNumber <= smRange.getEndMark())
.mapToInt(StakeMarkRange::getIdentification)
.findFirst()
.orElse(0);
String description = getDescriptionByIdentification(identification);
descriptions.put(identification, description);
flowCounts.put(identification, flowCounts.get(identification) + totalFlow);
}
}
}
}
// 构建结果列表
List<Map<String, Object>> mapList = new ArrayList<>();
for (int i = 1; i <= 14; i++) {
Map<String, Object> map = new HashMap<>();
map.put("name", descriptions.get(i));
map.put("totalFlow", flowCounts.get(i));
mapList.add(map);
}
return mapList;
}
return null;
}
/**
*
* @param startDate
* @param direction
* @return
* @throws HttpException
* @throws IOException
*/
public List<Map<String, Object>> realTimeTrafficFlowHour2(String startDate,Long direction) throws HttpException, IOException {
OkHttp okHttp = new OkHttp();
RequestParams requestParams = new RequestParams();
requestParams.put("sysid", sysid);
JSONObject parameters = new JSONObject() {
{
put("start_date", startDate);
put("end_date", startDate);
}
};
requestParams.put("parameters", parameters.toJSONString());
Map<String, String> headers = new HashMap<>();
headers.put("Authorization", getAccessToken());
Response response // 请求响应
= okHttp
.headers(headers)
.url(baseUrl + "/api/dc/query/gan_jihe_d_vehtypeflow") // 请求地址
.data(requestParams) // 请求参数
.post(); // 请求方法
ResponseBody body = response.body();
if (body != null) {
JSONArray jsonArray = JSON.parseArray(body.string());
// 使用HashMap来分组并求和
List<Map<String, Object>> list = new ArrayList();
for (Object item : jsonArray) { // 这里做了微调,直接遍历jsonArray的Object
JSONObject jsonObject = (JSONObject) item;
// 获取当前时间
LocalTime now = LocalTime.now();
// 获取当前小时数(24小时制)
int currentHour = now.getHour();
if (jsonObject.getInteger("data_hour") == 16) {
Map<String,Object> sumByName = new HashMap<>();
String name = jsonObject.getString("gantry_name"); // 更安全的取值方式
int totalFlow = jsonObject.getInteger("total_flow"); // 专门针对Integer类型
String gantryId = jsonObject.getString("gantry_id"); // 专门针对Integer类型
String data_hour = jsonObject.getString("data_hour"); // 专门针对Integer类型
sumByName.put("naame", name);
sumByName.put("gantryId", gantryId);
sumByName.put("totalFlow", totalFlow);
sumByName.put("data_hour", data_hour);
list.add(sumByName);
}
}
// 输出结果
return list;
}
return new ArrayList();
}
private static String extract(String input) {
Pattern pattern = Pattern.compile("K(\\d{3})\\+(\\d{3})");
Matcher matcher = pattern.matcher(input);
if (matcher.find()) {
String part1 = matcher.group(1);
String part2 = matcher.group(2);
// 直接拼接两部分数字,无需格式化,这样得到的字符串自然没有前导零
return part1 + part2;
} else {
return "N/A";
}
}
public static String getDescriptionByIdentification(int identification) {
for (StakeMarkRange range : StakeMarkRange.values()) {
if (range.getIdentification() == identification) {
return range.getDescription();
}
}
return "";
}
}

8
zc-business/src/main/java/com/zc/business/service/impl/DcWarningServiceImpl.java

@ -14,6 +14,7 @@ import com.zc.business.mapper.DcEventMapper;
import com.zc.business.mapper.DcProcessConfigMapper;
import com.zc.business.mapper.DcWarningMapper;
import com.zc.business.service.IDcEventService;
import com.zc.business.service.IDcTrafficPoliceService;
import com.zc.business.service.IDcWarningService;
import com.zc.business.utils.StakeMarkUtils;
import com.zc.common.core.websocket.WebSocketService;
@ -56,6 +57,8 @@ public class DcWarningServiceImpl implements IDcWarningService
@Autowired
private DcEventProcessServiceImpl dcEventProcessService;
@Autowired
private IDcTrafficPoliceService dcTrafficPoliceService;
@Autowired
private DcProcessConfigMapper dcProcessConfigMapper;
@Resource
private RedisCache redisCache;
@ -643,8 +646,11 @@ public class DcWarningServiceImpl implements IDcWarningService
if (!sortedHashMaps.isEmpty()) {
HashMap<String, Object> map = sortedHashMaps.get(0);
Long id = Long.parseLong(map.get("id").toString());//取出最近的机构id
//todo 交警
List<HashMap<String, Object>> trafficPolice = dcWarningMapper.selectTrafficPolice(id);//交警人员信息
mapAll.put("trafficPolice",trafficPolice);
DcTrafficPolice dcTrafficPolice = dcTrafficPoliceService.selectEvent(dcWarning.getStakeMark());
mapAll.put("trafficPolice",dcTrafficPolice);
}
if (dcDispatch==null){
mapAll.put("existence",0);

275
zc-business/src/main/java/com/zc/business/service/impl/IDcGantryMetricsStatisticsDataServiceImpl.java

@ -0,0 +1,275 @@
package com.zc.business.service.impl;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.common.exception.ServiceException;
import com.zc.business.domain.DcGantryMetricsStatisticsData;
import com.zc.business.domain.DcGantryStatisticsData;
import com.zc.business.enums.ChannelCongestionLevelEnum;
import com.zc.business.enums.TrafficCompositionRateEnum;
import com.zc.business.enums.TrafficDataPeriodTypeEnum;
import com.zc.business.mapper.DcGantryMetricsStatisticsDataMapper;
import com.zc.business.service.IDcGantryMetricsStatisticsDataService;
import com.zc.business.service.IDcTrafficStatisticsService;
import com.zc.business.statistics.cache.metrics.DailyGantryMetricsStatisticsCache;
import com.zc.business.statistics.cache.metrics.MonthlyGantryMetricsStatisticsCache;
import com.zc.business.statistics.cache.metrics.QuarterlyGantryMetricsStatisticsCache;
import com.zc.business.statistics.cache.metrics.YearlyGantryMetricsStatisticsCache;
import com.zc.common.core.httpclient.exception.HttpException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;
import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
/**
* 门架指标统计服务实现类负责处理实时设备消息缓存数据定时任务以及数据保存等功能
*
* @author xiepufeng
*/
@Service
public class IDcGantryMetricsStatisticsDataServiceImpl
extends ServiceImpl<DcGantryMetricsStatisticsDataMapper, DcGantryMetricsStatisticsData>
implements IDcGantryMetricsStatisticsDataService {
// 日志记录器
protected final Logger logger = LoggerFactory.getLogger(this.getClass());
@Resource
private IDcTrafficStatisticsService dcTrafficStatisticsService;
@Resource
private ThreadPoolTaskExecutor threadPoolTaskExecutor;
@Resource
private DcGantryMetricsStatisticsDataMapper gantryMetricsStatisticsDataMapper;
/**
* 初始化方法用于在对象创建后恢复各种周期的交通数据缓存
* 该方法标注了@PostConstruct注解确保在依赖注入完成后调用
*/
@PostConstruct
public void init() {
threadPoolTaskExecutor.execute(() -> {
// 获取当前月份的门架指标数据列表
List<DcGantryMetricsStatisticsData> gantryMetricsStatisticsDataList = currentMonthData();
recoveryHourlyCache(gantryMetricsStatisticsDataList); // 恢复小时缓存数据
recoveryDailyCache(gantryMetricsStatisticsDataList); // 恢复日缓存数据
recoveryMonthlyCache(); // 恢复每月交通门架缓存
recoveryQuarterlyCache(); // 恢复每季度交通门架缓
recoveryYearlyCache(); // 恢复每年交通门架缓存
});
}
/**
* 获取过去一小时的DcGantryMetricsStatisticsData数据列表
*
* <p>此方法不接受任何参数返回一个包含过去一小时所有符合条件的DcGantryMetricsStatisticsData对象的列表
* 该列表可用于进一步的数据分析和处理
*
* @return List<DcGantryMetricsStatisticsData> - 过去一小时的DcGantryMetricsStatisticsData数据列表
*/
@Override
public List<DcGantryMetricsStatisticsData> lastHourData() {
// 计算一小时前的时间点
DateTime lastHour = DateUtil.offsetHour(new Date(), -1);
String startTime = DateUtil.beginOfHour(lastHour).toString();
String endTime = DateUtil.endOfHour(lastHour).toString();
// 获取当月门架数指标据
JSONArray jsonArray = null;
try {
jsonArray = dcTrafficStatisticsService.gantryMetrics(startTime, endTime);
// 计算每个门架数指标据的统计信息,并添加到每日门架指标统计缓存中
return calculateGantryMetricsStatistics(jsonArray);
} catch (HttpException | IOException e) {
logger.error("获取过去一小时的门架指标数据失败", e);
return new ArrayList<>();
}
}
/**
* 获取当月的门架指标数据列表
*
* <p>此方法不接受任何参数返回一个包含当月所有符合条件的DcGantryMetricsStatisticsData对象的列表
* 该列表可用于进一步的数据分析和处理
*
* @return List<DcGantryMetricsStatisticsData> - 当月的DcGantryMetricsStatisticsData数据列表
*/
@Override
public List<DcGantryMetricsStatisticsData> currentMonthData() {
String startTime = DateUtil.beginOfMonth(new Date()).toString();
String endTime = DateUtil.now();
// 获取当月门架数指标据
JSONArray jsonArray = null;
try {
jsonArray = dcTrafficStatisticsService.gantryMetrics(startTime, endTime);
// 计算每个门架数指标据的统计信息,并添加到每日门架指标统计缓存中
return calculateGantryMetricsStatistics(jsonArray);
} catch (HttpException | IOException e) {
logger.error("获取当月门架指标数据失败", e);
return new ArrayList<>();
}
}
/**
* 根据请求条件获取门架指标统计数据
*
* @param request 请求条件
* @return 门架指标统计数据列表
*/
@Override
public List<DcGantryMetricsStatisticsData> gantryMetricsData(DcGantryMetricsStatisticsData request) {
if (request.getStartTime() == null || request.getEndTime() == null) {
throw new ServiceException("开始时间或结束时间不能为空");
}
if (request.getPeriodType() == null) {
throw new ServiceException("时段类型不能为空");
}
LambdaQueryWrapper<DcGantryMetricsStatisticsData> queryWrapper = new LambdaQueryWrapper<>();
if (request.getStatisticalDate() != null) {
queryWrapper.eq(DcGantryMetricsStatisticsData::getStatisticalDate, request.getStatisticalDate());
}
// 如果请求中包含唯一标识符,则根据唯一标识符进行过滤
if (request.getId() != null) {
queryWrapper.eq(DcGantryMetricsStatisticsData::getId, request.getId());
}
queryWrapper.eq(DcGantryMetricsStatisticsData::getPeriodType, request.getPeriodType());
queryWrapper.eq(DcGantryMetricsStatisticsData::getGantryCode, request.getGantryCode());
queryWrapper.between(DcGantryMetricsStatisticsData::getStatisticalDate, request.getStartTime(), request.getEndTime());
return list(queryWrapper);
}
/**
* 恢复小时缓存数据的方法
* 该方法首先会获取当前月份的门架入口数据
* 然后分别计算每个门架的统计信息并将这些统计信息添加到每日交通门架指标统计缓存中
*/
private void recoveryHourlyCache(List<DcGantryMetricsStatisticsData> gantryMetricsStatisticsDataList) {
if (gantryMetricsStatisticsDataList == null || gantryMetricsStatisticsDataList.isEmpty()) {
return;
}
gantryMetricsStatisticsDataMapper.insertOrUpdateBatch(gantryMetricsStatisticsDataList);
}
/**
* 恢复日缓存数据的方法
* 该方法首先会获取当前月份的门架入口数据
* 然后分别计算每个门架的统计信息并将这些统计信息添加到每日交通门架指标统计缓存中
*/
private void recoveryDailyCache(List<DcGantryMetricsStatisticsData> gantryMetricsStatisticsDataList) {
// 计算每个门架数指标据的统计信息,并添加到每日门架指标统计缓存中
gantryMetricsStatisticsDataList.forEach(DailyGantryMetricsStatisticsCache::addCacheData);
}
/**
* 恢复每月交通门架缓存的方法
* 通过查询当前月份至今的每日交通数据并将其添加到每月门架指标统计缓存中
*/
private void recoveryMonthlyCache() {
// 构建查询条件,查询当前月份至今的每日交通数据
LambdaQueryWrapper<DcGantryMetricsStatisticsData> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(DcGantryMetricsStatisticsData::getPeriodType, TrafficDataPeriodTypeEnum.DAY);
queryWrapper.between(DcGantryMetricsStatisticsData::getStatisticalDate, DateUtil.beginOfMonth(new Date()), new Date());
List<DcGantryMetricsStatisticsData> dcGantryMetricsStatisticsDataList = this.list(queryWrapper);
// 遍历查询结果,将每日数据添加到每月门架指标统计缓存中
dcGantryMetricsStatisticsDataList.forEach(MonthlyGantryMetricsStatisticsCache::addCacheData);
}
/**
* 恢复每季度交通门架缓存的方法
* 通过查询当前季度至今的每月交通数据并将其添加到每季度门架指标统计缓存中
*/
private void recoveryQuarterlyCache() {
// 构建查询条件,查询当前季度至今的每月交通数据
LambdaQueryWrapper<DcGantryMetricsStatisticsData> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(DcGantryMetricsStatisticsData::getPeriodType, TrafficDataPeriodTypeEnum.MONTH);
queryWrapper.between(DcGantryMetricsStatisticsData::getStatisticalDate, DateUtil.beginOfQuarter(new Date()), new Date());
List<DcGantryMetricsStatisticsData> dcGantryMetricsStatisticsDataList = this.list(queryWrapper);
// 遍历查询结果,将每月数据添加到每季度门架指标统计缓存
dcGantryMetricsStatisticsDataList.forEach(QuarterlyGantryMetricsStatisticsCache::addCacheData);
}
/**
* 恢复每年交通门架缓存的方法
* 通过查询当前年份至今的每季度交通数据并将其添加到每年门架指标统计缓存中
*/
private void recoveryYearlyCache() {
// 构建查询条件,查询当前年份至今的每季度交通数据
LambdaQueryWrapper<DcGantryMetricsStatisticsData> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(DcGantryMetricsStatisticsData::getPeriodType, TrafficDataPeriodTypeEnum.QUARTER);
queryWrapper.between(DcGantryMetricsStatisticsData::getStatisticalDate, DateUtil.beginOfYear(new Date()), new Date());
List<DcGantryMetricsStatisticsData> dcGantryMetricsStatisticsDataList = this.list(queryWrapper);
// 遍历查询结果,将每季度数据添加到每年门架指标统计缓存
dcGantryMetricsStatisticsDataList.forEach(YearlyGantryMetricsStatisticsCache::addCacheData);
}
/**
* 计算门架指标数据
*
* @param jsonArray 门架指标数据
* @return 门架指标数据列表
*/
private List<DcGantryMetricsStatisticsData> calculateGantryMetricsStatistics(JSONArray jsonArray) {
if (jsonArray == null || jsonArray.isEmpty()) {
return new ArrayList<>();
}
List<DcGantryMetricsStatisticsData> dcGantryMetricsStatisticsDataList = new ArrayList<>();
jsonArray.forEach(item -> {
DcGantryMetricsStatisticsData dcGantryMetricsStatisticsData = new DcGantryMetricsStatisticsData();
JSONObject jsonObject = (JSONObject) item;
// 门架编号
dcGantryMetricsStatisticsData.setGantryCode(jsonObject.getString("gantry_id"));
// 拥堵等级
dcGantryMetricsStatisticsData.setCrowdingRate(ChannelCongestionLevelEnum.fromDescription(jsonObject.getString("crowding_rate")).getLevel());
// 交通组成特征指数(大车占比)
dcGantryMetricsStatisticsData.setTrafficCompositionRate(TrafficCompositionRateEnum.fromDescription(jsonObject.getString("traffic_composition_rate")).getCode());
// 饱和度
dcGantryMetricsStatisticsData.setSaturationRate(jsonObject.getDouble("saturation_rate"));
// 时间
Date dataHour = DateUtil.date(jsonObject.getLong("data_hour"));
// 上报时间
dcGantryMetricsStatisticsData.setReportTime(dataHour);
// 统计时间
dcGantryMetricsStatisticsData.setStatisticalDate(DateUtil.beginOfHour(dataHour));
// 时间颗粒度(小时)
dcGantryMetricsStatisticsData.setPeriodType(TrafficDataPeriodTypeEnum.HOUR);
// 生成唯一ID
dcGantryMetricsStatisticsData.generateUniqueId();
dcGantryMetricsStatisticsDataList.add(dcGantryMetricsStatisticsData);
});
return dcGantryMetricsStatisticsDataList;
}
}

5
zc-business/src/main/java/com/zc/business/service/impl/OdsTollEtctuDataImpl.java

@ -201,7 +201,7 @@ public class OdsTollEtctuDataImpl extends ServiceImpl<OdsTollEtctuDataMapper, Od
// 上报时间
dcGantryStatisticsData.setReportTime(date);
// 统计粒度
dcGantryStatisticsData.setPeriodType(TrafficDataPeriodTypeEnum.DAY);
dcGantryStatisticsData.setPeriodType(TrafficDataPeriodTypeEnum.HOUR);
// 车流量
dcGantryStatisticsData.setTrafficVolume(trafficVolume);
@ -238,6 +238,9 @@ public class OdsTollEtctuDataImpl extends ServiceImpl<OdsTollEtctuDataMapper, Od
// 6型专项作业车车流量
dcGantryStatisticsData.setType6SpecialVehicleFlow(type6SpecialVehicleFlow);
// 生成唯一标识
dcGantryStatisticsData.generateUniqueId();
return dcGantryStatisticsData;
}

2
zc-business/src/main/java/com/zc/business/service/impl/OdsTollExpassDataServiceImpl.java

@ -206,7 +206,7 @@ public class OdsTollExpassDataServiceImpl extends ServiceImpl<OdsTollExpassDataM
// 统计粒度
dcTollStationStatisticsData.setPeriodType(TrafficDataPeriodTypeEnum.DAY);
// 出入类型
dcTollStationStatisticsData.setAccessType(DcTollStationStatisticsData.ENTRANCE);
dcTollStationStatisticsData.setAccessType(DcTollStationStatisticsData.EXIT);
// 车流量
dcTollStationStatisticsData.setTrafficVolume(trafficVolume);

1
zc-business/src/main/java/com/zc/business/statistics/cache/gantry/DailyTrafficGantryStatisticsCache.java

@ -3,7 +3,6 @@ package com.zc.business.statistics.cache.gantry;
import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import com.zc.business.domain.DcGantryStatisticsData;
import com.zc.business.domain.DcTollStationStatisticsData;
import com.zc.business.enums.TrafficDataPeriodTypeEnum;
import com.zc.business.statistics.cache.AbstractTrafficStatisticsCache;
import lombok.Getter;

147
zc-business/src/main/java/com/zc/business/statistics/cache/metrics/DailyGantryMetricsStatisticsCache.java

@ -0,0 +1,147 @@
package com.zc.business.statistics.cache.metrics;
import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import com.zc.business.domain.DcGantryMetricsStatisticsData;
import com.zc.business.enums.TrafficDataPeriodTypeEnum;
import com.zc.business.statistics.cache.AbstractTrafficStatisticsCache;
import lombok.Getter;
import lombok.Setter;
import java.util.Date;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;
/**
*
* 以天为单位的门架指标缓存数据类用于存储和管理门架统计数据同时提供了数据缓存的有效性管理和清理功能
* @author xiepufeng
*/
@Getter
@Setter
public class DailyGantryMetricsStatisticsCache extends AbstractTrafficStatisticsCache<DcGantryMetricsStatisticsData> {
// 静态缓存容器,使用ConcurrentHashMap保证线程安全
@Getter
private static final Map<String, DailyGantryMetricsStatisticsCache> cache = new ConcurrentHashMap<>();
// 最大缓存时间(单位:秒)
private static final long MAX_CACHE_TIME = 26 * 60 * 60; // 缓存数据最长保留25小时
// 最大容量限制,防止内存溢出
private static final int MAX_CAPACITY = 24 + 1 + 1000; // 缓存的最大条目数
// 私有构造函数,确保只能通过静态方法获取实例
private DailyGantryMetricsStatisticsCache() {
}
/**
* 添加门架数据到缓存中
*
* @param dcGantryMetricsStatisticsData 待添加的门架数据
*/
public static void addCacheData(DcGantryMetricsStatisticsData dcGantryMetricsStatisticsData) {
// 获取或新建对应的缓存实例
DailyGantryMetricsStatisticsCache instance = getInstance(dcGantryMetricsStatisticsData);
// 检查缓存容量是否达到上限
if (instance.getData().size() >= MAX_CAPACITY) {
instance.getLogger().error("门架指标缓存数据出现异常,最大缓存量达到设定上线 {}, 当前门架是 {}", MAX_CAPACITY, dcGantryMetricsStatisticsData.getGantryCode());
return;
}
// 更新最后添加时间
instance.setLastAddedTime(DateUtil.date());
// 更新状态
instance.setStored(false);
String formattedDate = formatDate(dcGantryMetricsStatisticsData.getStatisticalDate());
String key = generateCacheKey(dcGantryMetricsStatisticsData);
// 设置key和thatDay属性(仅在首次添加时)
if (instance.getCacheKey() == null) {
instance.setCacheKey(key);
instance.setStatisticalDateStr(formattedDate);
}
// 更新上报时间
dcGantryMetricsStatisticsData.setReportTime(dcGantryMetricsStatisticsData.getStatisticalDate());
// 更新数据周期类型
dcGantryMetricsStatisticsData.setPeriodType(TrafficDataPeriodTypeEnum.DAY);
// 更新统计日期
dcGantryMetricsStatisticsData.setStatisticalDate(dcGantryMetricsStatisticsData.getStatisticalDate(), TrafficDataPeriodTypeEnum.DAY);
// 移除旧数据
instance.getData().remove(dcGantryMetricsStatisticsData);
// 添加数据
instance.getData().add(dcGantryMetricsStatisticsData);
}
/**
* 获取或创建对应设备与日期的DailyTrafficGantryStatisticsCache实例
*
* @param dcGantryMetricsStatisticsData 门架数据统计定义
* @return 对应的门架指标缓存数据实例
*/
private static DailyGantryMetricsStatisticsCache getInstance(DcGantryMetricsStatisticsData dcGantryMetricsStatisticsData) {
// 使用toKey方法生成唯一键,并根据此键计算并返回缓存实例
return cache.computeIfAbsent(generateCacheKey(dcGantryMetricsStatisticsData), k -> new DailyGantryMetricsStatisticsCache());
}
/**
* 生成缓存键
* <p>此方法通过组合门架编号统计日期来生成一个唯一的缓存键</p>
*
* @param dcGantryMetricsStatisticsData 门架统计数据对象包含门架编号统计日期
* @return 缓存键格式为"门架编号|格式化后的统计日期"
*/
public static String generateCacheKey(DcGantryMetricsStatisticsData dcGantryMetricsStatisticsData) {
// 获取门架标识
String gantryCode = dcGantryMetricsStatisticsData.getGantryCode();
// 格式化统计日期
String formattedDate = formatDate(dcGantryMetricsStatisticsData.getStatisticalDate());
// 组合门架编号、格式化后的统计日期作为缓存键
return gantryCode + "|" + formattedDate;
}
/**
* 清除所有过期的门架指标缓存数据项
*/
public static void clearExpiredData() {
// 使用stream API找出所有过期的数据缓存项键
Set<String> keysToRemove = cache.keySet().stream()
.filter(DailyGantryMetricsStatisticsCache::isCacheItemExpire)
.collect(Collectors.toSet());
// 安全地从缓存中删除这些过期项
keysToRemove.forEach(cache::remove);
}
/**
* 检查给定缓存键所对应的缓存项是否已经过期
*
* @param key 缓存key
* @return 如果已过期则返回true否则返回false
*/
private static boolean isCacheItemExpire(String key) {
Date lastAddedTime = cache.get(key).getLastAddedTime();
Date currentTime = DateUtil.date();
long betweenSecond = DateUtil.between(lastAddedTime, currentTime, DateUnit.SECOND);
return betweenSecond > MAX_CACHE_TIME;
}
/**
* Date 类型的日期格式化为指定格式的字符串
*
* @param date 需要格式化的 Date 对象
* @return 格式化后的日期字符串
*/
private static String formatDate(Date date) {
// 使用 DateUtil 工具类将 date 格式化为指定格式的字符串
return DateUtil.formatDate(date);
}
}

152
zc-business/src/main/java/com/zc/business/statistics/cache/metrics/MonthlyGantryMetricsStatisticsCache.java

@ -0,0 +1,152 @@
package com.zc.business.statistics.cache.metrics;
import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import com.zc.business.domain.DcGantryMetricsStatisticsData;
import com.zc.business.enums.TrafficDataPeriodTypeEnum;
import com.zc.business.statistics.cache.AbstractTrafficStatisticsCache;
import lombok.Getter;
import lombok.Setter;
import java.util.Date;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;
/**
*
* 以月为单位的门架指标数据缓存类用于存储和管理门架统计数据同时提供了数据缓存的有效性管理和清理功能
* @author xiepufeng
*/
@Getter
@Setter
public class MonthlyGantryMetricsStatisticsCache extends AbstractTrafficStatisticsCache<DcGantryMetricsStatisticsData> {
// 静态缓存容器,使用ConcurrentHashMap保证线程安全
@Getter
private static final Map<String, MonthlyGantryMetricsStatisticsCache> cache = new ConcurrentHashMap<>();
// 最大缓存时间(单位:秒)
private static final long MAX_CACHE_TIME = (60 * 60) * (31 * 24 + 2);
// 最大容量限制,防止内存溢出
private static final int MAX_CAPACITY = 31 + 1000; // 缓存的最大条目数
// 私有构造函数,确保只能通过静态方法获取实例
private MonthlyGantryMetricsStatisticsCache() {
}
/**
* 添加门架指标数据到缓存中
*
* @param dcGantryMetricsStatisticsData 待添加的门架指标数据
*/
public static void addCacheData(DcGantryMetricsStatisticsData dcGantryMetricsStatisticsData) {
// 获取或新建对应的缓存实例
MonthlyGantryMetricsStatisticsCache instance = getInstance(dcGantryMetricsStatisticsData);
// 检查缓存容量是否达到上限
if (instance.getData().size() >= MAX_CAPACITY) {
instance.getLogger().error("门架指标数据缓存出现异常,最大缓存量达到设定上线 {}, 当前门架是 {}", MAX_CAPACITY, dcGantryMetricsStatisticsData.getGantryCode());
return;
}
// 更新最后添加时间
instance.setLastAddedTime(DateUtil.date());
// 更新状态
instance.setStored(false);
String formattedDate = formatDate(dcGantryMetricsStatisticsData.getStatisticalDate());
String key = generateCacheKey(dcGantryMetricsStatisticsData);
// 设置key和thatDay属性(仅在首次添加时)
if (instance.getCacheKey() == null) {
instance.setCacheKey(key);
instance.setStatisticalDateStr(formattedDate);
}
// 更新上报时间
dcGantryMetricsStatisticsData.setReportTime(dcGantryMetricsStatisticsData.getStatisticalDate());
// 更新数据周期类型
dcGantryMetricsStatisticsData.setPeriodType(TrafficDataPeriodTypeEnum.MONTH);
// 更新统计日期
dcGantryMetricsStatisticsData.setStatisticalDate(dcGantryMetricsStatisticsData.getStatisticalDate(), TrafficDataPeriodTypeEnum.MONTH);
// 移除旧数据
instance.getData().remove(dcGantryMetricsStatisticsData);
// 添加数据
instance.getData().add(dcGantryMetricsStatisticsData);
}
/**
* 获取月门架信息缓存的实例
* <p>
* 根据传入的门架在一定周期内的统计数据计算并返回对应的缓存实例
* 如果缓存中已存在该实例则直接返回否则创建新的缓存实例并加入缓存
* </p>
*
* @param dcGantryMetricsStatisticsData 门架统计数据用于生成缓存键
* @return 缓存中的或新创建的月门架统计信息缓存实例
*/
private static MonthlyGantryMetricsStatisticsCache getInstance(DcGantryMetricsStatisticsData dcGantryMetricsStatisticsData) {
// 使用toKey方法生成唯一键,并根据此键计算并返回缓存实例
return cache.computeIfAbsent(generateCacheKey(dcGantryMetricsStatisticsData), k -> new MonthlyGantryMetricsStatisticsCache());
}
/**
* 生成缓存键
* <p>此方法通过组合门架编号统计日期和访问类型来生成一个唯一的缓存键</p>
*
* @param dcGantryMetricsStatisticsData 门架统计数据对象包含门架编号统计日期
* @return 缓存键格式为"门架编号|格式化后的统计日期"
*/
public static String generateCacheKey(DcGantryMetricsStatisticsData dcGantryMetricsStatisticsData) {
// 获取门架标识
String gantryCode = dcGantryMetricsStatisticsData.getGantryCode();
// 格式化统计日期
String formattedDate = formatDate(dcGantryMetricsStatisticsData.getStatisticalDate());
// 组合门架编号、格式化后的统计日期和访问类型作为缓存键
return gantryCode + "|" + formattedDate;
}
/**
* 清除所有过期的交通断面数据缓存项
*/
public static void clearExpiredData() {
// 使用stream API找出所有过期的数据缓存项键
Set<String> keysToRemove = cache.keySet().stream()
.filter(MonthlyGantryMetricsStatisticsCache::isCacheItemExpire)
.collect(Collectors.toSet());
// 安全地从缓存中删除这些过期项
keysToRemove.forEach(cache::remove);
}
/**
* 检查给定缓存键所对应的缓存项是否已经过期
*
* @param key 缓存key
* @return 如果已过期则返回true否则返回false
*/
private static boolean isCacheItemExpire(String key) {
Date lastAddedTime = cache.get(key).getLastAddedTime();
Date currentTime = DateUtil.date();
long betweenSecond = DateUtil.between(lastAddedTime, currentTime, DateUnit.SECOND);
return betweenSecond > MAX_CACHE_TIME;
}
/**
* Date 类型的日期格式化为 "yyyy-MM-01" 格式的字符串
* @param date 需要格式化的日期对象
* @return 格式化后的日期字符串
*/
private static String formatDate(Date date) {
// 使用 DateUtil 工具类将 date 格式化为指定格式的字符串
return DateUtil.format(date, "yyyy-MM-01");
}
}

154
zc-business/src/main/java/com/zc/business/statistics/cache/metrics/QuarterlyGantryMetricsStatisticsCache.java

@ -0,0 +1,154 @@
package com.zc.business.statistics.cache.metrics;
import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import com.zc.business.domain.DcGantryMetricsStatisticsData;
import com.zc.business.enums.TrafficDataPeriodTypeEnum;
import com.zc.business.statistics.cache.AbstractTrafficStatisticsCache;
import lombok.Getter;
import lombok.Setter;
import java.util.Date;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;
/**
* 以季度为单位的门架数据缓存类用于存储和管理门架统计数据同时提供了数据缓存的有效性管理和清理功能
* @author xiepufeng
*/
@Getter
@Setter
public class QuarterlyGantryMetricsStatisticsCache extends AbstractTrafficStatisticsCache<DcGantryMetricsStatisticsData> {
// 静态缓存容器,使用ConcurrentHashMap保证线程安全
@Getter
private static final Map<String, QuarterlyGantryMetricsStatisticsCache> cache = new ConcurrentHashMap<>();
// 最大缓存时间(单位:秒)
private static final long MAX_CACHE_TIME = (60 * 60) * (3 * 31 * 24 + 2);
// 最大容量限制,防止内存溢出
private static final int MAX_CAPACITY = 3 + 1000; // 缓存的最大条目数
// 私有构造函数,确保只能通过静态方法获取实例
private QuarterlyGantryMetricsStatisticsCache() {
}
/**
* 添加门架数据到缓存中
*
* @param dcGantryMetricsStatisticsData 待添加的门架数据
*/
public static void addCacheData(DcGantryMetricsStatisticsData dcGantryMetricsStatisticsData) {
// 获取或新建对应的缓存实例
QuarterlyGantryMetricsStatisticsCache instance = getInstance(dcGantryMetricsStatisticsData);
// 检查缓存容量是否达到上限
if (instance.getData().size() >= MAX_CAPACITY) {
instance.getLogger().error("门架数据缓存出现异常,最大缓存量达到设定上线 {}, 当前门架是 {}", MAX_CAPACITY, dcGantryMetricsStatisticsData.getGantryCode());
return;
}
// 更新最后添加时间
instance.setLastAddedTime(DateUtil.date());
// 更新状态
instance.setStored(false);
String formattedDate = formatDate(dcGantryMetricsStatisticsData.getStatisticalDate());
String key = generateCacheKey(dcGantryMetricsStatisticsData);
// 设置key和thatDay属性(仅在首次添加时)
if (instance.getCacheKey() == null) {
instance.setCacheKey(key);
instance.setStatisticalDateStr(formattedDate);
}
// 更新上报时间
dcGantryMetricsStatisticsData.setReportTime(dcGantryMetricsStatisticsData.getStatisticalDate());
// 更新数据周期类型
dcGantryMetricsStatisticsData.setPeriodType(TrafficDataPeriodTypeEnum.QUARTER);
// 更新统计日期
dcGantryMetricsStatisticsData.setStatisticalDate(dcGantryMetricsStatisticsData.getStatisticalDate(), TrafficDataPeriodTypeEnum.QUARTER);
// 移除旧数据
instance.getData().remove(dcGantryMetricsStatisticsData);
// 添加数据
instance.getData().add(dcGantryMetricsStatisticsData);
}
/**
* 获取季度门架统计信息缓存的实例
* <p>
* 根据传入的门架在一定周期季度内的统计数据计算并返回对应的缓存实例
* 如果缓存中已存在该实例则直接返回否则创建新的缓存实例并加入缓存
* </p>
*
* @param dcGantryMetricsStatisticsData 门架统计数据用于生成缓存键
* @return 缓存中的或新创建的季度门架统计信息缓存实例
*/
private static QuarterlyGantryMetricsStatisticsCache getInstance(DcGantryMetricsStatisticsData dcGantryMetricsStatisticsData) {
// 根据传入数据生成唯一键,并尝试从缓存中获取或创建新的缓存实例
return cache.computeIfAbsent(generateCacheKey(dcGantryMetricsStatisticsData), k -> new QuarterlyGantryMetricsStatisticsCache());
}
/**
* 生成缓存键
* <p>此方法通过组合门架编号统计日期和访问类型来生成一个唯一的缓存键</p>
*
* @param dcGantryMetricsStatisticsData 门架统计数据对象包含门架编号统计日期和访问类型
* @return 缓存键格式为"门架编号|格式化后的统计日期|访问类型"
*/
public static String generateCacheKey(DcGantryMetricsStatisticsData dcGantryMetricsStatisticsData) {
// 获取门架标识
String gantryCode = dcGantryMetricsStatisticsData.getGantryCode();
// 格式化统计日期
String formattedDate = formatDate(dcGantryMetricsStatisticsData.getStatisticalDate());
// 组合门架编号、格式化后的统计日期缓存键
return gantryCode + "|" + formattedDate;
}
/**
* 清除所有过期的交通断面数据缓存项
*/
public static void clearExpiredData() {
// 使用stream API找出所有过期的数据缓存项键
Set<String> keysToRemove = cache.keySet().stream()
.filter(QuarterlyGantryMetricsStatisticsCache::isCacheItemExpire)
.collect(Collectors.toSet());
// 安全地从缓存中删除这些过期项
keysToRemove.forEach(cache::remove);
}
/**
* 检查给定缓存键所对应的缓存项是否已经过期
*
* @param key 缓存key
* @return 如果已过期则返回true否则返回false
*/
private static boolean isCacheItemExpire(String key) {
Date lastAddedTime = cache.get(key).getLastAddedTime();
Date currentTime = DateUtil.date();
long betweenSecond = DateUtil.between(lastAddedTime, currentTime, DateUnit.SECOND);
return betweenSecond > MAX_CACHE_TIME;
}
/**
* Date 类型的日期格式化为 "yyyy-MM-01" 格式字符串
*
* @param date 需要格式化的日期对象
* @return 格式化后的日期字符串格式为 "yyyy-MM-01"
*/
private static String formatDate(Date date) {
// 使用 DateUtil 工具类将 date 格式化为指定格式的字符串
return DateUtil.format(date, "yyyy-MM-01");
}
}

148
zc-business/src/main/java/com/zc/business/statistics/cache/metrics/YearlyGantryMetricsStatisticsCache.java

@ -0,0 +1,148 @@
package com.zc.business.statistics.cache.metrics;
import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import com.zc.business.domain.DcGantryMetricsStatisticsData;
import com.zc.business.enums.TrafficDataPeriodTypeEnum;
import com.zc.business.statistics.cache.AbstractTrafficStatisticsCache;
import lombok.Getter;
import lombok.Setter;
import java.util.Date;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;
/**
* 以年为单位的门架数据缓存类用于存储和管理门架统计数据同时提供了数据缓存的有效性管理和清理功能
* @author xiepufeng
*/
@Getter
@Setter
public class YearlyGantryMetricsStatisticsCache extends AbstractTrafficStatisticsCache<DcGantryMetricsStatisticsData> {
// 静态缓存容器,使用ConcurrentHashMap保证线程安全
@Getter
private static final Map<String, YearlyGantryMetricsStatisticsCache> cache = new ConcurrentHashMap<>();
// 最大缓存时间(单位:秒)
private static final long MAX_CACHE_TIME = (60 * 60) * (366 * 24 + 2);
// 最大容量限制,防止内存溢出
private static final int MAX_CAPACITY = 4 + 1000; // 缓存的最大条目数
// 私有构造函数,确保只能通过静态方法获取实例
private YearlyGantryMetricsStatisticsCache() {
}
/**
* 添加门架数据到缓存中
*
* @param dcGantryMetricsStatisticsData 待添加的门架数据
*/
public static void addCacheData(DcGantryMetricsStatisticsData dcGantryMetricsStatisticsData) {
// 获取或新建对应的缓存实例
YearlyGantryMetricsStatisticsCache instance = getInstance(dcGantryMetricsStatisticsData);
// 检查缓存容量是否达到上限
if (instance.getData().size() >= MAX_CAPACITY) {
instance.getLogger().error("门架数据缓存出现异常,最大缓存量达到设定上线 {}, 当前门架是 {}", MAX_CAPACITY, dcGantryMetricsStatisticsData.getGantryCode());
return;
}
// 更新最后添加时间
instance.setLastAddedTime(DateUtil.date());
// 更新状态
instance.setStored(false);
String formattedDate = formatDate(dcGantryMetricsStatisticsData.getStatisticalDate());
String key = generateCacheKey(dcGantryMetricsStatisticsData);
// 设置key和thatDay属性(仅在首次添加时)
if (instance.getCacheKey() == null) {
instance.setCacheKey(key);
instance.setStatisticalDateStr(formattedDate);
}
// 更新上报时间
dcGantryMetricsStatisticsData.setReportTime(dcGantryMetricsStatisticsData.getStatisticalDate());
// 更新数据周期类型
dcGantryMetricsStatisticsData.setPeriodType(TrafficDataPeriodTypeEnum.YEAR);
// 更新统计日期
dcGantryMetricsStatisticsData.setStatisticalDate(dcGantryMetricsStatisticsData.getStatisticalDate(), TrafficDataPeriodTypeEnum.YEAR);
// 移除旧数据
instance.getData().remove(dcGantryMetricsStatisticsData);
// 添加数据
instance.getData().add(dcGantryMetricsStatisticsData);
}
/**
* 获取或创建对应设备与日期的YearlyTrafficSectionStatisticsCache实例
*
* @param dcGantryMetricsStatisticsData 交通断面数据统计定义
* @return 对应的交通断面数据缓存实例
*/
private static YearlyGantryMetricsStatisticsCache getInstance(DcGantryMetricsStatisticsData dcGantryMetricsStatisticsData) {
// 使用toKey方法生成唯一键,并根据此键计算并返回缓存实例
return cache.computeIfAbsent(generateCacheKey(dcGantryMetricsStatisticsData), k -> new YearlyGantryMetricsStatisticsCache());
}
/**
* 生成缓存键
* <p>此方法通过组合门架编号统计日期来生成一个唯一的缓存键</p>
*
* @param dcGantryMetricsStatisticsData 门架统计数据对象包含门架编号统计日期
* @return 缓存键格式为"门架编号|格式化后的统计日期"
*/
public static String generateCacheKey(DcGantryMetricsStatisticsData dcGantryMetricsStatisticsData) {
// 获取门架站点标识
String gantryCode = dcGantryMetricsStatisticsData.getGantryCode();
// 格式化统计日期
String formattedDate = formatDate(dcGantryMetricsStatisticsData.getStatisticalDate());
// 组合门架编号、格式化后的统计日期作为缓存键
return gantryCode + "|" + formattedDate;
}
/**
* 清除所有过期的交通断面数据缓存项
*/
public static void clearExpiredData() {
// 使用stream API找出所有过期的数据缓存项键
Set<String> keysToRemove = cache.keySet().stream()
.filter(YearlyGantryMetricsStatisticsCache::isCacheItemExpire)
.collect(Collectors.toSet());
// 安全地从缓存中删除这些过期项
keysToRemove.forEach(cache::remove);
}
/**
* 检查给定缓存键所对应的缓存项是否已经过期
*
* @param key 缓存key
* @return 如果已过期则返回true否则返回false
*/
private static boolean isCacheItemExpire(String key) {
Date lastAddedTime = cache.get(key).getLastAddedTime();
Date currentTime = DateUtil.date();
long betweenSecond = DateUtil.between(lastAddedTime, currentTime, DateUnit.SECOND);
return betweenSecond > MAX_CACHE_TIME;
}
/**
* Date 类型的日期格式化为 "yyyy-01-01" 格式的字符串
*
* @param date 需要格式化的日期对象
* @return 格式化后的日期字符串
*/
private static String formatDate(Date date) {
// 使用 DateUtil 工具类将 date 格式化为 "yyyy-01-01" 格式的字符串
return DateUtil.format(date, "yyyy-01-01");
}
}

162
zc-business/src/main/java/com/zc/business/statistics/handler/TrafficGantryMetricsStatistics.java

@ -0,0 +1,162 @@
package com.zc.business.statistics.handler;
import com.zc.business.domain.DcGantryMetricsStatisticsData;
import com.zc.business.enums.TrafficDataPeriodTypeEnum;
import com.zc.business.mapper.DcGantryMetricsStatisticsDataMapper;
import com.zc.business.service.IDcGantryMetricsStatisticsDataService;
import com.zc.business.statistics.cache.AbstractTrafficStatisticsCache;
import com.zc.business.statistics.cache.metrics.DailyGantryMetricsStatisticsCache;
import com.zc.business.statistics.cache.metrics.MonthlyGantryMetricsStatisticsCache;
import com.zc.business.statistics.cache.metrics.QuarterlyGantryMetricsStatisticsCache;
import com.zc.business.statistics.cache.metrics.YearlyGantryMetricsStatisticsCache;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import javax.annotation.Resource;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;
import java.util.stream.Collectors;
/**
* TrafficGantryStatistics类用于处理门架指标的统计数据
* @author xiepufeng
*/
@Component
public class TrafficGantryMetricsStatistics {
// 日志记录器
protected final Logger logger = LoggerFactory.getLogger(this.getClass());
@Resource
private IDcGantryMetricsStatisticsDataService dcGantryMetricsStatisticsDataService;
@Resource
private DcGantryMetricsStatisticsDataMapper dcGantryMetricsStatisticsDataMapper;
/**
* 定义每小时第20分钟执行的任务用于清除过期缓存数据并将缓存中的数据整合后保存至数据库
*/
@Scheduled(cron = "0 20 * * * ?") // 每小时的20分整点执行该任务
public void performHourlyCleanupAndPersist() {
List<DcGantryMetricsStatisticsData> lastHourData = dcGantryMetricsStatisticsDataService.lastHourData();
if (lastHourData == null || lastHourData.isEmpty()) {
return;
}
// 数据库批量插入最近一小时的数据
dcGantryMetricsStatisticsDataMapper.insertOrUpdateBatch(lastHourData);
// 添加日门架指标数据到缓存中
lastHourData.forEach(DailyGantryMetricsStatisticsCache::addCacheData);
// 清除已过期的缓存数据
DailyGantryMetricsStatisticsCache.clearExpiredData();
MonthlyGantryMetricsStatisticsCache.clearExpiredData();
QuarterlyGantryMetricsStatisticsCache.clearExpiredData();
YearlyGantryMetricsStatisticsCache.clearExpiredData();
// 整合缓存数据并保存至数据库
// 将缓存中的数据按日统计后保存至数据库
// 添加月门架指标数据到缓存中
persistAggregatedData(DailyGantryMetricsStatisticsCache.getCache(), TrafficDataPeriodTypeEnum.DAY, MonthlyGantryMetricsStatisticsCache::addCacheData);
// 将缓存中的数据按月统计后保存至数据库
// 添加季度门架指标数据到缓存中
persistAggregatedData(MonthlyGantryMetricsStatisticsCache.getCache(), TrafficDataPeriodTypeEnum.MONTH, QuarterlyGantryMetricsStatisticsCache::addCacheData);
// 将缓存中的数据按季度统计后保存至数据库
// 添加年门架指标数据到缓存中
persistAggregatedData(QuarterlyGantryMetricsStatisticsCache.getCache(), TrafficDataPeriodTypeEnum.QUARTER, YearlyGantryMetricsStatisticsCache::addCacheData);
// 将缓存中的数据按年统计后保存至数据库
persistAggregatedData(YearlyGantryMetricsStatisticsCache.getCache(), TrafficDataPeriodTypeEnum.YEAR, (a) -> {});
}
/**
* 将缓存中的数据统计后保存至数据库
*/
public void persistAggregatedData(
Map<String, ? extends AbstractTrafficStatisticsCache<DcGantryMetricsStatisticsData>> cache,
TrafficDataPeriodTypeEnum periodType,
Consumer<DcGantryMetricsStatisticsData> consumer
) {
for (AbstractTrafficStatisticsCache<DcGantryMetricsStatisticsData> data : cache.values()) {
// 如果数据已经存储过,则跳过此次处理
if (data.isStored()) {
continue;
}
DcGantryMetricsStatisticsData aggregatedData = trafficStatistics(data.getData(), periodType);
if (dcGantryMetricsStatisticsDataMapper.insertOrUpdate(aggregatedData)) {
// 设置数据已存储状态
data.setStored(true);
// 调用回调函数
consumer.accept(aggregatedData);
}
}
}
/**
* 对给定的门架指标统计数据集合进行汇总处理
*
* @param dataCollection 门架指标统计数据的集合不可为null或空
* @param trafficDataPeriodType 统计数据的时段类型例如小时月等
* @return 汇总后的门架指标统计数据对象如果输入数据为空则返回null
*/
public DcGantryMetricsStatisticsData trafficStatistics(Collection<DcGantryMetricsStatisticsData> dataCollection, TrafficDataPeriodTypeEnum trafficDataPeriodType) {
// 判断输入数据是否为空
if (CollectionUtils.isEmpty(dataCollection)) {
return null;
}
// 创建一个汇总统计用的对象
DcGantryMetricsStatisticsData aggregatedData = new DcGantryMetricsStatisticsData();
// 获取拥堵度众数
Integer mostFrequentCrowdingRate = dataCollection.stream()
.collect(Collectors.groupingBy(DcGantryMetricsStatisticsData::getCrowdingRate, Collectors.counting()))
.entrySet().stream()
.max(Map.Entry.comparingByValue())
.map(Map.Entry::getKey)
.orElse(null); // 如果没有数据,则返回null
// 获取交通占比众数
Integer mostFrequentTrafficCompositionRate = dataCollection.stream()
.collect(Collectors.groupingBy(DcGantryMetricsStatisticsData::getTrafficCompositionRate, Collectors.counting()))
.entrySet().stream()
.max(Map.Entry.comparingByValue())
.map(Map.Entry::getKey)
.orElse(null); // 如果没有数据,则返回null
// 获取饱和度平均值
Double saturationRateAverage = dataCollection.stream()
.mapToDouble(DcGantryMetricsStatisticsData::getSaturationRate)
.average()
.orElse(0.00); // 如果没有数据,则返回0.0
aggregatedData.setCrowdingRate(mostFrequentCrowdingRate);
aggregatedData.setTrafficCompositionRate(mostFrequentTrafficCompositionRate);
aggregatedData.setSaturationRate(saturationRateAverage);
// 使用第一个数据项的信息填充汇总统计对象的基本属性
DcGantryMetricsStatisticsData firstDcGantryMetricsStatisticsData = dataCollection.iterator().next();
// 设置门架指标标识
aggregatedData.setGantryCode(firstDcGantryMetricsStatisticsData.getGantryCode());
// 设置统计时间
aggregatedData.setStatisticalDate(firstDcGantryMetricsStatisticsData.getStatisticalDate(), trafficDataPeriodType);
// 上报时间
aggregatedData.setReportTime(firstDcGantryMetricsStatisticsData.getReportTime());
// 时段类型
aggregatedData.setPeriodType(trafficDataPeriodType);
// 生成主键
aggregatedData.generateUniqueId();
return aggregatedData;
}
}

12
zc-business/src/main/java/com/zc/business/statistics/handler/TrafficGantryStatistics.java

@ -17,6 +17,7 @@ import org.springframework.util.CollectionUtils;
import javax.annotation.Resource;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;
@ -43,8 +44,17 @@ public class TrafficGantryStatistics {
@Scheduled(cron = "0 20 * * * ?") // 每小时的20分整点执行该任务
public void performHourlyCleanupAndPersist() {
List<DcGantryStatisticsData> lastHourData = dcGantryStatisticsDataService.lastHourData();
if (lastHourData == null || lastHourData.isEmpty()) {
return;
}
// 数据库批量插入最近一小时的数据
dcGantryStatisticsDataMapper.insertOrUpdateBatch(lastHourData);
// 添加日门架数据到缓存中
dcGantryStatisticsDataService.lastHourData().forEach(DailyTrafficGantryStatisticsCache::addCacheData);
lastHourData.forEach(DailyTrafficGantryStatisticsCache::addCacheData);
// 清除已过期的缓存数据
DailyTrafficGantryStatisticsCache.clearExpiredData();

3
zc-business/src/main/resources/mapper/business/DcEmergencyPlansMapper.xml

@ -116,6 +116,9 @@
<where>
<if test="planName != null and planName != ''"> and plan_name like concat('%', #{planName}, '%')</if>
<if test="eventType != 0 "> and event_type = #{eventType}</if>
<if test="triggerMechanism != null and triggerMechanism != ''">
and trigger_mechanism =#{triggerMechanism}
</if>
</where>
order by t1.id desc
</select>

3
zc-business/src/main/resources/mapper/business/DcEventMapper.xml

@ -850,4 +850,7 @@
</otherwise>
</choose>
</select>
<select id="selectEventNumByStatus" resultType="java.lang.Long">
select count(*) from dc_event where event_state = #{status}
</select>
</mapper>

77
zc-business/src/main/resources/mapper/business/DcGantryMetricsStatisticsDataMapper.xml

@ -0,0 +1,77 @@
<?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.zc.business.mapper.DcGantryMetricsStatisticsDataMapper">
<!-- 插入或更新门架指标数据 -->
<insert id="insertOrUpdate" parameterType="com.zc.business.domain.DcGantryMetricsStatisticsData">
INSERT INTO
dc_gantry_metrics_statistics_data
(
id,
gantry_code,
statistical_date,
period_type,
crowding_rate,
traffic_composition_rate,
saturation_rate,
create_time
)
VALUES
(
#{id},
#{gantryCode},
#{statisticalDate},
#{periodType},
#{crowdingRate},
#{trafficCompositionRate},
#{saturationRate},
NOW())
ON DUPLICATE KEY UPDATE
gantry_code = VALUES(gantry_code),
statistical_date = VALUES(statistical_date),
period_type = VALUES(period_type),
crowding_rate = VALUES(crowding_rate),
traffic_composition_rate = VALUES(traffic_composition_rate),
saturation_rate = VALUES(saturation_rate),
update_time = NOW()
</insert>
<insert id="insertOrUpdateBatch" parameterType="list">
INSERT INTO
dc_gantry_metrics_statistics_data
(
id,
gantry_code,
statistical_date,
period_type,
crowding_rate,
traffic_composition_rate,
saturation_rate,
create_time
)
VALUES
<foreach collection="list" item="item" index="index" separator=",">
(
#{item.id},
#{item.gantryCode},
#{item.statisticalDate},
#{item.periodType},
#{item.crowdingRate},
#{item.trafficCompositionRate},
#{item.saturationRate},
NOW()
)
</foreach>
ON DUPLICATE KEY UPDATE
gantry_code = VALUES(gantry_code),
statistical_date = VALUES(statistical_date),
period_type = VALUES(period_type),
crowding_rate = VALUES(crowding_rate),
traffic_composition_rate = VALUES(traffic_composition_rate),
saturation_rate = VALUES(saturation_rate),
update_time = NOW()
</insert>
</mapper>

127
zc-business/src/main/resources/mapper/business/DcGantryStatisticsDataMapper.xml

@ -3,7 +3,10 @@
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.zc.business.mapper.DcGantryStatisticsDataMapper">
<resultMap type="map" id="countMap">
<result property="volume" column="total_traffic_volume"/>
<result property="name" column="interval_name"/>
</resultMap>
<!-- 插入或更新交通路段数据 -->
<insert id="insertOrUpdate" parameterType="com.zc.business.domain.DcGantryStatisticsData">
INSERT INTO
@ -81,6 +84,84 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
type6_special_vehicle_flow = VALUES(type6_special_vehicle_flow)
</insert>
<insert id="insertOrUpdateBatch" parameterType="list">
INSERT INTO
dc_gantry_statistics_data
(
id,
gantry_code,
statistical_date,
traffic_volume,
period_type,
create_time,
type1_passenger_flow,
type2_passenger_flow,
type3_passenger_flow,
type4_passenger_flow,
type1_truck_flow,
type2_truck_flow,
type3_truck_flow,
type4_truck_flow,
type5_truck_flow,
type6_truck_flow,
type1_special_vehicle_flow,
type2_special_vehicle_flow,
type3_special_vehicle_flow,
type4_special_vehicle_flow,
type5_special_vehicle_flow,
type6_special_vehicle_flow
)
VALUES
<foreach collection="list" item="item" index="index" separator=",">
(
#{item.id},
#{item.gantryCode},
#{item.statisticalDate},
#{item.trafficVolume},
#{item.periodType},
NOW(),
#{item.type1PassengerFlow},
#{item.type2PassengerFlow},
#{item.type3PassengerFlow},
#{item.type4PassengerFlow},
#{item.type1TruckFlow},
#{item.type2TruckFlow},
#{item.type3TruckFlow},
#{item.type4TruckFlow},
#{item.type5TruckFlow},
#{item.type6TruckFlow},
#{item.type1SpecialVehicleFlow},
#{item.type2SpecialVehicleFlow},
#{item.type3SpecialVehicleFlow},
#{item.type4SpecialVehicleFlow},
#{item.type5SpecialVehicleFlow},
#{item.type6SpecialVehicleFlow}
)
</foreach>
ON DUPLICATE KEY UPDATE
gantry_code = VALUES(gantry_code),
statistical_date = VALUES(statistical_date),
traffic_volume = VALUES(traffic_volume),
period_type = VALUES(period_type),
update_time = NOW(),
type1_passenger_flow = VALUES(type1_passenger_flow),
type2_passenger_flow = VALUES(type2_passenger_flow),
type3_passenger_flow = VALUES(type3_passenger_flow),
type4_passenger_flow = VALUES(type4_passenger_flow),
type1_truck_flow = VALUES(type1_truck_flow),
type2_truck_flow = VALUES(type2_truck_flow),
type3_truck_flow = VALUES(type3_truck_flow),
type4_truck_flow = VALUES(type4_truck_flow),
type5_truck_flow = VALUES(type5_truck_flow),
type6_truck_flow = VALUES(type6_truck_flow),
type1_special_vehicle_flow = VALUES(type1_special_vehicle_flow),
type2_special_vehicle_flow = VALUES(type2_special_vehicle_flow),
type3_special_vehicle_flow = VALUES(type3_special_vehicle_flow),
type4_special_vehicle_flow = VALUES(type4_special_vehicle_flow),
type5_special_vehicle_flow = VALUES(type5_special_vehicle_flow),
type6_special_vehicle_flow = VALUES(type6_special_vehicle_flow)
</insert>
<select id="getMaxStatisticalDate" resultType="java.util.Date">
SELECT
MAX(statistical_date)
@ -88,4 +169,48 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
dc_gantry_statistics_data
</select>
<select id="realTimeTrafficFlow" resultMap="countMap" resultType="map" >
SELECT
intervals.interval_name,
intervals.stake_make,
intervals.end_make,
COALESCE(SUM(dgsd.traffic_volume), 0) AS total_traffic_volume
FROM
(
SELECT 'K054+394' AS stake_make, 'K059+289' AS end_make, '殷家林枢纽-大学城立交' AS interval_name UNION ALL
SELECT 'K059+289', 'K072+847', '大学城立交-长清立交' UNION ALL
SELECT 'K072+847', 'K083+835', '长清立交-松竹枢纽' UNION ALL
SELECT 'K083+835', 'K086+499', '松竹枢纽-孝里立交' UNION ALL
SELECT 'K086+499', 'K099+750', '孝里立交-平阴北立交' UNION ALL
SELECT 'K099+750', 'K105+904', '平阴北立交-平阴立交' UNION ALL
SELECT 'K105+904', 'K117+878', '平阴立交-孔村枢纽' UNION ALL
SELECT 'K117+878', 'K126+233', '孔村枢纽-平阴南立交' UNION ALL
SELECT 'K126+233', 'K145+933', '平阴南立交-东平立交' UNION ALL
SELECT 'K145+933', 'K155+652', '东平立交-东平湖枢纽' UNION ALL
SELECT 'K155+652', 'K173+950', '东平湖枢纽-梁山东立交' UNION ALL
SELECT 'K173+950', 'K179+396', '梁山东立交-梁山立交' UNION ALL
SELECT 'K179+396', 'K190+495', '梁山立交-嘉祥西立交' UNION ALL
SELECT 'K190+495', 'K202+979', '嘉祥西立交'
) AS intervals
LEFT JOIN (
SELECT
facility_code,
stake_mark,
facility_name,
direction
FROM
dc_facility
WHERE
direction = #{direction}
) AS ps ON ps.stake_mark BETWEEN CONCAT(intervals.stake_make, '+0') AND CONCAT(intervals.end_make, '+0')
LEFT JOIN dc_gantry_statistics_data dgsd ON ps.facility_code = dgsd.gantry_code
AND dgsd.statistical_date =#{startDate}
AND dgsd.period_type =#{periodType}
GROUP BY
intervals.interval_name,
intervals.stake_make,
intervals.end_make;
</select>
</mapper>

4
zc-business/src/main/resources/mapper/business/DcStakeMarkMapper.xml

@ -38,4 +38,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
</trim>
</foreach>
</insert>
<select id="selectByDirection" resultType="com.zc.business.domain.DcStakeMark">
select stake_mark stakeMark, longitude,latitude,direction,location,section_id sectionId,mileage
from dc_stake_mark where stake_mark = #{stakeMark} and direction = #{direction}
</select>
</mapper>

84
zc-business/src/main/resources/mapper/business/DcTrafficPoliceMapper.xml

@ -0,0 +1,84 @@
<?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.zc.business.mapper.DcTrafficPoliceMapper">
<resultMap type="com.zc.business.domain.DcTrafficPolice" id="DcTrafficPoliceResult">
<result property="id" column="id" />
<result property="name" column="name" />
<result property="phone" column="phone" />
<result property="stakeMake" column="stake_make" />
<result property="endMake" column="end_make" />
<result property="createTime" column="create_time" />
<result property="updateTime" column="update_time" />
</resultMap>
<sql id="selectDcTrafficPoliceVo">
select id, name, phone, stake_make, end_make, create_time, update_time from dc_traffic_police
</sql>
<select id="selectDcTrafficPoliceList" parameterType="DcTrafficPolice" resultMap="DcTrafficPoliceResult">
<include refid="selectDcTrafficPoliceVo"/>
<where>
<if test="name != null and name != ''"> and name like concat('%', #{name}, '%')</if>
<if test="phone != null and phone != ''"> and phone = #{phone}</if>
<if test="stakeMake != null and stakeMake != ''"> and stake_make = #{stakeMake}</if>
<if test="endMake != null and endMake != ''"> and end_make = #{endMake}</if>
</where>
</select>
<select id="selectDcTrafficPoliceById" parameterType="Long" resultMap="DcTrafficPoliceResult">
<include refid="selectDcTrafficPoliceVo"/>
where id = #{id}
</select>
<insert id="insertDcTrafficPolice" parameterType="DcTrafficPolice" useGeneratedKeys="true" keyProperty="id">
insert into dc_traffic_police
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="name != null">name,</if>
<if test="phone != null">phone,</if>
<if test="stakeMake != null">stake_make,</if>
<if test="endMake != null">end_make,</if>
<if test="createTime != null">create_time,</if>
<if test="updateTime != null">update_time,</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="name != null">#{name},</if>
<if test="phone != null">#{phone},</if>
<if test="stakeMake != null">#{stakeMake},</if>
<if test="endMake != null">#{endMake},</if>
<if test="createTime != null">#{createTime},</if>
<if test="updateTime != null">#{updateTime},</if>
</trim>
</insert>
<update id="updateDcTrafficPolice" parameterType="DcTrafficPolice">
update dc_traffic_police
<trim prefix="SET" suffixOverrides=",">
<if test="name != null">name = #{name},</if>
<if test="phone != null">phone = #{phone},</if>
<if test="stakeMake != null">stake_make = #{stakeMake},</if>
<if test="endMake != null">end_make = #{endMake},</if>
<if test="createTime != null">create_time = #{createTime},</if>
<if test="updateTime != null">update_time = #{updateTime},</if>
</trim>
where id = #{id}
</update>
<delete id="deleteDcTrafficPoliceById" parameterType="Long">
delete from dc_traffic_police where id = #{id}
</delete>
<delete id="deleteDcTrafficPoliceByIds" parameterType="String">
delete from dc_traffic_police where id in
<foreach item="id" collection="array" open="(" separator="," close=")">
#{id}
</foreach>
</delete>
<select id="selectEvent" parameterType="String" resultMap="DcTrafficPoliceResult">
<include refid="selectDcTrafficPoliceVo"/>
WHERE #{make} BETWEEN dc_traffic_police.stake_make AND dc_traffic_police.end_make;
</select>
</mapper>

3
zc-business/src/main/resources/mapper/business/DcWarningMapper.xml

@ -433,5 +433,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<select id="selectDispatchId" resultType="java.util.HashMap">
select id dispatchId from dc_dispatch where event_id=#{eventId}
</select>
<select id="selectWarningNum" resultType="java.lang.Long">
select count(*) from dc_warning where warning_state = 1 and warning_source != 6
</select>
</mapper>

10
zc-business/src/main/resources/mapper/business/MiddleDatabaseMapper.xml

@ -39,6 +39,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="fusionId != null">fusionId,</if>
<if test="eventName != null">event_name,</if>
<if test="eventTypeCode != null">event_type_code,</if>
<if test="eventTypeName != null">event_type_name,</if>
<if test="eventDesc != null">event_desc,</if>
<if test="occurTime != null">occur_time,</if>
<if test="endTime != null">end_time,</if>
@ -54,6 +55,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="eventLevel != null">event_level,</if>
<if test="sectionId != null">section_id,</if>
<if test="eventTypeCode2 != null">event_type_code2,</if>
<if test="eventTypeName2 != null">event_type_name2,</if>
<if test="eventCause != null">event_cause,</if>
<if test="accidentWeather != null">accident_weather,</if>
<if test="accidentQueue != null">accident_queue,</if>
@ -79,6 +81,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="fusionId != null">#{fusionId},</if>
<if test="eventName != null">#{eventName},</if>
<if test="eventTypeCode != null">#{eventTypeCode},</if>
<if test="eventTypeName != null">#{eventTypeName},</if>
<if test="eventDesc != null">#{eventDesc},</if>
<if test="occurTime != null">#{occurTime},</if>
<if test="endTime != null">#{endTime},</if>
@ -94,6 +97,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="eventLevel != null">#{eventLevel},</if>
<if test="sectionId != null">#{sectionId},</if>
<if test="eventTypeCode2 != null">#{eventTypeCode2},</if>
<if test="eventTypeName2 != null">#{eventTypeName2},</if>
<if test="eventCause != null">#{eventCause},</if>
<if test="accidentWeather != null">#{accidentWeather},</if>
<if test="accidentQueue != null">#{accidentQueue},</if>
@ -238,6 +242,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="mdEvent.fusionId != null">fusionId,</if>
<if test="mdEvent.eventName != null">event_name,</if>
<if test="mdEvent.eventTypeCode != null">event_type_code,</if>
<if test="mdEvent.eventTypeName != null">event_type_name,</if>
<if test="mdEvent.eventDesc != null">event_desc,</if>
<if test="mdEvent.occurTime != null">occur_time,</if>
<if test="mdEvent.endTime != null">end_time,</if>
@ -253,6 +258,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="mdEvent.eventLevel != null">event_level,</if>
<if test="mdEvent.sectionId != null">section_id,</if>
<if test="mdEvent.eventTypeCode2 != null">event_type_code2,</if>
<if test="mdEvent.eventTypeName2 != null">event_type_name2,</if>
<if test="mdEvent.eventCause != null">event_cause,</if>
<if test="mdEvent.accidentWeather != null">accident_weather,</if>
<if test="mdEvent.accidentQueue != null">accident_queue,</if>
@ -278,6 +284,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="mdEvent.fusionId != null">#{mdEvent.fusionId},</if>
<if test="mdEvent.eventName != null">#{mdEvent.eventName},</if>
<if test="mdEvent.eventTypeCode != null">#{mdEvent.eventTypeCode},</if>
<if test="mdEvent.eventTypeName != null">#{mdEvent.eventTypeName},</if>
<if test="mdEvent.eventDesc != null">#{mdEvent.eventDesc},</if>
<if test="mdEvent.occurTime != null">#{mdEvent.occurTime},</if>
<if test="mdEvent.endTime != null">#{mdEvent.endTime},</if>
@ -293,6 +300,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="mdEvent.eventLevel != null">#{mdEvent.eventLevel},</if>
<if test="mdEvent.sectionId != null">#{mdEvent.sectionId},</if>
<if test="mdEvent.eventTypeCode2 != null">#{mdEvent.eventTypeCode2},</if>
<if test="mdEvent.eventTypeName2 != null">#{mdEvent.eventTypeName2},</if>
<if test="mdEvent.eventCause != null">#{mdEvent.eventCause},</if>
<if test="mdEvent.accidentWeather != null">#{mdEvent.accidentWeather},</if>
<if test="mdEvent.accidentQueue != null">#{mdEvent.accidentQueue},</if>
@ -357,6 +365,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<trim prefix="SET" suffixOverrides=",">
<if test="eventName != null">event_name = #{eventName},</if>
<if test="eventTypeCode != null">event_type_code = #{eventTypeCode},</if>
<if test="eventTypeName != null">event_type_name = #{eventTypeName},</if>
<if test="eventDesc != null">event_desc = #{eventDesc},</if>
<if test="occurTime != null">occur_time = #{occurTime},</if>
<if test="endTime != null">end_time = #{endTime},</if>
@ -372,6 +381,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="eventLevel != null">event_level = #{eventLevel},</if>
<if test="sectionId != null">section_id = #{sectionId},</if>
<if test="eventTypeCode2 != null">event_type_code2 = #{eventTypeCode2},</if>
<if test="eventTypeName2 != null">event_type_name2 = #{eventTypeName2},</if>
<if test="eventCause != null">event_cause = #{eventCause},</if>
<if test="accidentWeather != null">accident_weather = #{accidentWeather},</if>
<if test="accidentQueue != null">accident_queue = #{accidentQueue},</if>

Loading…
Cancel
Save