风险时段分析

This commit is contained in:
cwchen 2024-12-10 10:36:01 +08:00
parent ee7019f797
commit 1b40800b83
15 changed files with 614 additions and 4 deletions

View File

@ -0,0 +1,56 @@
package com.securityControl.common.core;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.BeanProperty;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.ContextualSerializer;
import com.securityControl.common.core.annotation.Sensitive;
import com.securityControl.common.core.enums.SensitizedType;
import com.securityControl.common.core.utils.SensitizedUtil;
import java.io.IOException;
import java.util.Objects;
/**
* @className:SensitiveInfoSerialize
* @author:cwchen
* @date:2024-12-10-9:53
* @version:1.0
* @description:
*/
public class SensitiveInfoSerialize extends JsonSerializer<String> implements ContextualSerializer {
private SensitizedType sensitizedType;
/**
* 步骤一
* 方法来源于ContextualSerializer获取属性上的注解属性,同时返回一个合适的序列化器
*/
@Override
public JsonSerializer<?> createContextual(SerializerProvider serializerProvider, BeanProperty beanProperty) throws JsonMappingException {
// 获取自定义注解
Sensitive annotation = beanProperty.getAnnotation(Sensitive.class);
// 注解不为空且标注的字段为String
if(Objects.nonNull(annotation) && Objects.equals(String.class, beanProperty.getType().getRawClass())){
this.sensitizedType = annotation.value();
//自定义情况返回本序列化器将顺利进入到该类中的serialize方法中
return this;
}
// 注解为空字段不为String寻找合适的序列化器进行处理
return serializerProvider.findValueSerializer(beanProperty.getType(), beanProperty);
}
/**
* 步骤二
* 方法来源于JsonSerializer<String>指定返回类型为String类型serialize()将修改后的数据返回
*/
@Override
public void serialize(String str, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
if(Objects.isNull(sensitizedType)){
// 定义策略为空返回原字符串
jsonGenerator.writeString(str);
}else {
// 定义策略不为空返回策略处理过的字符串
jsonGenerator.writeString(SensitizedUtil.desensitized(str,sensitizedType));
}
}
}

View File

@ -0,0 +1,19 @@
package com.securityControl.common.core.annotation;
import com.fasterxml.jackson.annotation.JacksonAnnotationsInside;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.securityControl.common.core.SensitiveInfoSerialize;
import com.securityControl.common.core.enums.SensitizedType;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.FIELD) //作用于字段上
@Retention(RetentionPolicy.RUNTIME)
@JacksonAnnotationsInside // 表示自定义自己的注解Sensitive
@JsonSerialize(using = SensitiveInfoSerialize.class) // 该注解使用序列化的方式
public @interface Sensitive {
SensitizedType value();
}

View File

@ -0,0 +1,63 @@
package com.securityControl.common.core.enums;
/**
* @className:SensitizedType
* @author:cwchen
* @date:2024-12-10-9:52
* @version:1.0
* @description: 脱敏字段类型枚举
*/
public enum SensitizedType {
/**
* 用户id
*/
USER_ID,
/**
* 中文名
*/
CHINESE_NAME,
/**
* 身份证号
*/
ID_CARD,
/**
* 座机号
*/
FIXED_PHONE,
/**
* 手机号
*/
MOBILE_PHONE,
/**
* 地址
*/
ADDRESS,
/**
* 电子邮件
*/
EMAIL,
/**
* 密码
*/
PASSWORD,
/**
* 中国大陆车牌包含普通车辆新能源车辆
*/
CAR_LICENSE,
/**
* 银行卡
*/
BANK_CARD,
/**
* IPv4地址
*/
IPV4,
/**
* IPv6地址
*/
IPV6,
/**
* 定义了一个first_mask的规则只显示第一个字符
*/
FIRST_MASK
}

View File

@ -0,0 +1,252 @@
package com.securityControl.common.core.utils;
import cn.hutool.core.util.CharUtil;
import cn.hutool.core.util.StrUtil;
import com.securityControl.common.core.enums.SensitizedType;
/**
* @className:SensitizedUtil
* @author:cwchen
* @date:2024-12-10-9:57
* @version:1.0
* @description:
*/
public class SensitizedUtil {
public static String desensitized(CharSequence str, SensitizedType desensitizedType) {
if (StrUtil.isBlank(str)) {
return StrUtil.EMPTY;
}
String newStr = String.valueOf(str);
switch (desensitizedType) {
case USER_ID:
newStr = String.valueOf(userId());
break;
case CHINESE_NAME:
newStr = chineseName(String.valueOf(str));
break;
case ID_CARD:
newStr = idCardNum(String.valueOf(str), 3, 4);
break;
case FIXED_PHONE:
newStr = fixedPhone(String.valueOf(str));
break;
case MOBILE_PHONE:
newStr = mobilePhone(String.valueOf(str));
break;
case ADDRESS:
newStr = address(String.valueOf(str), 8);
break;
case EMAIL:
newStr = email(String.valueOf(str));
break;
case PASSWORD:
newStr = password(String.valueOf(str));
break;
case CAR_LICENSE:
newStr = carLicense(String.valueOf(str));
break;
case BANK_CARD:
newStr = bankCard(String.valueOf(str));
break;
case IPV4:
newStr = ipv4(String.valueOf(str));
break;
case IPV6:
newStr = ipv6(String.valueOf(str));
break;
case FIRST_MASK:
newStr = firstMask(String.valueOf(str));
break;
default:
}
return newStr;
}
/**
* 用户id不对外提供userId
*
* @return 脱敏后的主键
*/
public static Long userId() {
return 0L;
}
/**
* 定义了一个first_mask的规则只显示第一个字符<br>
* 脱敏前123456789脱敏后1********
*
* @param str 字符串
* @return 脱敏后的字符串
*/
public static String firstMask(String str) {
if (StrUtil.isBlank(str)) {
return StrUtil.EMPTY;
}
return StrUtil.hide(str, 1, str.length());
}
/**
* 中文姓名只显示第一个汉字其他隐藏为2个星号比如**
*
* @param fullName 姓名
* @return 脱敏后的姓名
*/
public static String chineseName(String fullName) {
return firstMask(fullName);
}
/**
* 身份证号前1位 和后2位
*
* @param idCardNum 身份证
* @param front 保留前面的front位数从1开始
* @param end 保留后面的end位数从1开始
* @return 脱敏后的身份证
*/
public static String idCardNum(String idCardNum, int front, int end) {
//身份证不能为空
if (StrUtil.isBlank(idCardNum)) {
return StrUtil.EMPTY;
}
//需要截取的长度不能大于身份证号长度
if ((front + end) > idCardNum.length()) {
return StrUtil.EMPTY;
}
//需要截取的不能小于0
if (front < 0 || end < 0) {
return StrUtil.EMPTY;
}
return StrUtil.hide(idCardNum, front, idCardNum.length() - end);
}
/**
* 固定电话 前四位后两位
*
* @param num 固定电话
* @return 脱敏后的固定电话
*/
public static String fixedPhone(String num) {
if (StrUtil.isBlank(num)) {
return StrUtil.EMPTY;
}
return StrUtil.hide(num, 4, num.length() - 2);
}
/**
* 手机号码前三位后4位其他隐藏比如135****2210
*
* @param num 移动电话
* @return 脱敏后的移动电话
*/
public static String mobilePhone(String num) {
if (StrUtil.isBlank(num)) {
return StrUtil.EMPTY;
}
return StrUtil.hide(num, 3, num.length() - 4);
}
/**
* 地址只显示到地区不显示详细地址比如北京市海淀区****
*
* @param address 家庭住址
* @param sensitiveSize 敏感信息长度
* @return 脱敏后的家庭地址
*/
public static String address(String address, int sensitiveSize) {
if (StrUtil.isBlank(address)) {
return StrUtil.EMPTY;
}
int length = address.length();
return StrUtil.hide(address, length - sensitiveSize, length);
}
/**
* 电子邮箱邮箱前缀仅显示第一个字母前缀其他隐藏用星号代替@及后面的地址显示比如d**@126.com
*
* @param email 邮箱
* @return 脱敏后的邮箱
*/
public static String email(String email) {
if (StrUtil.isBlank(email)) {
return StrUtil.EMPTY;
}
int index = StrUtil.indexOf(email, '@');
if (index <= 1) {
return email;
}
return StrUtil.hide(email, 1, index);
}
/**
* 密码密码的全部字符都用*代替比如******
*
* @param password 密码
* @return 脱敏后的密码
*/
public static String password(String password) {
if (StrUtil.isBlank(password)) {
return StrUtil.EMPTY;
}
return StrUtil.repeat('*', password.length());
}
/**
* 中国车牌车牌中间用*代替
* eg1null - ""
* eg1"" - ""
* eg3苏D40000 - 苏D4***0
* eg4陕A12345D - 陕A1****D
* eg5京A123 - 京A123 如果是错误的车牌不处理
*
* @param carLicense 完整的车牌号
* @return 脱敏后的车牌
*/
public static String carLicense(String carLicense) {
if (StrUtil.isBlank(carLicense)) {
return StrUtil.EMPTY;
}
// 普通车牌
if (carLicense.length() == 7) {
carLicense = StrUtil.hide(carLicense, 3, 6);
} else if (carLicense.length() == 8) {
// 新能源车牌
carLicense = StrUtil.hide(carLicense, 3, 7);
}
return carLicense;
}
/**
* 银行卡号脱敏
* eg: 1101 **** **** **** 3256
*
* @param bankCardNo 银行卡号
* @return 脱敏之后的银行卡号
* @since 5.6.3
*/
public static String bankCard(String bankCardNo) {
if (StrUtil.isBlank(bankCardNo)) {
return bankCardNo;
}
bankCardNo = StrUtil.trim(bankCardNo);
if (bankCardNo.length() < 9) {
return bankCardNo;
}
final int length = bankCardNo.length();
final int midLength = length - 8;
final StringBuilder buf = new StringBuilder();
buf.append(bankCardNo, 0, 4);
for (int i = 0; i < midLength; ++i) {
if (i % 4 == 0) {
buf.append(CharUtil.SPACE);
}
buf.append('*');
}
buf.append(CharUtil.SPACE).append(bankCardNo, length - 4, length);
return buf.toString();
}
/**
* IPv4脱敏脱敏前192.0.2.1脱敏后192.*.*.*
*
* @param ipv4 IPv4地址
* @return 脱敏后的地址
*/
public static String ipv4(String ipv4) {
return StrUtil.subBefore(ipv4, '.', false) + ".*.*.*";
}
/**
* IPv4脱敏脱敏前2001:0db8:86a3:08d3:1319:8a2e:0370:7344脱敏后2001:*:*:*:*:*:*:*
*
* @param ipv6 IPv4地址
* @return 脱敏后的地址
*/
public static String ipv6(String ipv6) {
return StrUtil.subBefore(ipv6, ':', false) + ":*:*:*:*:*:*:*";
}
}

View File

@ -0,0 +1,37 @@
package com.sercurityControl.proteam.supplement.controller;
import com.securityControl.common.log.annotation.Log;
import com.securityControl.common.log.enums.BusinessType;
import com.sercurityControl.proteam.supplement.domain.dto.ParamsDto;
import com.sercurityControl.proteam.supplement.service.RiskTimeService;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import java.util.Map;
/**
* @className:RiskTimeController
* @author:cwchen
* @date:2024-12-10-9:18
* @version:1.0
* @description:风险时段分析-controller
*/
@RestController
@RequestMapping("/pot/riskTime/")
@Slf4j
public class RiskTimeController {
@Resource(name = "RiskTimeService")
private RiskTimeService service;
@ApiOperation(value = "风险时段分析-列表")
@PostMapping(value = "getRiskRectList")
@Log(title = "风险时段分析", menu = "值班任务->风险时段分析", businessType = BusinessType.QUERY, details = "风险时段分析")
public Map<String, Object> getRiskTimeList(ParamsDto dto) {
return service.getRiskTimeList(dto);
}
}

View File

@ -20,6 +20,10 @@ public class ParamsDto {
private String riskLevel;
/**是否整改 0.未整改 1.已整改*/
private String isRect;
/**开始日期*/
private String startDay;
/**结束日期*/
private String endDay;
private int page;

View File

@ -1,5 +1,7 @@
package com.sercurityControl.proteam.supplement.domain.vo;
import com.securityControl.common.core.annotation.Sensitive;
import com.securityControl.common.core.enums.SensitizedType;
import com.securityControl.common.core.web.page.PageDomain;
import lombok.Data;
@ -22,6 +24,7 @@ public class ProVioVo{
/**班组长*/
private String workManager;
/**班组长手机号*/
@Sensitive(SensitizedType.MOBILE_PHONE)
private String workManagerPhone;
/**风险等级*/
private String riskLevel;

View File

@ -1,5 +1,7 @@
package com.sercurityControl.proteam.supplement.domain.vo;
import com.securityControl.common.core.annotation.Sensitive;
import com.securityControl.common.core.enums.SensitizedType;
import lombok.Data;
import java.util.List;
@ -27,6 +29,7 @@ public class RiskRectDetailVo {
/**班组长*/
private String workManager;
/**班组长手机号*/
@Sensitive(SensitizedType.MOBILE_PHONE)
private String workManagerPhone;
/**违章等级*/
private String levelId;

View File

@ -1,5 +1,7 @@
package com.sercurityControl.proteam.supplement.domain.vo;
import com.securityControl.common.core.annotation.Sensitive;
import com.securityControl.common.core.enums.SensitizedType;
import lombok.Data;
/**
@ -23,6 +25,7 @@ public class RiskRectVo {
/**班组长*/
private String workManager;
/**班组长手机号*/
@Sensitive(SensitizedType.MOBILE_PHONE)
private String workManagerPhone;
/**违章等级*/
private String levelId;

View File

@ -0,0 +1,39 @@
package com.sercurityControl.proteam.supplement.domain.vo;
import com.securityControl.common.core.annotation.Sensitive;
import com.securityControl.common.core.enums.SensitizedType;
import lombok.Data;
/**
* @className:ProVioVo
* @author:cwchen
* @date:2024-12-09-15:12
* @version:1.0
* @description:风险时段分析-vo
*/
@Data
public class RiskTimeVo {
/**id*/
private String id;
/**作业票编号*/
private String ticketNo;
/**作业票名称*/
private String ticketName;
/**工程名称*/
private String proName;
/**班组长*/
private String workManager;
/**班组长手机号*/
@Sensitive(SensitizedType.MOBILE_PHONE)
private String workManagerPhone;
/**风险等级*/
private String riskLevel;
/**作业部位*/
private String workSite;
/**工序*/
private String gx;
/**时间*/
private String time;
}

View File

@ -0,0 +1,26 @@
package com.sercurityControl.proteam.supplement.mapper;
import com.sercurityControl.proteam.supplement.domain.dto.ParamsDto;
import com.sercurityControl.proteam.supplement.domain.vo.RiskTimeVo;
import org.springframework.stereotype.Repository;
import java.util.List;
/**
* @className:RiskTimeMapper
* @author:cwchen
* @date:2024-12-10-9:20
* @version:1.0
* @description:风险时段分析-mapper
*/
@Repository("RiskTimeMapper")
public interface RiskTimeMapper {
/**
* 风险时段分析-列表
* @param dto
* @return List<RiskTimeVo>
* @author cwchen
* @date 2024/12/10 9:26
*/
List<RiskTimeVo> getRiskTimeList(ParamsDto dto);
}

View File

@ -0,0 +1,23 @@
package com.sercurityControl.proteam.supplement.service;
import com.sercurityControl.proteam.supplement.domain.dto.ParamsDto;
import java.util.Map;
/**
* @className:RiskTimeService
* @author:cwchen
* @date:2024-12-10-9:19
* @version:1.0
* @description:风险时段分析-service
*/
public interface RiskTimeService {
/**
* 风险时段分析
* @param dto
* @return Map<String,Object>
* @author cwchen
* @date 2024/12/10 9:25
*/
Map<String, Object> getRiskTimeList(ParamsDto dto);
}

View File

@ -40,10 +40,6 @@ public class RiskRectServiceImpl implements RiskRectService {
List<RiskRectVo> list = null;
try {
list = mapper.getRiskRectList(dto);
/*list.forEach(item->{
List<String> rectTimeList = mapper.getRectTime(item);
item.setTime(rectTimeList.get(0));
});*/
} catch (Exception e) {
log.error(e.toString(),e);
}

View File

@ -0,0 +1,52 @@
package com.sercurityControl.proteam.supplement.service.impl;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.securityControl.common.core.constant.HttpStatus;
import com.sercurityControl.proteam.supplement.domain.dto.ParamsDto;
import com.sercurityControl.proteam.supplement.domain.vo.RiskRectVo;
import com.sercurityControl.proteam.supplement.domain.vo.RiskTimeVo;
import com.sercurityControl.proteam.supplement.mapper.RiskTimeMapper;
import com.sercurityControl.proteam.supplement.service.RiskTimeService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @className:RiskTimeServiceImpl
* @author:cwchen
* @date:2024-12-10-9:19
* @version:1.0
* @description:风险时段分析-impl
*/
@Service(value = "RiskTimeService")
@Slf4j
public class RiskTimeServiceImpl implements RiskTimeService {
@Resource(name = "RiskTimeMapper")
private RiskTimeMapper mapper;
@Override
public Map<String, Object> getRiskTimeList(ParamsDto dto) {
PageHelper.startPage(dto.getPage(), dto.getLimit());
Map<String, Object> map = new HashMap<>(16);
List<RiskTimeVo> list = null;
try {
list = mapper.getRiskTimeList(dto);
} catch (Exception e) {
log.error(e.toString(),e);
}
PageInfo<RiskTimeVo> pageInfo = new PageInfo<>(list);
map.put("code", HttpStatus.SUCCESS);
map.put("msg", "获取数据成功");
map.put("count", pageInfo.getTotal());
map.put("curr", dto.getPage());
map.put("limit", dto.getLimit());
map.put("data", pageInfo.getList());
return map;
}
}

View File

@ -0,0 +1,34 @@
<?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.sercurityControl.proteam.supplement.mapper.RiskTimeMapper">
<!--风险时段分析-->
<select id="getRiskTimeList" resultType="com.sercurityControl.proteam.supplement.domain.vo.RiskTimeVo">
SELECT jjcm.id AS id,
jjcm.ticket_no AS ticketNo,
jjt.ticket_name AS ticketName,
jjcm.bidding_section_name AS proName,
jjcm.re_assessment_risk_level AS riskLevel,
jjcmi.work_manage AS workManager,
jjcmi.work_manage_phone AS workManagerPhone,
jjcmi.work_gx AS gx,
jjcmi.work_site AS workSite,
jjcm.current_constr_date AS time
FROM jj_class_meetting jjcm
LEFT JOIN jj_class_metting_info jjcmi ON jjcm.id = jjcmi.class_id
LEFT JOIN jj_ticket jjt ON jjcm.ticket_id = jjt.id
<where>
<if test="proName!=null and proName!=''">
AND INSTR(jjcm.bidding_section_name,#{proName}) > 0
</if>
<if test="riskLevel!=null and riskLevel!=''">
AND jjcm.re_assessment_risk_level = #{riskLevel}
</if>
<if test="startDay!=null and startDay!='' and endDay!=null and endDay!=''">
AND jjcm.current_constr_date BETWEEN #{startDay} AND #{endDay}
</if>
AND jjcm.delete_flag = '0'
</where>
ORDER BY jjcm.create_time DESC
</select>
</mapper>