This commit is contained in:
huzhengkao 2025-10-21 14:21:49 +08:00
commit cf9eb6a75a
349 changed files with 28201 additions and 0 deletions

View File

@ -0,0 +1,30 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.tcctyn</groupId>
<artifactId>tcctyn-api</artifactId>
<version>1.0.0</version>
</parent>
<artifactId>tcctyn-api-iot</artifactId>
<properties>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-openfeign-core</artifactId>
</dependency>
<dependency>
<groupId>com.tcctyn</groupId>
<artifactId>tcctyn-common-core</artifactId>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,29 @@
package com.tcctyn.iot.api;
import com.tcctyn.common.core.constant.ServiceNameConstants;
import com.tcctyn.common.core.web.domain.R;
import com.tcctyn.common.core.web.domain.model.LoginUser;
import com.tcctyn.iot.api.factory.RemoteDeviceFallbackFactory;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
/**
* 用户服务
*
* @author tcctyn
*/
@FeignClient(contextId = "remoteDeviceService", value = ServiceNameConstants.SYSTEM_SERVICE, fallbackFactory = RemoteDeviceFallbackFactory.class)
public interface RemoteDeviceService
{
/**
* 通过id获取设备信息
*
* @param username 用户名
* @return 结果
*/
@GetMapping("/device/info/{deviceNo}")
public R<LoginUser> getDeviceInfoByDeviceNo(@PathVariable("deviceNo") String deviceNo);
}

View File

@ -0,0 +1,58 @@
package com.tcctyn.iot.api.domain;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import lombok.Data;
import javax.validation.constraints.NotBlank;
/**
* <p>
* 设备配置表
* </p>
*
* @author 宋国强
* @since 2025-04-14
*/
@Data
public class DeviceConfig {
/**
* 主键id
*/
@TableId(value = "id", type = IdType.AUTO)
private Long id;
/**
* 设备编号
*/
@NotBlank(message = "设备编号不能为空")
private String deviceNo;
/**
* 用户账户
*/
private String username;
/**
* 密码
*/
private String password;
/**
* IP地址
*/
private String ip;
/**
* 端口号
*/
private String port;
/**
* 备注
*/
private String remark;
}

View File

@ -0,0 +1,161 @@
package com.tcctyn.iot.api.domain;
import com.baomidou.mybatisplus.annotation.*;
import lombok.Data;
import lombok.EqualsAndHashCode;
import javax.validation.constraints.NotBlank;
import java.io.Serializable;
import java.util.Date;
/**
* <p>
* 设备信息表
* </p>
*
* @author 代超
* @since 2024-10-09
*/
@Data
@EqualsAndHashCode(callSuper = false)
@TableName("device_info")
public class DeviceInfo implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 主键id
*/
@TableId(value = "id", type = IdType.AUTO)
private Long id;
/**
* 设备编号
*/
@NotBlank(message = "设备编号不能为空")
private String deviceNo;
/**
* 设备名称
*/
private String deviceName;
/**
* 设备型号
*/
private String deviceModel;
/**
* 设备厂商
*/
private String deviceManufacturer;
/**
* 设备协议
*/
private String deviceProtocol;
/**
* 接入方式
*/
private String accessMethod;
/**
* 设备类型
*/
private String deviceType;
/**
* 设备状态在线/离线
*/
private String deviceStatus;
/**
* 归属区域id,机场需要挂在地区下面
*/
private Long regionId;
/**
* 归属云台/卡口id
*/
private Long pointId;
/**
* 林区id
*/
private Long forestId;
/**
* 林场id
*/
private Long farmId;
/**
* 电子围栏id
*/
private Long fenceId;
/**
* 机场id
*/
private Long airportId;
/**
* 地址
*/
private String address;
/**
* 经度
*/
private String longitude;
/**
* 纬度
*/
private String latitude;
/**
* 高度
*/
private String height;
/**
* 设备启用状态0-停用/1-启用
*/
private Integer enableFlag;
/**
* 备注信息
*/
private String remark;
/**
* 该条记录是否被删除1-已删除0-未删除
*/
@TableLogic
private Integer delFlag;
/**
* 创建人员姓名
*/
private String createdBy;
/**
* 记录创建时间默认用服务器时间
*/
@TableField(fill = FieldFill.INSERT)
private Date createdTime;
/**
* 修改人员姓名
*/
private String updatedBy;
/**
* 记录修改时间默认用服务器时间
*/
@TableField(fill = FieldFill.UPDATE)
private Date updatedTime;
}

View File

@ -0,0 +1,35 @@
package com.tcctyn.iot.api.factory;
import com.tcctyn.common.core.web.domain.R;
import com.tcctyn.common.core.web.domain.model.LoginUser;
import com.tcctyn.iot.api.RemoteDeviceService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cloud.openfeign.FallbackFactory;
import org.springframework.stereotype.Component;
/**
* 用户服务降级处理
*
* @author tcctyn
*/
@Component
public class RemoteDeviceFallbackFactory implements FallbackFactory<RemoteDeviceService>
{
private static final Logger log = LoggerFactory.getLogger(RemoteDeviceFallbackFactory.class);
@Override
public RemoteDeviceService create(Throwable throwable)
{
log.error("物联网服务调用失败:{}", throwable.getMessage());
return new RemoteDeviceService()
{
@Override
public R<LoginUser> getDeviceInfoByDeviceNo(String deviceNo) {
return R.fail("获取设备信息失败:" + throwable.getMessage());
}
};
}
}

View File

@ -0,0 +1 @@
com.tcctyn.iot.api.factory.RemoteDeviceFallbackFactory

View File

@ -0,0 +1,15 @@
package com.tcctyn.common.core.annotation;
import java.lang.annotation.*;
/**
* 匿名访问不鉴权注解
*
* @author tcctyn
*/
@Target({ ElementType.METHOD, ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Anonymous
{
}

View File

@ -0,0 +1,29 @@
package com.tcctyn.common.core.annotation;
import java.lang.annotation.*;
/**
* 数据权限过滤注解
*
* @author tcctyn
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface DataScope
{
/**
* 部门表的别名
*/
public String deptAlias() default "";
/**
* 用户表的别名
*/
public String userAlias() default "";
/**
* 权限字符用于多个角色匹配符合要求的权限默认根据权限注解@ss获取多个权限用逗号分隔开来
*/
public String permission() default "";
}

View File

@ -0,0 +1,24 @@
package com.tcctyn.common.core.annotation;
import com.tcctyn.common.core.enums.DataSourceType;
import java.lang.annotation.*;
/**
* 自定义多数据源切换注解
*
* 优先级先方法后类如果方法覆盖了类上的数据源类型以方法的为准否则以类上的为准
*
* @author tcctyn
*/
@Target({ ElementType.METHOD, ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface DataSource
{
/**
* 切换数据源名称
*/
public DataSourceType value() default DataSourceType.MASTER;
}

View File

@ -0,0 +1,48 @@
package com.tcctyn.common.core.annotation;
import com.tcctyn.common.core.enums.BusinessType;
import com.tcctyn.common.core.enums.OperatorType;
import java.lang.annotation.*;
/**
* 自定义操作日志记录注解
*
* @author tcctyn
*
*/
@Target({ ElementType.PARAMETER, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Log
{
/**
* 模块
*/
public String title() default "";
/**
* 功能
*/
public BusinessType businessType() default BusinessType.OTHER;
/**
* 操作人类别
*/
public OperatorType operatorType() default OperatorType.MANAGE;
/**
* 是否保存请求的参数
*/
public boolean isSaveRequestData() default true;
/**
* 是否保存响应的参数
*/
public boolean isSaveResponseData() default true;
/**
* 排除指定的请求参数
*/
public String[] excludeParamNames() default {};
}

View File

@ -0,0 +1,37 @@
package com.tcctyn.common.core.annotation;
import com.tcctyn.common.core.constant.CacheConstants;
import com.tcctyn.common.core.enums.LimitType;
import java.lang.annotation.*;
/**
* 限流注解
*
* @author tcctyn
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RateLimiter
{
/**
* 限流key
*/
public String key() default CacheConstants.RATE_LIMIT_KEY;
/**
* 限流时间,单位秒
*/
public int time() default 60;
/**
* 限流次数
*/
public int count() default 100;
/**
* 限流类型
*/
public LimitType limitType() default LimitType.DEFAULT;
}

View File

@ -0,0 +1,26 @@
package com.tcctyn.common.core.annotation;
import java.lang.annotation.*;
/**
* 自定义注解防止表单重复提交
*
* @author tcctyn
*
*/
@Inherited
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RepeatSubmit
{
/**
* 间隔时间(ms)小于此时间视为重复提交
*/
public int interval() default 5000;
/**
* 提示消息
*/
public String message() default "不允许重复提交,请稍候再试";
}

View File

@ -0,0 +1,25 @@
package com.tcctyn.common.core.annotation;
import com.fasterxml.jackson.annotation.JacksonAnnotationsInside;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.tcctyn.common.core.config.serializer.SensitiveJsonSerializer;
import com.tcctyn.common.core.enums.DesensitizedType;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 数据脱敏注解
*
* @author tcctyn
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
@JacksonAnnotationsInside
@JsonSerialize(using = SensitiveJsonSerializer.class)
public @interface Sensitive
{
DesensitizedType desensitizedType();
}

View File

@ -0,0 +1,122 @@
package com.tcctyn.common.core.config;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* 读取项目相关配置
*
* @author tcctyn
*/
@Component
@ConfigurationProperties(prefix = "tcctyn")
public class TcctynConfig
{
/** 项目名称 */
private String name;
/** 版本 */
private String version;
/** 版权年份 */
private String copyrightYear;
/** 上传路径 */
private static String profile;
/** 获取地址开关 */
private static boolean addressEnabled;
/** 验证码类型 */
private static String captchaType;
public String getName()
{
return name;
}
public void setName(String name)
{
this.name = name;
}
public String getVersion()
{
return version;
}
public void setVersion(String version)
{
this.version = version;
}
public String getCopyrightYear()
{
return copyrightYear;
}
public void setCopyrightYear(String copyrightYear)
{
this.copyrightYear = copyrightYear;
}
public static String getProfile()
{
return profile;
}
public void setProfile(String profile)
{
TcctynConfig.profile = profile;
}
public static boolean isAddressEnabled()
{
return addressEnabled;
}
public void setAddressEnabled(boolean addressEnabled)
{
TcctynConfig.addressEnabled = addressEnabled;
}
public static String getCaptchaType() {
return captchaType;
}
public void setCaptchaType(String captchaType) {
TcctynConfig.captchaType = captchaType;
}
/**
* 获取导入上传路径
*/
public static String getImportPath()
{
return getProfile() + "/import";
}
/**
* 获取头像上传路径
*/
public static String getAvatarPath()
{
return getProfile() + "/avatar";
}
/**
* 获取下载路径
*/
public static String getDownloadPath()
{
return getProfile() + "/download/";
}
/**
* 获取上传路径
*/
public static String getUploadPath()
{
return getProfile() + "/upload";
}
}

View File

@ -0,0 +1,68 @@
package com.tcctyn.common.core.config.serializer;
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.tcctyn.common.core.annotation.Sensitive;
import com.tcctyn.common.core.web.domain.model.LoginUser;
import com.tcctyn.common.core.enums.DesensitizedType;
import com.tcctyn.common.core.utils.SecurityUtils;
import java.io.IOException;
import java.util.Objects;
/**
* 数据脱敏序列化过滤
*
* @author tcctyn
*/
public class SensitiveJsonSerializer extends JsonSerializer<String> implements ContextualSerializer
{
private DesensitizedType desensitizedType;
@Override
public void serialize(String value, JsonGenerator gen, SerializerProvider serializers) throws IOException
{
if (desensitization())
{
gen.writeString(desensitizedType.desensitizer().apply(value));
}
else
{
gen.writeString(value);
}
}
@Override
public JsonSerializer<?> createContextual(SerializerProvider prov, BeanProperty property)
throws JsonMappingException
{
Sensitive annotation = property.getAnnotation(Sensitive.class);
if (Objects.nonNull(annotation) && Objects.equals(String.class, property.getType().getRawClass()))
{
this.desensitizedType = annotation.desensitizedType();
return this;
}
return prov.findValueSerializer(property.getType(), property);
}
/**
* 是否需要脱敏处理
*/
private boolean desensitization()
{
try
{
LoginUser securityUser = SecurityUtils.getLoginUser();
// 管理员不脱敏
return !securityUser.getUser().isAdmin();
}
catch (Exception e)
{
return true;
}
}
}

View File

@ -0,0 +1,9 @@
package com.tcctyn.common.core.constant;
/**
* 地区常量
*/
public interface RegionConstants {
String DIVISION_COMMA = ",";
}

View File

@ -0,0 +1,20 @@
package com.tcctyn.common.core.enums;
/**
* 操作状态
*
* @author tcctyn
*
*/
public enum BusinessStatus
{
/**
* 成功
*/
SUCCESS,
/**
* 失败
*/
FAIL,
}

View File

@ -0,0 +1,59 @@
package com.tcctyn.common.core.enums;
/**
* 业务操作类型
*
* @author tcctyn
*/
public enum BusinessType
{
/**
* 其它
*/
OTHER,
/**
* 新增
*/
INSERT,
/**
* 修改
*/
UPDATE,
/**
* 删除
*/
DELETE,
/**
* 授权
*/
GRANT,
/**
* 导出
*/
EXPORT,
/**
* 导入
*/
IMPORT,
/**
* 强退
*/
FORCE,
/**
* 生成代码
*/
GENCODE,
/**
* 清空数据
*/
CLEAN,
}

View File

@ -0,0 +1,19 @@
package com.tcctyn.common.core.enums;
/**
* 数据源
*
* @author tcctyn
*/
public enum DataSourceType
{
/**
* 主库
*/
MASTER,
/**
* 从库
*/
SLAVE
}

View File

@ -0,0 +1,60 @@
package com.tcctyn.common.core.enums;
import com.tcctyn.common.core.utils.DesensitizedUtil;
import java.util.function.Function;
/**
* 脱敏类型
*
* @author tcctyn
*/
public enum DesensitizedType
{
/**
* 姓名第2位星号替换
*/
USERNAME(s -> s.replaceAll("(\\S)\\S(\\S*)", "$1*$2")),
/**
* 密码全部字符都用*代替
*/
PASSWORD(DesensitizedUtil::password),
/**
* 身份证中间10位星号替换
*/
ID_CARD(s -> s.replaceAll("(\\d{4})\\d{10}(\\d{4})", "$1** **** ****$2")),
/**
* 手机号中间4位星号替换
*/
PHONE(s -> s.replaceAll("(\\d{3})\\d{4}(\\d{4})", "$1****$2")),
/**
* 电子邮箱仅显示第一个字母和@后面的地址显示其他星号替换
*/
EMAIL(s -> s.replaceAll("(^.)[^@]*(@.*$)", "$1****$2")),
/**
* 银行卡号保留最后4位其他星号替换
*/
BANK_CARD(s -> s.replaceAll("\\d{15}(\\d{3})", "**** **** **** **** $1")),
/**
* 车牌号码包含普通车辆新能源车辆
*/
CAR_LICENSE(DesensitizedUtil::carLicense);
private final Function<String, String> desensitizer;
DesensitizedType(Function<String, String> desensitizer)
{
this.desensitizer = desensitizer;
}
public Function<String, String> desensitizer()
{
return desensitizer;
}
}

View File

@ -0,0 +1,37 @@
package com.tcctyn.common.core.enums;
import org.springframework.lang.Nullable;
import java.util.HashMap;
import java.util.Map;
/**
* 请求方式
*
* @author tcctyn
*/
public enum HttpMethod
{
GET, HEAD, POST, PUT, PATCH, DELETE, OPTIONS, TRACE;
private static final Map<String, HttpMethod> mappings = new HashMap<>(16);
static
{
for (HttpMethod httpMethod : values())
{
mappings.put(httpMethod.name(), httpMethod);
}
}
@Nullable
public static HttpMethod resolve(@Nullable String method)
{
return (method != null ? mappings.get(method) : null);
}
public boolean matches(String method)
{
return (this == resolve(method));
}
}

View File

@ -0,0 +1,20 @@
package com.tcctyn.common.core.enums;
/**
* 限流类型
*
* @author tcctyn
*/
public enum LimitType
{
/**
* 默认策略全局限流
*/
DEFAULT,
/**
* 根据请求者IP进行限流
*/
IP
}

View File

@ -0,0 +1,24 @@
package com.tcctyn.common.core.enums;
/**
* 操作人类别
*
* @author tcctyn
*/
public enum OperatorType
{
/**
* 其它
*/
OTHER,
/**
* 后台用户
*/
MANAGE,
/**
* 手机端用户
*/
MOBILE
}

View File

@ -0,0 +1,16 @@
package com.tcctyn.common.core.exception.user;
/**
* 黑名单IP异常类
*
* @author tcctyn
*/
public class BlackListException extends UserException
{
private static final long serialVersionUID = 1L;
public BlackListException()
{
super("login.blocked", null);
}
}

View File

@ -0,0 +1,16 @@
package com.tcctyn.common.core.exception.user;
/**
* 验证码错误异常类
*
* @author tcctyn
*/
public class CaptchaException extends UserException
{
private static final long serialVersionUID = 1L;
public CaptchaException()
{
super("user.jcaptcha.error", null);
}
}

View File

@ -0,0 +1,16 @@
package com.tcctyn.common.core.exception.user;
/**
* 用户不存在异常类
*
* @author tcctyn
*/
public class UserNotExistsException extends UserException
{
private static final long serialVersionUID = 1L;
public UserNotExistsException()
{
super("user.not.exists", null);
}
}

View File

@ -0,0 +1,16 @@
package com.tcctyn.common.core.exception.user;
/**
* 用户错误最大次数异常类
*
* @author tcctyn
*/
public class UserPasswordRetryLimitExceedException extends UserException
{
private static final long serialVersionUID = 1L;
public UserPasswordRetryLimitExceedException(int retryLimitCount, int lockTime)
{
super("user.password.retry.limit.exceed", new Object[] { retryLimitCount, lockTime });
}
}

View File

@ -0,0 +1,24 @@
package com.tcctyn.common.core.filter;
import com.alibaba.fastjson2.filter.SimplePropertyPreFilter;
/**
* 排除JSON敏感属性
*
* @author tcctyn
*/
public class PropertyPreExcludeFilter extends SimplePropertyPreFilter
{
public PropertyPreExcludeFilter()
{
}
public PropertyPreExcludeFilter addExcludes(String... filters)
{
for (int i = 0; i < filters.length; i++)
{
this.getExcludes().add(filters[i]);
}
return this;
}
}

View File

@ -0,0 +1,48 @@
package com.tcctyn.common.core.filter;
import com.tcctyn.common.core.utils.StringUtils;
import org.springframework.http.MediaType;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
/**
* Repeatable 过滤器
*
* @author tcctyn
*/
public class RepeatableFilter implements Filter
{
@Override
public void init(FilterConfig filterConfig) throws ServletException
{
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException
{
ServletRequest requestWrapper = null;
if (request instanceof HttpServletRequest
&& StringUtils.startsWithIgnoreCase(request.getContentType(), MediaType.APPLICATION_JSON_VALUE))
{
requestWrapper = new RepeatedlyRequestWrapper((HttpServletRequest) request, response);
}
if (null == requestWrapper)
{
chain.doFilter(request, response);
}
else
{
chain.doFilter(requestWrapper, response);
}
}
@Override
public void destroy()
{
}
}

View File

@ -0,0 +1,77 @@
package com.tcctyn.common.core.filter;
import com.tcctyn.common.core.constant.Constants;
import com.tcctyn.common.core.utils.http.HttpHelper;
import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
/**
* 构建可重复读取inputStream的request
*
* @author tcctyn
*/
public class RepeatedlyRequestWrapper extends HttpServletRequestWrapper
{
private final byte[] body;
public RepeatedlyRequestWrapper(HttpServletRequest request, ServletResponse response) throws IOException
{
super(request);
request.setCharacterEncoding(Constants.UTF8);
response.setCharacterEncoding(Constants.UTF8);
body = HttpHelper.getBodyString(request).getBytes(Constants.UTF8);
}
@Override
public BufferedReader getReader() throws IOException
{
return new BufferedReader(new InputStreamReader(getInputStream()));
}
@Override
public ServletInputStream getInputStream() throws IOException
{
final ByteArrayInputStream bais = new ByteArrayInputStream(body);
return new ServletInputStream()
{
@Override
public int read() throws IOException
{
return bais.read();
}
@Override
public int available() throws IOException
{
return body.length;
}
@Override
public boolean isFinished()
{
return false;
}
@Override
public boolean isReady()
{
return false;
}
@Override
public void setReadListener(ReadListener readListener)
{
}
};
}
}

View File

@ -0,0 +1,71 @@
package com.tcctyn.common.core.filter;
import com.tcctyn.common.core.enums.HttpMethod;
import com.tcctyn.common.core.utils.StringUtils;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
/**
* 防止XSS攻击的过滤器
*
* @author tcctyn
*/
public class XssFilter implements Filter
{
/**
* 排除链接
*/
public List<String> excludes = new ArrayList<>();
@Override
public void init(FilterConfig filterConfig) throws ServletException
{
String tempExcludes = filterConfig.getInitParameter("excludes");
if (StringUtils.isNotEmpty(tempExcludes))
{
String[] urls = tempExcludes.split(",");
for (String url : urls)
{
excludes.add(url);
}
}
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException
{
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse resp = (HttpServletResponse) response;
if (handleExcludeURL(req, resp))
{
chain.doFilter(request, response);
return;
}
XssHttpServletRequestWrapper xssRequest = new XssHttpServletRequestWrapper((HttpServletRequest) request);
chain.doFilter(xssRequest, response);
}
private boolean handleExcludeURL(HttpServletRequest request, HttpServletResponse response)
{
String url = request.getServletPath();
String method = request.getMethod();
// GET DELETE 不过滤
if (method == null || HttpMethod.GET.matches(method) || HttpMethod.DELETE.matches(method))
{
return true;
}
return StringUtils.matches(url, excludes);
}
@Override
public void destroy()
{
}
}

View File

@ -0,0 +1,112 @@
package com.tcctyn.common.core.filter;
import com.tcctyn.common.core.utils.StringUtils;
import com.tcctyn.common.core.utils.html.EscapeUtil;
import org.apache.commons.io.IOUtils;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.ByteArrayInputStream;
import java.io.IOException;
/**
* XSS过滤处理
*
* @author tcctyn
*/
public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper
{
/**
* @param request
*/
public XssHttpServletRequestWrapper(HttpServletRequest request)
{
super(request);
}
@Override
public String[] getParameterValues(String name)
{
String[] values = super.getParameterValues(name);
if (values != null)
{
int length = values.length;
String[] escapesValues = new String[length];
for (int i = 0; i < length; i++)
{
// 防xss攻击和过滤前后空格
escapesValues[i] = EscapeUtil.clean(values[i]).trim();
}
return escapesValues;
}
return super.getParameterValues(name);
}
@Override
public ServletInputStream getInputStream() throws IOException
{
// 非json类型直接返回
if (!isJsonRequest())
{
return super.getInputStream();
}
// 为空直接返回
String json = IOUtils.toString(super.getInputStream(), "utf-8");
if (StringUtils.isEmpty(json))
{
return super.getInputStream();
}
// xss过滤
json = EscapeUtil.clean(json).trim();
byte[] jsonBytes = json.getBytes("utf-8");
final ByteArrayInputStream bis = new ByteArrayInputStream(jsonBytes);
return new ServletInputStream()
{
@Override
public boolean isFinished()
{
return true;
}
@Override
public boolean isReady()
{
return true;
}
@Override
public int available() throws IOException
{
return jsonBytes.length;
}
@Override
public void setReadListener(ReadListener readListener)
{
}
@Override
public int read() throws IOException
{
return bis.read();
}
};
}
/**
* 是否是Json请求
*
* @param request
*/
public boolean isJsonRequest()
{
String header = super.getHeader(HttpHeaders.CONTENT_TYPE);
return StringUtils.startsWithIgnoreCase(header, MediaType.APPLICATION_JSON_VALUE);
}
}

View File

@ -0,0 +1,265 @@
package com.tcctyn.common.core.redis;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.BoundSetOperations;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Component;
import java.util.*;
import java.util.concurrent.TimeUnit;
/**
* spring redis 工具类
*
* @author tcctyn
**/
@SuppressWarnings(value = { "unchecked", "rawtypes" })
@Component
public class RedisCache
{
@Autowired
public RedisTemplate redisTemplate;
/**
* 缓存基本的对象IntegerString实体类等
*
* @param key 缓存的键值
* @param value 缓存的值
*/
public <T> void setCacheObject(final String key, final T value)
{
redisTemplate.opsForValue().set(key, value);
}
/**
* 缓存基本的对象IntegerString实体类等
*
* @param key 缓存的键值
* @param value 缓存的值
* @param timeout 时间
* @param timeUnit 时间颗粒度
*/
public <T> void setCacheObject(final String key, final T value, final Integer timeout, final TimeUnit timeUnit)
{
redisTemplate.opsForValue().set(key, value, timeout, timeUnit);
}
/**
* 设置有效时间
*
* @param key Redis键
* @param timeout 超时时间
* @return true=设置成功false=设置失败
*/
public boolean expire(final String key, final long timeout)
{
return expire(key, timeout, TimeUnit.SECONDS);
}
/**
* 设置有效时间
*
* @param key Redis键
* @param timeout 超时时间
* @param unit 时间单位
* @return true=设置成功false=设置失败
*/
public boolean expire(final String key, final long timeout, final TimeUnit unit)
{
return redisTemplate.expire(key, timeout, unit);
}
/**
* 获取有效时间
*
* @param key Redis键
* @return 有效时间
*/
public long getExpire(final String key)
{
return redisTemplate.getExpire(key);
}
/**
* 判断 key是否存在
*
* @param key
* @return true 存在 false不存在
*/
public Boolean hasKey(String key)
{
return redisTemplate.hasKey(key);
}
/**
* 获得缓存的基本对象
*
* @param key 缓存键值
* @return 缓存键值对应的数据
*/
public <T> T getCacheObject(final String key)
{
ValueOperations<String, T> operation = redisTemplate.opsForValue();
return operation.get(key);
}
/**
* 删除单个对象
*
* @param key
*/
public boolean deleteObject(final String key)
{
return redisTemplate.delete(key);
}
/**
* 删除集合对象
*
* @param collection 多个对象
* @return
*/
public boolean deleteObject(final Collection collection)
{
return redisTemplate.delete(collection) > 0;
}
/**
* 缓存List数据
*
* @param key 缓存的键值
* @param dataList 待缓存的List数据
* @return 缓存的对象
*/
public <T> long setCacheList(final String key, final List<T> dataList)
{
Long count = redisTemplate.opsForList().rightPushAll(key, dataList);
return count == null ? 0 : count;
}
/**
* 获得缓存的list对象
*
* @param key 缓存的键值
* @return 缓存键值对应的数据
*/
public <T> List<T> getCacheList(final String key)
{
return redisTemplate.opsForList().range(key, 0, -1);
}
/**
* 缓存Set
*
* @param key 缓存键值
* @param dataSet 缓存的数据
* @return 缓存数据的对象
*/
public <T> BoundSetOperations<String, T> setCacheSet(final String key, final Set<T> dataSet)
{
BoundSetOperations<String, T> setOperation = redisTemplate.boundSetOps(key);
Iterator<T> it = dataSet.iterator();
while (it.hasNext())
{
setOperation.add(it.next());
}
return setOperation;
}
/**
* 获得缓存的set
*
* @param key
* @return
*/
public <T> Set<T> getCacheSet(final String key)
{
return redisTemplate.opsForSet().members(key);
}
/**
* 缓存Map
*
* @param key
* @param dataMap
*/
public <T> void setCacheMap(final String key, final Map<String, T> dataMap)
{
if (dataMap != null) {
redisTemplate.opsForHash().putAll(key, dataMap);
}
}
/**
* 获得缓存的Map
*
* @param key
* @return
*/
public <T> Map<String, T> getCacheMap(final String key)
{
return redisTemplate.opsForHash().entries(key);
}
/**
* 往Hash中存入数据
*
* @param key Redis键
* @param hKey Hash键
* @param value
*/
public <T> void setCacheMapValue(final String key, final String hKey, final T value)
{
redisTemplate.opsForHash().put(key, hKey, value);
}
/**
* 获取Hash中的数据
*
* @param key Redis键
* @param hKey Hash键
* @return Hash中的对象
*/
public <T> T getCacheMapValue(final String key, final String hKey)
{
HashOperations<String, String, T> opsForHash = redisTemplate.opsForHash();
return opsForHash.get(key, hKey);
}
/**
* 获取多个Hash中的数据
*
* @param key Redis键
* @param hKeys Hash键集合
* @return Hash对象集合
*/
public <T> List<T> getMultiCacheMapValue(final String key, final Collection<Object> hKeys)
{
return redisTemplate.opsForHash().multiGet(key, hKeys);
}
/**
* 删除Hash中的某条数据
*
* @param key Redis键
* @param hKey Hash键
* @return 是否成功
*/
public boolean deleteCacheMapValue(final String key, final String hKey)
{
return redisTemplate.opsForHash().delete(key, hKey) > 0;
}
/**
* 获得缓存的基本对象列表
*
* @param pattern 字符串前缀
* @return 对象列表
*/
public Collection<String> keys(final String pattern)
{
return redisTemplate.keys(pattern);
}
}

View File

@ -0,0 +1,100 @@
package com.tcctyn.common.core.utils;
import javax.crypto.*;
import javax.crypto.spec.SecretKeySpec;
import java.io.UnsupportedEncodingException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
public class AESUtil {
// 加密密码可以为任意字符串
private static final String password_str = "中华名族的伟大复兴¥¥¥";
/**
* AES加密字符串
*
* @param content 需要被加密的字符串
* @return 密文
*/
public static String encrypt(String content) {
try {
KeyGenerator kgen = KeyGenerator.getInstance("AES");// 创建AES的Key生产者
kgen.init(128, new SecureRandom(password_str.getBytes()));// 利用用户密码作为随机数初始化出
//加密没关系SecureRandom是生成安全随机数序列password.getBytes()是种子只要种子相同序列就一样所以解密只要有password就行
SecretKey secretKey = kgen.generateKey();// 根据用户密码生成一个密钥
byte[] enCodeFormat = secretKey.getEncoded();// 返回基本编码格式的密钥如果此密钥不支持编码则返回
SecretKeySpec key = new SecretKeySpec(enCodeFormat, "AES");// 转换为AES专用密钥
Cipher cipher = Cipher.getInstance("AES");// 创建密码器
byte[] byteContent = content.getBytes("utf-8");
cipher.init(Cipher.ENCRYPT_MODE, key);// 初始化为加密模式的密码器
byte[] result = cipher.doFinal(byteContent);// 加密
return ParseSystemUtil.parseByte2HexStr(result); //加密后的16进制
} catch (NoSuchPaddingException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
}
return null;
}
/**
* 解密AES加密过的字符串
*
* @param hexStr AES加密过过的内容
* @return 明文
*/
public static byte[] decrypt(String hexStr) {
try {
// 16进制转换为2进制
byte[] content = ParseSystemUtil.parseHexStr2Byte(hexStr);
KeyGenerator kgen = KeyGenerator.getInstance("AES");// 创建AES的Key生产者
kgen.init(128, new SecureRandom(password_str.getBytes()));
SecretKey secretKey = kgen.generateKey();// 根据用户密码生成一个密钥
byte[] enCodeFormat = secretKey.getEncoded();// 返回基本编码格式的密钥
SecretKeySpec key = new SecretKeySpec(enCodeFormat, "AES");// 转换为AES专用密钥
Cipher cipher = Cipher.getInstance("AES");// 创建密码器
cipher.init(Cipher.DECRYPT_MODE, key);// 初始化为解密模式的密码器
byte[] result = cipher.doFinal(content); //解密后的二进制
return result; // 明文
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
}
return null;
}
public static void main(String[] args) throws Exception {
String content = "密码1993";
String password = "中华名族的伟大复兴";
System.out.println("需要加密的内容:" + content);
String encrypt = encrypt(content);
System.out.println(encrypt);
// System.out.println("加密后的2进制密文" + new String(encrypt));
// String hexStr = ParseSystemUtil.parseByte2HexStr(encrypt);
// System.out.println("加密后的16进制密文:" + hexStr);
// byte[] byte2 = ParseSystemUtil.parseHexStr2Byte(hexStr);
// System.out.println("加密后的2进制密文" + new String(byte2));
byte[] decrypt = decrypt(encrypt);
System.out.println("解密后的内容:" + new String(decrypt, "utf-8"));
}
}

View File

@ -0,0 +1,114 @@
package com.tcctyn.common.core.utils;
import java.math.BigDecimal;
import java.math.RoundingMode;
/**
* 精确的浮点数运算
*
* @author tcctyn
*/
public class Arith
{
/** 默认除法运算精度 */
private static final int DEF_DIV_SCALE = 10;
/** 这个类不能实例化 */
private Arith()
{
}
/**
* 提供精确的加法运算
* @param v1 被加数
* @param v2 加数
* @return 两个参数的和
*/
public static double add(double v1, double v2)
{
BigDecimal b1 = new BigDecimal(Double.toString(v1));
BigDecimal b2 = new BigDecimal(Double.toString(v2));
return b1.add(b2).doubleValue();
}
/**
* 提供精确的减法运算
* @param v1 被减数
* @param v2 减数
* @return 两个参数的差
*/
public static double sub(double v1, double v2)
{
BigDecimal b1 = new BigDecimal(Double.toString(v1));
BigDecimal b2 = new BigDecimal(Double.toString(v2));
return b1.subtract(b2).doubleValue();
}
/**
* 提供精确的乘法运算
* @param v1 被乘数
* @param v2 乘数
* @return 两个参数的积
*/
public static double mul(double v1, double v2)
{
BigDecimal b1 = new BigDecimal(Double.toString(v1));
BigDecimal b2 = new BigDecimal(Double.toString(v2));
return b1.multiply(b2).doubleValue();
}
/**
* 提供相对精确的除法运算当发生除不尽的情况时精确到
* 小数点以后10位以后的数字四舍五入
* @param v1 被除数
* @param v2 除数
* @return 两个参数的商
*/
public static double div(double v1, double v2)
{
return div(v1, v2, DEF_DIV_SCALE);
}
/**
* 提供相对精确的除法运算当发生除不尽的情况时由scale参数指
* 定精度以后的数字四舍五入
* @param v1 被除数
* @param v2 除数
* @param scale 表示表示需要精确到小数点以后几位
* @return 两个参数的商
*/
public static double div(double v1, double v2, int scale)
{
if (scale < 0)
{
throw new IllegalArgumentException(
"The scale must be a positive integer or zero");
}
BigDecimal b1 = new BigDecimal(Double.toString(v1));
BigDecimal b2 = new BigDecimal(Double.toString(v2));
if (b1.compareTo(BigDecimal.ZERO) == 0)
{
return BigDecimal.ZERO.doubleValue();
}
return b1.divide(b2, scale, RoundingMode.HALF_UP).doubleValue();
}
/**
* 提供精确的小数位四舍五入处理
* @param v 需要四舍五入的数字
* @param scale 小数点后保留几位
* @return 四舍五入后的结果
*/
public static double round(double v, int scale)
{
if (scale < 0)
{
throw new IllegalArgumentException(
"The scale must be a positive integer or zero");
}
BigDecimal b = new BigDecimal(Double.toString(v));
BigDecimal one = BigDecimal.ONE;
return b.divide(one, scale, RoundingMode.HALF_UP).doubleValue();
}
}

View File

@ -0,0 +1,49 @@
package com.tcctyn.common.core.utils;
/**
* 脱敏工具类
*
* @author tcctyn
*/
public class DesensitizedUtil
{
/**
* 密码的全部字符都用*代替比如******
*
* @param password 密码
* @return 脱敏后的密码
*/
public static String password(String password)
{
if (StringUtils.isBlank(password))
{
return StringUtils.EMPTY;
}
return StringUtils.repeat('*', password.length());
}
/**
* 车牌中间用*代替如果是错误的车牌不处理
*
* @param carLicense 完整的车牌号
* @return 脱敏后的车牌
*/
public static String carLicense(String carLicense)
{
if (StringUtils.isBlank(carLicense))
{
return StringUtils.EMPTY;
}
// 普通车牌
if (carLicense.length() == 7)
{
carLicense = StringUtils.hide(carLicense, 3, 6);
}
else if (carLicense.length() == 8)
{
// 新能源车牌
carLicense = StringUtils.hide(carLicense, 3, 7);
}
return carLicense;
}
}

View File

@ -0,0 +1,239 @@
package com.tcctyn.common.core.utils;
import com.alibaba.fastjson2.JSONArray;
import com.tcctyn.common.core.constant.CacheConstants;
import com.tcctyn.common.core.web.domain.entity.SysDictData;
import com.tcctyn.common.core.redis.RedisCache;
import java.util.Collection;
import java.util.List;
/**
* 字典工具类
*
* @author tcctyn
*/
public class DictUtils
{
/**
* 分隔符
*/
public static final String SEPARATOR = ",";
/**
* 设置字典缓存
*
* @param key 参数键
* @param dictDatas 字典数据列表
*/
public static void setDictCache(String key, List<SysDictData> dictDatas)
{
SpringUtils.getBean(RedisCache.class).setCacheObject(getCacheKey(key), dictDatas);
}
/**
* 获取字典缓存
*
* @param key 参数键
* @return dictDatas 字典数据列表
*/
public static List<SysDictData> getDictCache(String key)
{
JSONArray arrayCache = SpringUtils.getBean(RedisCache.class).getCacheObject(getCacheKey(key));
if (StringUtils.isNotNull(arrayCache))
{
return arrayCache.toList(SysDictData.class);
}
return null;
}
/**
* 根据字典类型和字典值获取字典标签
*
* @param dictType 字典类型
* @param dictValue 字典值
* @return 字典标签
*/
public static String getDictLabel(String dictType, String dictValue)
{
if (StringUtils.isEmpty(dictValue))
{
return StringUtils.EMPTY;
}
return getDictLabel(dictType, dictValue, SEPARATOR);
}
/**
* 根据字典类型和字典标签获取字典值
*
* @param dictType 字典类型
* @param dictLabel 字典标签
* @return 字典值
*/
public static String getDictValue(String dictType, String dictLabel)
{
if (StringUtils.isEmpty(dictLabel))
{
return StringUtils.EMPTY;
}
return getDictValue(dictType, dictLabel, SEPARATOR);
}
/**
* 根据字典类型和字典值获取字典标签
*
* @param dictType 字典类型
* @param dictValue 字典值
* @param separator 分隔符
* @return 字典标签
*/
public static String getDictLabel(String dictType, String dictValue, String separator)
{
StringBuilder propertyString = new StringBuilder();
List<SysDictData> datas = getDictCache(dictType);
if (StringUtils.isNull(datas))
{
return StringUtils.EMPTY;
}
if (StringUtils.containsAny(separator, dictValue))
{
for (SysDictData dict : datas)
{
for (String value : dictValue.split(separator))
{
if (value.equals(dict.getDictValue()))
{
propertyString.append(dict.getDictLabel()).append(separator);
break;
}
}
}
}
else
{
for (SysDictData dict : datas)
{
if (dictValue.equals(dict.getDictValue()))
{
return dict.getDictLabel();
}
}
}
return StringUtils.stripEnd(propertyString.toString(), separator);
}
/**
* 根据字典类型和字典标签获取字典值
*
* @param dictType 字典类型
* @param dictLabel 字典标签
* @param separator 分隔符
* @return 字典值
*/
public static String getDictValue(String dictType, String dictLabel, String separator)
{
StringBuilder propertyString = new StringBuilder();
List<SysDictData> datas = getDictCache(dictType);
if (StringUtils.isNull(datas))
{
return StringUtils.EMPTY;
}
if (StringUtils.containsAny(separator, dictLabel))
{
for (SysDictData dict : datas)
{
for (String label : dictLabel.split(separator))
{
if (label.equals(dict.getDictLabel()))
{
propertyString.append(dict.getDictValue()).append(separator);
break;
}
}
}
}
else
{
for (SysDictData dict : datas)
{
if (dictLabel.equals(dict.getDictLabel()))
{
return dict.getDictValue();
}
}
}
return StringUtils.stripEnd(propertyString.toString(), separator);
}
/**
* 根据字典类型获取字典所有值
*
* @param dictType 字典类型
* @return 字典值
*/
public static String getDictValues(String dictType)
{
StringBuilder propertyString = new StringBuilder();
List<SysDictData> datas = getDictCache(dictType);
if (StringUtils.isNull(datas))
{
return StringUtils.EMPTY;
}
for (SysDictData dict : datas)
{
propertyString.append(dict.getDictValue()).append(SEPARATOR);
}
return StringUtils.stripEnd(propertyString.toString(), SEPARATOR);
}
/**
* 根据字典类型获取字典所有标签
*
* @param dictType 字典类型
* @return 字典值
*/
public static String getDictLabels(String dictType)
{
StringBuilder propertyString = new StringBuilder();
List<SysDictData> datas = getDictCache(dictType);
if (StringUtils.isNull(datas))
{
return StringUtils.EMPTY;
}
for (SysDictData dict : datas)
{
propertyString.append(dict.getDictLabel()).append(SEPARATOR);
}
return StringUtils.stripEnd(propertyString.toString(), SEPARATOR);
}
/**
* 删除指定字典缓存
*
* @param key 字典键
*/
public static void removeDictCache(String key)
{
SpringUtils.getBean(RedisCache.class).deleteObject(getCacheKey(key));
}
/**
* 清空字典缓存
*/
public static void clearDictCache()
{
Collection<String> keys = SpringUtils.getBean(RedisCache.class).keys(CacheConstants.SYS_DICT_KEY + "*");
SpringUtils.getBean(RedisCache.class).deleteObject(keys);
}
/**
* 设置cache key
*
* @param configKey 参数键
* @return 缓存键key
*/
public static String getCacheKey(String configKey)
{
return CacheConstants.SYS_DICT_KEY + configKey;
}
}

View File

@ -0,0 +1,32 @@
package com.tcctyn.common.core.utils;
/**
* 距离计算工具类
*/
public class DistanceCalculationUtil {
// 地球半径单位千米
private static final double EARTH_RADIUS_KM = 6371.0;
public static double calculateDistance(String lon1, String lat1, String lon2, String lat2) {
// 将角度转换为弧度
double lat1Rad = Math.toRadians(Double.valueOf(lat1));
double lon1Rad = Math.toRadians(Double.valueOf(lon1));
double lat2Rad = Math.toRadians(Double.valueOf(lat2));
double lon2Rad = Math.toRadians(Double.valueOf(lon2));
// 计算纬度和经度的差值
double deltaLat = lat2Rad - lat1Rad;
double deltaLon = lon2Rad - lon1Rad;
// 应用Haversine公式
double a = Math.pow(Math.sin(deltaLat / 2), 2)
+ Math.cos(lat1Rad) * Math.cos(lat2Rad)
* Math.pow(Math.sin(deltaLon / 2), 2);
double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
// 计算距离
return EARTH_RADIUS_KM * c;
}
}

View File

@ -0,0 +1,171 @@
package com.tcctyn.common.core.utils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import java.io.*;
import java.util.concurrent.TimeUnit;
/**
* @author songguoqiang
* @date 2025年04月17日 22:42:13
*/
@Component
public class FFmpegExecutor {
private Process ffmpegProcess;
private OutputStream ffmpegInput;
private static final Logger logger = LoggerFactory.getLogger(FFmpegExecutor.class);
public void start(String format, String outputUrl, String rtspUrl) throws IOException {
// 构建 FFmpeg 命令
ProcessBuilder pb = new ProcessBuilder(
"ffmpeg",
"-i", rtspUrl,
"-c:v", "copy",
"-c:a", "aac",
"-ar", "44100",
"-f", format,
outputUrl
);
// 启动进程
ffmpegProcess = pb.start();
ffmpegInput = ffmpegProcess.getOutputStream();
// 异步读取输出日志
new Thread(() -> {
try (BufferedReader reader = new BufferedReader(
new InputStreamReader(ffmpegProcess.getInputStream()))) {
String line;
while ((line = reader.readLine()) != null) {
logger.info("[FFmpeg] {}", line);
}
} catch (IOException e) {
logger.error("Failed to read FFmpeg output: {}", e.getMessage());
}
}).start();
}
public void writeFrame(byte[] frameData) throws IOException {
ffmpegInput.write(frameData);
ffmpegInput.flush();
}
public void stop() {
if (ffmpegProcess != null) {
try {
// 1. 尝试优雅退出发送 'q' 命令
if (ffmpegInput != null) {
ffmpegInput.write("q\n".getBytes());
ffmpegInput.flush();
}
} catch (IOException e) {
logger.warn("Failed to send exit command: {}", e.getMessage());
}
// 2. 关闭输入流
try {
if (ffmpegInput != null) {
ffmpegInput.close();
}
} catch (IOException e) {
logger.error("Error closing input stream: {}", e.getMessage());
}
// 3. 销毁进程
if (ffmpegProcess.isAlive()) {
ffmpegProcess.destroy();
try {
if (!ffmpegProcess.waitFor(5, TimeUnit.SECONDS)) {
ffmpegProcess.destroyForcibly();
logger.warn("FFmpeg process was forcibly terminated");
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
logger.error("Interrupted while waiting for termination: {}", e.getMessage());
}
}
ffmpegProcess = null; // 清除引用
}
}
private void readProcessOutput(InputStream inputStream) {
try (BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream))) {
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
//package com.tcctyn.common.utils;
//
//import com.tcctyn.common.annotation.Anonymous;
//import org.springframework.stereotype.Component;
//
//import java.io.IOException;
//import java.io.OutputStream;
//import java.nio.ByteBuffer;
//import java.util.ArrayList;
//import java.util.List;
//
///**
// * @author Jason
// * @date 2025年03月26日 22:42:13
// */
//@Component
//
//public class FFmpegExecutor {
//
// private Process ffmpegProcess;
// private OutputStream ffmpegInput;
// public void start(String format, String outputUrl, byte[] sps, byte[] pps) throws IOException {
// List<String> command = new ArrayList<>();
// command.add("ffmpeg");
// command.add("-y");
// command.add("-f"); command.add("h264");
// command.add("-i"); command.add("pipe:0");
// command.add("-c:v"); command.add("copy"); // 直接拷贝视频流
// command.add("-f"); command.add(format);
// command.add("-flvflags"); command.add("no_duration_filesize");
// command.add("-movflags"); command.add("faststart");
// command.add("-preset"); command.add("ultrafast");
// command.add("-tune"); command.add("zerolatency");
// command.add("-g"); command.add("50"); // GOP长度
// command.add("-keyint_min"); command.add("25"); // 最小关键帧间隔
// command.add("-x264-params"); command.add("scenecut=0:open_gop=0:min-keyint=25:keyint=50");
// command.add(outputUrl);
//
// ProcessBuilder pb = new ProcessBuilder(command);
// pb.redirectErrorStream(true);
// ffmpegProcess = pb.start();
// ffmpegInput = ffmpegProcess.getOutputStream();
//
// // 写入extradata
// writeExtradata(sps, pps);
// }
//
// public void writeFrame(byte[] frameData) throws IOException {
// ffmpegInput.write(frameData);
// ffmpegInput.flush();
// }
//
// public void stop() {
// try {
// if (ffmpegInput != null) {
// ffmpegInput.close();
// }
// if (ffmpegProcess != null) {
// ffmpegProcess.destroyForcibly();
// }
// } catch (IOException e) {
// e.printStackTrace();
// }
// }
//}

View File

@ -0,0 +1,18 @@
package com.tcctyn.common.core.utils;
/**
* 处理并记录日志文件
*
* @author tcctyn
*/
public class LogUtils
{
public static String getBlock(Object msg)
{
if (msg == null)
{
msg = "";
}
return "[" + msg.toString() + "]";
}
}

View File

@ -0,0 +1,25 @@
package com.tcctyn.common.core.utils;
import org.springframework.context.MessageSource;
import org.springframework.context.i18n.LocaleContextHolder;
/**
* 获取i18n资源文件
*
* @author tcctyn
*/
public class MessageUtils
{
/**
* 根据消息键和参数 获取消息 委托给spring messageSource
*
* @param code 消息键
* @param args 参数
* @return 获取国际化翻译值
*/
public static String message(String code, Object... args)
{
MessageSource messageSource = SpringUtils.getBean(MessageSource.class);
return messageSource.getMessage(code, args, LocaleContextHolder.getLocale());
}
}

View File

@ -0,0 +1,40 @@
package com.tcctyn.common.core.utils;
/**
* 进制转换工具类
*
*/
public class ParseSystemUtil {
/**将二进制转换成16进制
* @param buf
* @return
*/
public static String parseByte2HexStr(byte buf[]) {
StringBuffer sb = new StringBuffer();
for (int i = 0; i < buf.length; i++) {
String hex = Integer.toHexString(buf[i] & 0xFF);
if (hex.length() == 1) {
hex = '0' + hex;
}
sb.append(hex.toUpperCase());
}
return sb.toString();
}
/**将16进制转换为二进制
* @param hexStr
* @return
*/
public static byte[] parseHexStr2Byte(String hexStr) {
if (hexStr.length() < 1)
return null;
byte[] result = new byte[hexStr.length()/2];
for (int i = 0;i< hexStr.length()/2; i++) {
int high = Integer.parseInt(hexStr.substring(i*2, i*2+1), 16);
int low = Integer.parseInt(hexStr.substring(i*2+1, i*2+2), 16);
result[i] = (byte) (high * 16 + low);
}
return result;
}
}

View File

@ -0,0 +1,179 @@
package com.tcctyn.common.core.utils;
import com.tcctyn.common.core.constant.Constants;
import com.tcctyn.common.core.constant.HttpStatus;
import com.tcctyn.common.core.web.domain.entity.SysRole;
import com.tcctyn.common.core.web.domain.model.LoginUser;
import com.tcctyn.common.core.exception.ServiceException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.util.PatternMatchUtils;
import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;
/**
* 安全服务工具类
*
* @author tcctyn
*/
public class SecurityUtils
{
/**
* 用户ID
**/
public static Long getUserId()
{
try
{
return getLoginUser().getUserId();
}
catch (Exception e)
{
throw new ServiceException("获取用户ID异常", HttpStatus.UNAUTHORIZED);
}
}
/**
* 获取部门ID
**/
public static Long getDeptId()
{
try
{
return getLoginUser().getDeptId();
}
catch (Exception e)
{
throw new ServiceException("获取部门ID异常", HttpStatus.UNAUTHORIZED);
}
}
/**
* 获取用户账户
**/
public static String getUsername()
{
try
{
return getLoginUser().getUsername();
}
catch (Exception e)
{
throw new ServiceException("获取用户账户异常", HttpStatus.UNAUTHORIZED);
}
}
/**
* 获取用户
**/
public static LoginUser getLoginUser()
{
try
{
return (LoginUser) getAuthentication().getPrincipal();
}
catch (Exception e)
{
throw new ServiceException("获取用户信息异常", HttpStatus.UNAUTHORIZED);
}
}
/**
* 获取Authentication
*/
public static Authentication getAuthentication()
{
return SecurityContextHolder.getContext().getAuthentication();
}
/**
* 生成BCryptPasswordEncoder密码
*
* @param password 密码
* @return 加密字符串
*/
public static String encryptPassword(String password)
{
BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
return passwordEncoder.encode(password);
}
/**
* 判断密码是否相同
*
* @param rawPassword 真实密码
* @param encodedPassword 加密后字符
* @return 结果
*/
public static boolean matchesPassword(String rawPassword, String encodedPassword)
{
BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
return passwordEncoder.matches(rawPassword, encodedPassword);
}
/**
* 是否为管理员
*
* @param userId 用户ID
* @return 结果
*/
public static boolean isAdmin(Long userId)
{
return userId != null && 1L == userId;
}
/**
* 验证用户是否具备某权限
*
* @param permission 权限字符串
* @return 用户是否具备某权限
*/
public static boolean hasPermi(String permission)
{
return hasPermi(getLoginUser().getPermissions(), permission);
}
/**
* 判断是否包含权限
*
* @param authorities 权限列表
* @param permission 权限字符串
* @return 用户是否具备某权限
*/
public static boolean hasPermi(Collection<String> authorities, String permission)
{
return authorities.stream().filter(StringUtils::hasText)
.anyMatch(x -> Constants.ALL_PERMISSION.equals(x) || PatternMatchUtils.simpleMatch(x, permission));
}
/**
* 验证用户是否拥有某个角色
*
* @param role 角色标识
* @return 用户是否具备某角色
*/
public static boolean hasRole(String role)
{
List<SysRole> roleList = getLoginUser().getUser().getRoles();
Collection<String> roles = roleList.stream().map(SysRole::getRoleKey).collect(Collectors.toSet());
return hasRole(roles, role);
}
/**
* 判断是否包含角色
*
* @param roles 角色列表
* @param role 角色
* @return 用户是否具备某角色权限
*/
public static boolean hasRole(Collection<String> roles, String role)
{
return roles.stream().filter(StringUtils::hasText)
.anyMatch(x -> Constants.SUPER_ADMIN.equals(x) || PatternMatchUtils.simpleMatch(x, role));
}
}

View File

@ -0,0 +1,59 @@
package com.tcctyn.common.core.utils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.concurrent.Semaphore;
/**
* 信号量相关处理
*
* @author ruoyi
*/
public class SemaphoreUtils
{
/**
* SemaphoreUtils 日志控制器
*/
private static final Logger LOGGER = LoggerFactory.getLogger(SemaphoreUtils.class);
/**
* 获取信号量
*
* @param semaphore
* @return
*/
public static boolean tryAcquire(Semaphore semaphore)
{
boolean flag = false;
try
{
flag = semaphore.tryAcquire();
}
catch (Exception e)
{
LOGGER.error("获取信号量异常", e);
}
return flag;
}
/**
* 释放信号量
*
* @param semaphore
*/
public static void release(Semaphore semaphore)
{
try
{
semaphore.release();
}
catch (Exception e)
{
LOGGER.error("释放信号量异常", e);
}
}
}

View File

@ -0,0 +1,96 @@
package com.tcctyn.common.core.utils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.concurrent.*;
/**
* 线程相关工具类.
*
* @author tcctyn
*/
public class Threads
{
private static final Logger logger = LoggerFactory.getLogger(Threads.class);
/**
* sleep等待,单位为毫秒
*/
public static void sleep(long milliseconds)
{
try
{
Thread.sleep(milliseconds);
}
catch (InterruptedException e)
{
return;
}
}
/**
* 停止线程池
* 先使用shutdown, 停止接收新任务并尝试完成所有已存在任务.
* 如果超时, 则调用shutdownNow, 取消在workQueue中Pending的任务,并中断所有阻塞函数.
* 如果仍然超時則強制退出.
* 另对在shutdown时线程本身被调用中断做了处理.
*/
public static void shutdownAndAwaitTermination(ExecutorService pool)
{
if (pool != null && !pool.isShutdown())
{
pool.shutdown();
try
{
if (!pool.awaitTermination(120, TimeUnit.SECONDS))
{
pool.shutdownNow();
if (!pool.awaitTermination(120, TimeUnit.SECONDS))
{
logger.info("Pool did not terminate");
}
}
}
catch (InterruptedException ie)
{
pool.shutdownNow();
Thread.currentThread().interrupt();
}
}
}
/**
* 打印线程异常信息
*/
public static void printException(Runnable r, Throwable t)
{
if (t == null && r instanceof Future<?>)
{
try
{
Future<?> future = (Future<?>) r;
if (future.isDone())
{
future.get();
}
}
catch (CancellationException ce)
{
t = ce;
}
catch (ExecutionException ee)
{
t = ee.getCause();
}
catch (InterruptedException ie)
{
Thread.currentThread().interrupt();
}
}
if (t != null)
{
logger.error(t.getMessage(), t);
}
}
}

View File

@ -0,0 +1,233 @@
package com.tcctyn.common.core.utils.file;
import com.tcctyn.common.core.config.TcctynConfig;
import com.tcctyn.common.core.constant.Constants;
import com.tcctyn.common.core.exception.file.FileNameLengthLimitExceededException;
import com.tcctyn.common.core.exception.file.FileSizeLimitExceededException;
import com.tcctyn.common.core.exception.file.InvalidExtensionException;
import com.tcctyn.common.core.utils.DateUtils;
import com.tcctyn.common.core.utils.StringUtils;
import com.tcctyn.common.core.utils.uuid.Seq;
import org.apache.commons.io.FilenameUtils;
import org.springframework.web.multipart.MultipartFile;
import java.io.File;
import java.io.IOException;
import java.nio.file.Paths;
import java.util.Objects;
/**
* 文件上传工具类
*
* @author tcctyn
*/
public class FileUploadUtils
{
/**
* 默认大小 50M
*/
public static final long DEFAULT_MAX_SIZE = 50 * 1024 * 1024L;
/**
* 默认的文件名最大长度 100
*/
public static final int DEFAULT_FILE_NAME_LENGTH = 100;
/**
* 默认上传的地址
*/
private static String defaultBaseDir = TcctynConfig.getProfile();
public static void setDefaultBaseDir(String defaultBaseDir)
{
FileUploadUtils.defaultBaseDir = defaultBaseDir;
}
public static String getDefaultBaseDir()
{
return defaultBaseDir;
}
/**
* 以默认配置进行文件上传
*
* @param file 上传的文件
* @return 文件名称
* @throws Exception
*/
public static final String upload(MultipartFile file) throws IOException
{
try
{
return upload(getDefaultBaseDir(), file, MimeTypeUtils.DEFAULT_ALLOWED_EXTENSION);
}
catch (Exception e)
{
throw new IOException(e.getMessage(), e);
}
}
/**
* 根据文件路径上传
*
* @param baseDir 相对应用的基目录
* @param file 上传的文件
* @return 文件名称
* @throws IOException
*/
public static final String upload(String baseDir, MultipartFile file) throws IOException
{
try
{
return upload(baseDir, file, MimeTypeUtils.DEFAULT_ALLOWED_EXTENSION);
}
catch (Exception e)
{
throw new IOException(e.getMessage(), e);
}
}
/**
* 文件上传
*
* @param baseDir 相对应用的基目录
* @param file 上传的文件
* @param allowedExtension 上传文件类型
* @return 返回上传成功的文件名
* @throws FileSizeLimitExceededException 如果超出最大大小
* @throws FileNameLengthLimitExceededException 文件名太长
* @throws IOException 比如读写文件出错时
* @throws InvalidExtensionException 文件校验异常
*/
public static final String upload(String baseDir, MultipartFile file, String[] allowedExtension)
throws FileSizeLimitExceededException, IOException, FileNameLengthLimitExceededException,
InvalidExtensionException
{
int fileNamelength = Objects.requireNonNull(file.getOriginalFilename()).length();
if (fileNamelength > FileUploadUtils.DEFAULT_FILE_NAME_LENGTH)
{
throw new FileNameLengthLimitExceededException(FileUploadUtils.DEFAULT_FILE_NAME_LENGTH);
}
assertAllowed(file, allowedExtension);
String fileName = extractFilename(file);
String absPath = getAbsoluteFile(baseDir, fileName).getAbsolutePath();
file.transferTo(Paths.get(absPath));
return getPathFileName(baseDir, fileName);
}
/**
* 编码文件名
*/
public static final String extractFilename(MultipartFile file)
{
return StringUtils.format("{}/{}_{}.{}", DateUtils.datePath(),
FilenameUtils.getBaseName(file.getOriginalFilename()), Seq.getId(Seq.uploadSeqType), getExtension(file));
}
public static final File getAbsoluteFile(String uploadDir, String fileName) throws IOException
{
File desc = new File(uploadDir + File.separator + fileName);
if (!desc.exists())
{
if (!desc.getParentFile().exists())
{
desc.getParentFile().mkdirs();
}
}
return desc;
}
public static final String getPathFileName(String uploadDir, String fileName) throws IOException
{
int dirLastIndex = TcctynConfig.getProfile().length() + 1;
String currentDir = StringUtils.substring(uploadDir, dirLastIndex);
return Constants.RESOURCE_PREFIX + "/" + currentDir + "/" + fileName;
}
/**
* 文件大小校验
*
* @param file 上传的文件
* @return
* @throws FileSizeLimitExceededException 如果超出最大大小
* @throws InvalidExtensionException
*/
public static final void assertAllowed(MultipartFile file, String[] allowedExtension)
throws FileSizeLimitExceededException, InvalidExtensionException
{
long size = file.getSize();
if (size > DEFAULT_MAX_SIZE)
{
throw new FileSizeLimitExceededException(DEFAULT_MAX_SIZE / 1024 / 1024);
}
String fileName = file.getOriginalFilename();
String extension = getExtension(file);
if (allowedExtension != null && !isAllowedExtension(extension, allowedExtension))
{
if (allowedExtension == MimeTypeUtils.IMAGE_EXTENSION)
{
throw new InvalidExtensionException.InvalidImageExtensionException(allowedExtension, extension,
fileName);
}
else if (allowedExtension == MimeTypeUtils.FLASH_EXTENSION)
{
throw new InvalidExtensionException.InvalidFlashExtensionException(allowedExtension, extension,
fileName);
}
else if (allowedExtension == MimeTypeUtils.MEDIA_EXTENSION)
{
throw new InvalidExtensionException.InvalidMediaExtensionException(allowedExtension, extension,
fileName);
}
else if (allowedExtension == MimeTypeUtils.VIDEO_EXTENSION)
{
throw new InvalidExtensionException.InvalidVideoExtensionException(allowedExtension, extension,
fileName);
}
else
{
throw new InvalidExtensionException(allowedExtension, extension, fileName);
}
}
}
/**
* 判断MIME类型是否是允许的MIME类型
*
* @param extension
* @param allowedExtension
* @return
*/
public static final boolean isAllowedExtension(String extension, String[] allowedExtension)
{
for (String str : allowedExtension)
{
if (str.equalsIgnoreCase(extension))
{
return true;
}
}
return false;
}
/**
* 获取文件名的后缀
*
* @param file 表单文件
* @return 后缀名
*/
public static final String getExtension(MultipartFile file)
{
String extension = FilenameUtils.getExtension(file.getOriginalFilename());
if (StringUtils.isEmpty(extension))
{
extension = MimeTypeUtils.getExtension(Objects.requireNonNull(file.getContentType()));
}
return extension;
}
}

View File

@ -0,0 +1,56 @@
package com.tcctyn.common.core.utils.http;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.servlet.ServletRequest;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
/**
* 通用http工具封装
*
* @author tcctyn
*/
public class HttpHelper
{
private static final Logger LOGGER = LoggerFactory.getLogger(HttpHelper.class);
public static String getBodyString(ServletRequest request)
{
StringBuilder sb = new StringBuilder();
BufferedReader reader = null;
try (InputStream inputStream = request.getInputStream())
{
reader = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8));
String line = "";
while ((line = reader.readLine()) != null)
{
sb.append(line);
}
}
catch (IOException e)
{
LOGGER.warn("getBodyString出现问题");
}
finally
{
if (reader != null)
{
try
{
reader.close();
}
catch (IOException e)
{
LOGGER.error(ExceptionUtils.getMessage(e));
}
}
}
return sb.toString();
}
}

View File

@ -0,0 +1,266 @@
package com.tcctyn.common.core.utils.http;
import com.tcctyn.common.core.constant.Constants;
import com.tcctyn.common.core.utils.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.net.ssl.*;
import java.io.*;
import java.net.ConnectException;
import java.net.SocketTimeoutException;
import java.net.URL;
import java.net.URLConnection;
import java.nio.charset.StandardCharsets;
import java.security.cert.X509Certificate;
/**
* 通用http发送方法
*
* @author tcctyn
*/
public class HttpUtils
{
private static final Logger log = LoggerFactory.getLogger(HttpUtils.class);
/**
* 向指定 URL 发送GET方法的请求
*
* @param url 发送请求的 URL
* @return 所代表远程资源的响应结果
*/
public static String sendGet(String url)
{
return sendGet(url, StringUtils.EMPTY);
}
/**
* 向指定 URL 发送GET方法的请求
*
* @param url 发送请求的 URL
* @param param 请求参数请求参数应该是 name1=value1&name2=value2 的形式
* @return 所代表远程资源的响应结果
*/
public static String sendGet(String url, String param)
{
return sendGet(url, param, Constants.UTF8);
}
/**
* 向指定 URL 发送GET方法的请求
*
* @param url 发送请求的 URL
* @param param 请求参数请求参数应该是 name1=value1&name2=value2 的形式
* @param contentType 编码类型
* @return 所代表远程资源的响应结果
*/
public static String sendGet(String url, String param, String contentType)
{
StringBuilder result = new StringBuilder();
BufferedReader in = null;
try
{
String urlNameString = StringUtils.isNotBlank(param) ? url + "?" + param : url;
log.info("sendGet - {}", urlNameString);
URL realUrl = new URL(urlNameString);
URLConnection connection = realUrl.openConnection();
connection.setRequestProperty("accept", "*/*");
connection.setRequestProperty("connection", "Keep-Alive");
connection.setRequestProperty("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64)");
connection.connect();
in = new BufferedReader(new InputStreamReader(connection.getInputStream(), contentType));
String line;
while ((line = in.readLine()) != null)
{
result.append(line);
}
log.info("recv - {}", result);
}
catch (ConnectException e)
{
log.error("调用HttpUtils.sendGet ConnectException, url=" + url + ",param=" + param, e);
}
catch (SocketTimeoutException e)
{
log.error("调用HttpUtils.sendGet SocketTimeoutException, url=" + url + ",param=" + param, e);
}
catch (IOException e)
{
log.error("调用HttpUtils.sendGet IOException, url=" + url + ",param=" + param, e);
}
catch (Exception e)
{
log.error("调用HttpsUtil.sendGet Exception, url=" + url + ",param=" + param, e);
}
finally
{
try
{
if (in != null)
{
in.close();
}
}
catch (Exception ex)
{
log.error("调用in.close Exception, url=" + url + ",param=" + param, ex);
}
}
return result.toString();
}
/**
* 向指定 URL 发送POST方法的请求
*
* @param url 发送请求的 URL
* @param param 请求参数请求参数应该是 name1=value1&name2=value2 的形式
* @return 所代表远程资源的响应结果
*/
public static String sendPost(String url, String param)
{
PrintWriter out = null;
BufferedReader in = null;
StringBuilder result = new StringBuilder();
try
{
log.info("sendPost - {}", url);
URL realUrl = new URL(url);
URLConnection conn = realUrl.openConnection();
conn.setRequestProperty("accept", "*/*");
conn.setRequestProperty("connection", "Keep-Alive");
conn.setRequestProperty("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64)");
conn.setRequestProperty("Accept-Charset", "utf-8");
conn.setRequestProperty("contentType", "utf-8");
conn.setDoOutput(true);
conn.setDoInput(true);
out = new PrintWriter(conn.getOutputStream());
out.print(param);
out.flush();
in = new BufferedReader(new InputStreamReader(conn.getInputStream(), StandardCharsets.UTF_8));
String line;
while ((line = in.readLine()) != null)
{
result.append(line);
}
log.info("recv - {}", result);
}
catch (ConnectException e)
{
log.error("调用HttpUtils.sendPost ConnectException, url=" + url + ",param=" + param, e);
}
catch (SocketTimeoutException e)
{
log.error("调用HttpUtils.sendPost SocketTimeoutException, url=" + url + ",param=" + param, e);
}
catch (IOException e)
{
log.error("调用HttpUtils.sendPost IOException, url=" + url + ",param=" + param, e);
}
catch (Exception e)
{
log.error("调用HttpsUtil.sendPost Exception, url=" + url + ",param=" + param, e);
}
finally
{
try
{
if (out != null)
{
out.close();
}
if (in != null)
{
in.close();
}
}
catch (IOException ex)
{
log.error("调用in.close Exception, url=" + url + ",param=" + param, ex);
}
}
return result.toString();
}
public static String sendSSLPost(String url, String param)
{
StringBuilder result = new StringBuilder();
String urlNameString = url + "?" + param;
try
{
log.info("sendSSLPost - {}", urlNameString);
SSLContext sc = SSLContext.getInstance("SSL");
sc.init(null, new TrustManager[] { new TrustAnyTrustManager() }, new java.security.SecureRandom());
URL console = new URL(urlNameString);
HttpsURLConnection conn = (HttpsURLConnection) console.openConnection();
conn.setRequestProperty("accept", "*/*");
conn.setRequestProperty("connection", "Keep-Alive");
conn.setRequestProperty("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64)");
conn.setRequestProperty("Accept-Charset", "utf-8");
conn.setRequestProperty("contentType", "utf-8");
conn.setDoOutput(true);
conn.setDoInput(true);
conn.setSSLSocketFactory(sc.getSocketFactory());
conn.setHostnameVerifier(new TrustAnyHostnameVerifier());
conn.connect();
InputStream is = conn.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(is));
String ret = "";
while ((ret = br.readLine()) != null)
{
if (ret != null && !"".equals(ret.trim()))
{
result.append(new String(ret.getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8));
}
}
log.info("recv - {}", result);
conn.disconnect();
br.close();
}
catch (ConnectException e)
{
log.error("调用HttpUtils.sendSSLPost ConnectException, url=" + url + ",param=" + param, e);
}
catch (SocketTimeoutException e)
{
log.error("调用HttpUtils.sendSSLPost SocketTimeoutException, url=" + url + ",param=" + param, e);
}
catch (IOException e)
{
log.error("调用HttpUtils.sendSSLPost IOException, url=" + url + ",param=" + param, e);
}
catch (Exception e)
{
log.error("调用HttpsUtil.sendSSLPost Exception, url=" + url + ",param=" + param, e);
}
return result.toString();
}
private static class TrustAnyTrustManager implements X509TrustManager
{
@Override
public void checkClientTrusted(X509Certificate[] chain, String authType)
{
}
@Override
public void checkServerTrusted(X509Certificate[] chain, String authType)
{
}
@Override
public X509Certificate[] getAcceptedIssuers()
{
return new X509Certificate[] {};
}
}
private static class TrustAnyHostnameVerifier implements HostnameVerifier
{
@Override
public boolean verify(String hostname, SSLSession session)
{
return true;
}
}
}

View File

@ -0,0 +1,56 @@
package com.tcctyn.common.core.utils.ip;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.tcctyn.common.core.config.TcctynConfig;
import com.tcctyn.common.core.constant.Constants;
import com.tcctyn.common.core.utils.StringUtils;
import com.tcctyn.common.core.utils.http.HttpUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* 获取地址类
*
* @author tcctyn
*/
public class AddressUtils
{
private static final Logger log = LoggerFactory.getLogger(AddressUtils.class);
// IP地址查询
public static final String IP_URL = "http://whois.pconline.com.cn/ipJson.jsp";
// 未知地址
public static final String UNKNOWN = "XX XX";
public static String getRealAddressByIP(String ip)
{
// 内网不查询
if (IpUtils.internalIp(ip))
{
return "内网IP";
}
if (TcctynConfig.isAddressEnabled())
{
try
{
String rspStr = HttpUtils.sendGet(IP_URL, "ip=" + ip + "&json=true", Constants.GBK);
if (StringUtils.isEmpty(rspStr))
{
log.error("获取地理位置异常 {}", ip);
return UNKNOWN;
}
JSONObject obj = JSON.parseObject(rspStr);
String region = obj.getString("pro");
String city = obj.getString("city");
return String.format("%s %s", region, city);
}
catch (Exception e)
{
log.error("获取地理位置异常 {}", ip);
}
}
return UNKNOWN;
}
}

View File

@ -0,0 +1,51 @@
package com.tcctyn.common.core.utils.mqtt;
public class JavaDemoMQTTV3 {
public static void main(String[] args) {
String broker = "tcp://47.109.202.121:1883";
String clientId = "hqyjDemo";
String topic = "topic/hqyj";
int subQos = 1;
int pubQos = 1;
String msg = "Hello MQTT";
// try {
// MqttClient client = new MqttClient(broker, clientId);
// MqttConnectOptions options = new MqttConnectOptions();
// client.connect(options);
//
// if (client.isConnected()) {
// client.setCallback(new MqttCallback() {
// public void messageArrived(String topic, MqttMessage message) throws Exception {
// System.out.println("topic: " + topic);
// System.out.println("qos: " + message.getQos());
// System.out.println("message content: " + new String(message.getPayload()));
// }
//
// public void connectionLost(Throwable cause) {
// System.out.println("connectionLost: " + cause.getMessage());
// }
//
// public void deliveryComplete(IMqttDeliveryToken token) {
// System.out.println("deliveryComplete: " + token.isComplete());
// }
// });
//
// client.subscribe(topic, subQos);
//
// MqttMessage message = new MqttMessage(msg.getBytes());
// message.setQos(pubQos);
// client.publish(topic, message);
// }
//
// client.disconnect();
// client.close();
//
// } catch (MqttException e) {
// e.printStackTrace();
// }
}
}

View File

@ -0,0 +1,63 @@
package com.tcctyn.common.core.utils.mqtt;
import com.tcctyn.common.core.utils.StringUtils;
import lombok.Data;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;
@Component
@ConfigurationProperties("spring.mqtt")
@Data
public class MqttConfig {
@Autowired
private MqttPushClient mqttPushClient;
/**
* 用户名
*/
private String username;
/**
* 密码
*/
private String password;
/**
* 连接地址
*/
private String hostUrl;
/**
* 客户Id
*/
private String clientId;
/**
* 默认连接话题
*/
private String defaultTopic;
/**
* 超时时间
*/
private int timeout;
/**
* 保持连接数
*/
private int keepalive;
/**
* mqtt功能使能
*/
private boolean enabled;
@Bean
public MqttPushClient getMqttPushClient() {
if(enabled == true){
String mqtt_topic[] = StringUtils.split(defaultTopic, ",");
mqttPushClient.connect(hostUrl, clientId, username, password, timeout, keepalive);//连接
for(int i=0; i<mqtt_topic.length; i++){
mqttPushClient.subscribe(mqtt_topic[i], 0);//订阅主题
}
}
return mqttPushClient;
}
}

View File

@ -0,0 +1,108 @@
package com.tcctyn.common.core.utils.mqtt;
import com.tcctyn.common.core.web.domain.AjaxResult;
import org.eclipse.paho.client.mqttv3.*;
import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component;
@Component
public class MqttPushClient {
private static final Logger logger = LoggerFactory.getLogger(MqttPushClient.class);
@Autowired
@Lazy
private PushCallback pushCallback;
private static MqttClient client;
private static MqttClient getClient() {
return client;
}
private static void setClient(MqttClient client) {
MqttPushClient.client = client;
}
/**
* 客户端连接
*
* @param host ip+端口
* @param clientID 客户端Id
* @param username 用户名
* @param password 密码
* @param timeout 超时时间
* @param keepalive 保留数
*/
public void connect(String host, String clientID, String username, String password, int timeout, int keepalive) {
MqttClient client;
try {
client = new MqttClient(host, clientID, new MemoryPersistence());
MqttConnectOptions options = new MqttConnectOptions();
options.setCleanSession(true);
options.setUserName(username);
options.setPassword(password.toCharArray());
options.setConnectionTimeout(timeout);
options.setKeepAliveInterval(keepalive);
MqttPushClient.setClient(client);
try {
client.setCallback(pushCallback);
client.connect(options);
} catch (Exception e) {
e.printStackTrace();
}
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 发布
*
* @param qos 连接方式
* @param retained 是否保留
* @param topic 主题
* @param pushMessage 消息体
*/
public AjaxResult publish(int qos, boolean retained, String topic, String pushMessage) {
MqttMessage message = new MqttMessage();
message.setQos(qos);
message.setRetained(retained);
message.setPayload(pushMessage.getBytes());
MqttTopic mTopic = MqttPushClient.getClient().getTopic(topic);
if (null == mTopic) {
logger.error("topic not exist");
}
MqttDeliveryToken token;
try {
token = mTopic.publish(message);
token.waitForCompletion();
return AjaxResult.success();
} catch (MqttPersistenceException e) {
e.printStackTrace();
return AjaxResult.error();
} catch (MqttException e) {
e.printStackTrace();
return AjaxResult.error();
}
}
/**
* 订阅某个主题
*
* @param topic 主题
* @param qos 连接方式
*/
public void subscribe(String topic, int qos) {
logger.info("开始订阅主题" + topic);
try {
MqttPushClient.getClient().subscribe(topic, qos);
} catch (MqttException e) {
e.printStackTrace();
}
}
}

View File

@ -0,0 +1,70 @@
package com.tcctyn.common.core.utils.mqtt;
import com.alibaba.fastjson2.JSONObject;
import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken;
import org.eclipse.paho.client.mqttv3.MqttCallback;
import org.eclipse.paho.client.mqttv3.MqttClient;
import org.eclipse.paho.client.mqttv3.MqttMessage;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component;
@Component
public class PushCallback implements MqttCallback {
private static final Logger logger = LoggerFactory.getLogger(MqttPushClient.class);
@Autowired
@Lazy
private MqttConfig mqttConfig;
private static MqttClient client;
private static String _topic;
private static String _qos;
private static String _msg;
@Override
public void connectionLost(Throwable throwable) {
// 连接丢失后一般在这里面进行重连
logger.info("连接断开,可以做重连");
if (client == null || !client.isConnected()) {
mqttConfig.getMqttPushClient();
}
}
@Override
public void messageArrived(String topic, MqttMessage mqttMessage) throws Exception {
// subscribe后得到的消息会执行到这里面
logger.info("接收消息主题 : " + topic);
logger.info("接收消息Qos : " + mqttMessage.getQos());
logger.info("接收消息内容 : " + new String(mqttMessage.getPayload()));
_topic = topic;
_qos = mqttMessage.getQos()+"";
_msg = new String(mqttMessage.getPayload());
/*
* 在这里添加处理接收到主题的代码
* 屎山开堆
*
*/
}
@Override
public void deliveryComplete(IMqttDeliveryToken iMqttDeliveryToken) {
logger.info("deliveryComplete---------" + iMqttDeliveryToken.isComplete());
}
//别的Controller层会调用这个方法来 获取 接收到的硬件数据
public String receive() {
JSONObject jsonObject = new JSONObject();
jsonObject.put("topic", _topic);
jsonObject.put("qos", _qos);
jsonObject.put("msg", _msg);
return jsonObject.toString();
}
}

View File

@ -0,0 +1,68 @@
package com.tcctyn.common.core.utils.sign;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
/**
* Md5加密方法
*
* @author tcctyn
*/
public class Md5Utils
{
private static final Logger log = LoggerFactory.getLogger(Md5Utils.class);
private static byte[] md5(String s)
{
MessageDigest algorithm;
try
{
algorithm = MessageDigest.getInstance("MD5");
algorithm.reset();
algorithm.update(s.getBytes("UTF-8"));
byte[] messageDigest = algorithm.digest();
return messageDigest;
}
catch (Exception e)
{
log.error("MD5 Error...", e);
}
return null;
}
private static final String toHex(byte hash[])
{
if (hash == null)
{
return null;
}
StringBuffer buf = new StringBuffer(hash.length * 2);
int i;
for (i = 0; i < hash.length; i++)
{
if ((hash[i] & 0xff) < 0x10)
{
buf.append("0");
}
buf.append(Long.toString(hash[i] & 0xff, 16));
}
return buf.toString();
}
public static String hash(String s)
{
try
{
return new String(toHex(md5(s)).getBytes(StandardCharsets.UTF_8), StandardCharsets.UTF_8);
}
catch (Exception e)
{
log.error("not supported charset...{}", e);
return s;
}
}
}

View File

@ -0,0 +1,85 @@
package com.tcctyn.common.core.web.domain;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.tcctyn.common.core.web.domain.entity.RegionInfo;
import com.tcctyn.common.core.web.domain.entity.SysDept;
import com.tcctyn.common.core.web.domain.entity.SysMenu;
import java.io.Serializable;
import java.util.List;
import java.util.stream.Collectors;
/**
* Treeselect树结构实体类
*
* @author tcctyn
*/
public class TreeSelect implements Serializable
{
private static final long serialVersionUID = 1L;
/** 节点ID */
private Long id;
/** 节点名称 */
private String label;
/** 子节点 */
@JsonInclude(JsonInclude.Include.NON_EMPTY)
private List<TreeSelect> children;
public TreeSelect()
{
}
public TreeSelect(SysDept dept)
{
this.id = dept.getDeptId();
this.label = dept.getDeptName();
this.children = dept.getChildren().stream().map(TreeSelect::new).collect(Collectors.toList());
}
public TreeSelect(SysMenu menu)
{
this.id = menu.getMenuId();
this.label = menu.getMenuName();
this.children = menu.getChildren().stream().map(TreeSelect::new).collect(Collectors.toList());
}
public TreeSelect(RegionInfo regionInfo){
this.id = regionInfo.getId();
this.label = regionInfo.getAreaName();
this.children = regionInfo.getChildren().stream().map(TreeSelect::new).collect(Collectors.toList());
}
public Long getId()
{
return id;
}
public void setId(Long id)
{
this.id = id;
}
public String getLabel()
{
return label;
}
public void setLabel(String label)
{
this.label = label;
}
public List<TreeSelect> getChildren()
{
return children;
}
public void setChildren(List<TreeSelect> children)
{
this.children = children;
}
}

View File

@ -0,0 +1,196 @@
package com.tcctyn.common.core.web.domain.entity;
import com.baomidou.mybatisplus.annotation.*;
import lombok.Data;
import lombok.EqualsAndHashCode;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
/**
* <p>
* 区域信息表
* </p>
*
* @author 代超
* @since 2024-09-24
*/
@Data
@EqualsAndHashCode(callSuper = false)
@TableName("region_info")
public class RegionInfo implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 主键id
*/
@TableId(value = "id", type = IdType.AUTO)
private Long id;
/**
* 父id
*/
@NotNull(message = "父级id不能为空")
private Long parentId;
/**
* 全路径 父id为0的数据默认传0
*/
private String ancestors;
/**
* 地区编号
*/
@NotBlank(message = "地区编号不能为空")
private String areaNo;
/**
* 地区名称
*/
@NotBlank(message = "地区名称不能为空")
private String areaName;
/**
* 地区类型林区林场电子围栏切片
*/
@NotBlank(message = "地区类型不能为空")
private String areaType;
/**
* 植被类型
*/
private String vegetationType;
/**
* 土质类型
*/
private String soilType;
/**
* 地区运营状态
*/
private String operationStatus;
/**
* 地区排序
*/
private Integer sortNo;
/**
* 归属行政区划
*/
private String administrativeDivision;
/**
* 详细地址
*/
private String address;
/**
* 地区负责单位
*/
private String belongingUnit;
/**
* 负责单位联系方式
*/
private String unitTel;
/**
* 地区简介
*/
private String areaIntroduction;
/**
* 地区图片多张以英文逗号分隔
*/
private String areaPicture;
/**
* 边框颜色
*/
private String borderColor;
/**
* 边框宽度
*/
private String borderWidth;
/**
* 边框透明度
*/
private String borderTransparency;
/**
* 填充色
*/
private String fillColor;
/**
* 填充色透明度
*/
private String fillColorTransparency;
/**
* 边框样式
*/
private String borderStyle;
/**
* 地区面积平方米
*/
private String regionArea;
/**
* 经纬度信息
*/
private String coordinateInfo;
/**
* 备注信息
*/
private String remark;
/**
* 该条记录是否被删除1-已删除0-未删除
*/
@TableLogic
private Integer delFlag;
/**
* 创建人员姓名
*/
private String createdBy;
/**
* 记录创建时间默认用服务器时间
*/
@TableField(fill = FieldFill.INSERT)
private Date createdTime;
/**
* 修改人员姓名
*/
private String updatedBy;
/**
* 记录修改时间默认用服务器时间
*/
@TableField(fill = FieldFill.UPDATE)
private Date updatedTime;
/**
* 子节点列表
*/
@TableField(exist = false)
private List<RegionInfo> children = new ArrayList<>();
@TableField(exist = false)
private boolean hasChildren;
}

View File

@ -0,0 +1,207 @@
package com.tcctyn.common.core.web.domain.entity;
import com.baomidou.mybatisplus.annotation.TableField;
import com.tcctyn.common.core.web.domain.BaseEntity;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import javax.validation.constraints.Email;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import java.util.ArrayList;
import java.util.List;
/**
* 部门表 sys_dept
*
* @author tcctyn
*/
public class SysDept extends BaseEntity
{
private static final long serialVersionUID = 1L;
/** 部门ID */
private Long deptId;
/** 父部门ID */
private Long parentId;
/** 祖级列表 */
private String ancestors;
/** 部门名称 */
private String deptName;
/** 显示顺序 */
private Integer orderNum;
/** 负责人 */
private String leader;
/** 联系电话 */
private String phone;
/** 邮箱 */
private String email;
/** 部门状态:0正常,1停用 */
private String status;
/** 删除标志0代表存在 2代表删除 */
private String delFlag;
/** 父部门名称 */
@TableField(exist = false)
private String parentName;
/** 子部门 */
@TableField(exist = false)
private List<SysDept> children = new ArrayList<SysDept>();
public Long getDeptId()
{
return deptId;
}
public void setDeptId(Long deptId)
{
this.deptId = deptId;
}
public Long getParentId()
{
return parentId;
}
public void setParentId(Long parentId)
{
this.parentId = parentId;
}
public String getAncestors()
{
return ancestors;
}
public void setAncestors(String ancestors)
{
this.ancestors = ancestors;
}
@NotBlank(message = "部门名称不能为空")
@Size(min = 0, max = 30, message = "部门名称长度不能超过30个字符")
public String getDeptName()
{
return deptName;
}
public void setDeptName(String deptName)
{
this.deptName = deptName;
}
@NotNull(message = "显示顺序不能为空")
public Integer getOrderNum()
{
return orderNum;
}
public void setOrderNum(Integer orderNum)
{
this.orderNum = orderNum;
}
public String getLeader()
{
return leader;
}
public void setLeader(String leader)
{
this.leader = leader;
}
@Size(min = 0, max = 11, message = "联系电话长度不能超过11个字符")
public String getPhone()
{
return phone;
}
public void setPhone(String phone)
{
this.phone = phone;
}
@Email(message = "邮箱格式不正确")
@Size(min = 0, max = 50, message = "邮箱长度不能超过50个字符")
public String getEmail()
{
return email;
}
public void setEmail(String email)
{
this.email = email;
}
public String getStatus()
{
return status;
}
public void setStatus(String status)
{
this.status = status;
}
public String getDelFlag()
{
return delFlag;
}
public void setDelFlag(String delFlag)
{
this.delFlag = delFlag;
}
public String getParentName()
{
return parentName;
}
public void setParentName(String parentName)
{
this.parentName = parentName;
}
public List<SysDept> getChildren()
{
return children;
}
public void setChildren(List<SysDept> children)
{
this.children = children;
}
@Override
public String toString() {
return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
.append("deptId", getDeptId())
.append("parentId", getParentId())
.append("ancestors", getAncestors())
.append("deptName", getDeptName())
.append("orderNum", getOrderNum())
.append("leader", getLeader())
.append("phone", getPhone())
.append("email", getEmail())
.append("status", getStatus())
.append("delFlag", getDelFlag())
.append("createBy", getCreateBy())
.append("createTime", getCreateTime())
.append("updateBy", getUpdateBy())
.append("updateTime", getUpdateTime())
.toString();
}
}

View File

@ -0,0 +1,177 @@
package com.tcctyn.common.core.web.domain.entity;
import com.tcctyn.common.core.annotation.Excel;
import com.tcctyn.common.core.annotation.Excel.ColumnType;
import com.tcctyn.common.core.constant.UserConstants;
import com.tcctyn.common.core.web.domain.BaseEntity;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.Size;
/**
* 字典数据表 sys_dict_data
*
* @author tcctyn
*/
public class SysDictData extends BaseEntity
{
private static final long serialVersionUID = 1L;
/** 字典编码 */
@Excel(name = "字典编码", cellType = ColumnType.NUMERIC)
private Long dictCode;
/** 字典排序 */
@Excel(name = "字典排序", cellType = ColumnType.NUMERIC)
private Long dictSort;
/** 字典标签 */
@Excel(name = "字典标签")
private String dictLabel;
/** 字典键值 */
@Excel(name = "字典键值")
private String dictValue;
/** 字典类型 */
@Excel(name = "字典类型")
private String dictType;
/** 样式属性(其他样式扩展) */
private String cssClass;
/** 表格字典样式 */
private String listClass;
/** 是否默认Y是 N否 */
@Excel(name = "是否默认", readConverterExp = "Y=是,N=否")
private String isDefault;
/** 状态0正常 1停用 */
@Excel(name = "状态", readConverterExp = "0=正常,1=停用")
private String status;
public Long getDictCode()
{
return dictCode;
}
public void setDictCode(Long dictCode)
{
this.dictCode = dictCode;
}
public Long getDictSort()
{
return dictSort;
}
public void setDictSort(Long dictSort)
{
this.dictSort = dictSort;
}
@NotBlank(message = "字典标签不能为空")
@Size(min = 0, max = 100, message = "字典标签长度不能超过100个字符")
public String getDictLabel()
{
return dictLabel;
}
public void setDictLabel(String dictLabel)
{
this.dictLabel = dictLabel;
}
@NotBlank(message = "字典键值不能为空")
@Size(min = 0, max = 100, message = "字典键值长度不能超过100个字符")
public String getDictValue()
{
return dictValue;
}
public void setDictValue(String dictValue)
{
this.dictValue = dictValue;
}
@NotBlank(message = "字典类型不能为空")
@Size(min = 0, max = 100, message = "字典类型长度不能超过100个字符")
public String getDictType()
{
return dictType;
}
public void setDictType(String dictType)
{
this.dictType = dictType;
}
@Size(min = 0, max = 100, message = "样式属性长度不能超过100个字符")
public String getCssClass()
{
return cssClass;
}
public void setCssClass(String cssClass)
{
this.cssClass = cssClass;
}
public String getListClass()
{
return listClass;
}
public void setListClass(String listClass)
{
this.listClass = listClass;
}
public boolean getDefault()
{
return UserConstants.YES.equals(this.isDefault);
}
public String getIsDefault()
{
return isDefault;
}
public void setIsDefault(String isDefault)
{
this.isDefault = isDefault;
}
public String getStatus()
{
return status;
}
public void setStatus(String status)
{
this.status = status;
}
@Override
public String toString() {
return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
.append("dictCode", getDictCode())
.append("dictSort", getDictSort())
.append("dictLabel", getDictLabel())
.append("dictValue", getDictValue())
.append("dictType", getDictType())
.append("cssClass", getCssClass())
.append("listClass", getListClass())
.append("isDefault", getIsDefault())
.append("status", getStatus())
.append("createBy", getCreateBy())
.append("createTime", getCreateTime())
.append("updateBy", getUpdateBy())
.append("updateTime", getUpdateTime())
.append("remark", getRemark())
.toString();
}
}

View File

@ -0,0 +1,97 @@
package com.tcctyn.common.core.web.domain.entity;
import com.tcctyn.common.core.annotation.Excel;
import com.tcctyn.common.core.annotation.Excel.ColumnType;
import com.tcctyn.common.core.web.domain.BaseEntity;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.Pattern;
import javax.validation.constraints.Size;
/**
* 字典类型表 sys_dict_type
*
* @author tcctyn
*/
public class SysDictType extends BaseEntity
{
private static final long serialVersionUID = 1L;
/** 字典主键 */
@Excel(name = "字典主键", cellType = ColumnType.NUMERIC)
private Long dictId;
/** 字典名称 */
@Excel(name = "字典名称")
private String dictName;
/** 字典类型 */
@Excel(name = "字典类型")
private String dictType;
/** 状态0正常 1停用 */
@Excel(name = "状态", readConverterExp = "0=正常,1=停用")
private String status;
public Long getDictId()
{
return dictId;
}
public void setDictId(Long dictId)
{
this.dictId = dictId;
}
@NotBlank(message = "字典名称不能为空")
@Size(min = 0, max = 100, message = "字典类型名称长度不能超过100个字符")
public String getDictName()
{
return dictName;
}
public void setDictName(String dictName)
{
this.dictName = dictName;
}
@NotBlank(message = "字典类型不能为空")
@Size(min = 0, max = 100, message = "字典类型类型长度不能超过100个字符")
@Pattern(regexp = "^[a-z][a-z0-9_]*$", message = "字典类型必须以字母开头,且只能为(小写字母,数字,下滑线)")
public String getDictType()
{
return dictType;
}
public void setDictType(String dictType)
{
this.dictType = dictType;
}
public String getStatus()
{
return status;
}
public void setStatus(String status)
{
this.status = status;
}
@Override
public String toString() {
return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
.append("dictId", getDictId())
.append("dictName", getDictName())
.append("dictType", getDictType())
.append("status", getStatus())
.append("createBy", getCreateBy())
.append("createTime", getCreateTime())
.append("updateBy", getUpdateBy())
.append("updateTime", getUpdateTime())
.append("remark", getRemark())
.toString();
}
}

View File

@ -0,0 +1,275 @@
package com.tcctyn.common.core.web.domain.entity;
import com.tcctyn.common.core.web.domain.BaseEntity;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import java.util.ArrayList;
import java.util.List;
/**
* 菜单权限表 sys_menu
*
* @author tcctyn
*/
public class SysMenu extends BaseEntity
{
private static final long serialVersionUID = 1L;
/** 菜单ID */
private Long menuId;
/** 菜单名称 */
private String menuName;
/** 父菜单名称 */
private String parentName;
/** 父菜单ID */
private Long parentId;
/** 显示顺序 */
private Integer orderNum;
/** 路由地址 */
private String path;
/** 组件路径 */
private String component;
/** 路由参数 */
private String query;
/** 路由名称默认和路由地址相同的驼峰格式注意因为vue3版本的router会删除名称相同路由为避免名字的冲突特殊情况可以自定义 */
private String routeName;
/** 是否为外链0是 1否 */
private String isFrame;
/** 是否缓存0缓存 1不缓存 */
private String isCache;
/** 类型M目录 C菜单 F按钮 */
private String menuType;
/** 显示状态0显示 1隐藏 */
private String visible;
/** 菜单状态0正常 1停用 */
private String status;
/** 权限字符串 */
private String perms;
/** 菜单图标 */
private String icon;
/** 子菜单 */
private List<SysMenu> children = new ArrayList<SysMenu>();
public Long getMenuId()
{
return menuId;
}
public void setMenuId(Long menuId)
{
this.menuId = menuId;
}
@NotBlank(message = "菜单名称不能为空")
@Size(min = 0, max = 50, message = "菜单名称长度不能超过50个字符")
public String getMenuName()
{
return menuName;
}
public void setMenuName(String menuName)
{
this.menuName = menuName;
}
public String getParentName()
{
return parentName;
}
public void setParentName(String parentName)
{
this.parentName = parentName;
}
public Long getParentId()
{
return parentId;
}
public void setParentId(Long parentId)
{
this.parentId = parentId;
}
@NotNull(message = "显示顺序不能为空")
public Integer getOrderNum()
{
return orderNum;
}
public void setOrderNum(Integer orderNum)
{
this.orderNum = orderNum;
}
@Size(min = 0, max = 200, message = "路由地址不能超过200个字符")
public String getPath()
{
return path;
}
public void setPath(String path)
{
this.path = path;
}
@Size(min = 0, max = 200, message = "组件路径不能超过255个字符")
public String getComponent()
{
return component;
}
public void setComponent(String component)
{
this.component = component;
}
public String getQuery()
{
return query;
}
public void setQuery(String query)
{
this.query = query;
}
public String getRouteName()
{
return routeName;
}
public void setRouteName(String routeName)
{
this.routeName = routeName;
}
public String getIsFrame()
{
return isFrame;
}
public void setIsFrame(String isFrame)
{
this.isFrame = isFrame;
}
public String getIsCache()
{
return isCache;
}
public void setIsCache(String isCache)
{
this.isCache = isCache;
}
@NotBlank(message = "菜单类型不能为空")
public String getMenuType()
{
return menuType;
}
public void setMenuType(String menuType)
{
this.menuType = menuType;
}
public String getVisible()
{
return visible;
}
public void setVisible(String visible)
{
this.visible = visible;
}
public String getStatus()
{
return status;
}
public void setStatus(String status)
{
this.status = status;
}
@Size(min = 0, max = 100, message = "权限标识长度不能超过100个字符")
public String getPerms()
{
return perms;
}
public void setPerms(String perms)
{
this.perms = perms;
}
public String getIcon()
{
return icon;
}
public void setIcon(String icon)
{
this.icon = icon;
}
public List<SysMenu> getChildren()
{
return children;
}
public void setChildren(List<SysMenu> children)
{
this.children = children;
}
@Override
public String toString() {
return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
.append("menuId", getMenuId())
.append("menuName", getMenuName())
.append("parentId", getParentId())
.append("orderNum", getOrderNum())
.append("path", getPath())
.append("component", getComponent())
.append("query", getQuery())
.append("routeName", getRouteName())
.append("isFrame", getIsFrame())
.append("IsCache", getIsCache())
.append("menuType", getMenuType())
.append("visible", getVisible())
.append("status ", getStatus())
.append("perms", getPerms())
.append("icon", getIcon())
.append("createBy", getCreateBy())
.append("createTime", getCreateTime())
.append("updateBy", getUpdateBy())
.append("updateTime", getUpdateTime())
.append("remark", getRemark())
.toString();
}
}

View File

@ -0,0 +1,242 @@
package com.tcctyn.common.core.web.domain.entity;
import com.tcctyn.common.core.annotation.Excel;
import com.tcctyn.common.core.annotation.Excel.ColumnType;
import com.tcctyn.common.core.web.domain.BaseEntity;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import java.util.Set;
/**
* 角色表 sys_role
*
* @author tcctyn
*/
public class SysRole extends BaseEntity
{
private static final long serialVersionUID = 1L;
/** 角色ID */
@Excel(name = "角色序号", cellType = ColumnType.NUMERIC)
private Long roleId;
/** 角色名称 */
@Excel(name = "角色名称")
private String roleName;
/** 角色权限 */
@Excel(name = "角色权限")
private String roleKey;
/** 角色排序 */
@Excel(name = "角色排序")
private Integer roleSort;
/** 数据范围1所有数据权限2自定义数据权限3本部门数据权限4本部门及以下数据权限5仅本人数据权限 */
@Excel(name = "数据范围", readConverterExp = "1=所有数据权限,2=自定义数据权限,3=本部门数据权限,4=本部门及以下数据权限,5=仅本人数据权限")
private String dataScope;
/** 菜单树选择项是否关联显示( 0父子不互相关联显示 1父子互相关联显示 */
private boolean menuCheckStrictly;
/** 部门树选择项是否关联显示0父子不互相关联显示 1父子互相关联显示 */
private boolean deptCheckStrictly;
/** 角色状态0正常 1停用 */
@Excel(name = "角色状态", readConverterExp = "0=正常,1=停用")
private String status;
/** 删除标志0代表存在 2代表删除 */
private String delFlag;
/** 用户是否存在此角色标识 默认不存在 */
private boolean flag = false;
/** 菜单组 */
private Long[] menuIds;
/** 部门组(数据权限) */
private Long[] deptIds;
/** 角色菜单权限 */
private Set<String> permissions;
public SysRole()
{
}
public SysRole(Long roleId)
{
this.roleId = roleId;
}
public Long getRoleId()
{
return roleId;
}
public void setRoleId(Long roleId)
{
this.roleId = roleId;
}
public boolean isAdmin()
{
return isAdmin(this.roleId);
}
public static boolean isAdmin(Long roleId)
{
return roleId != null && 1L == roleId;
}
@NotBlank(message = "角色名称不能为空")
@Size(min = 0, max = 30, message = "角色名称长度不能超过30个字符")
public String getRoleName()
{
return roleName;
}
public void setRoleName(String roleName)
{
this.roleName = roleName;
}
@NotBlank(message = "权限字符不能为空")
@Size(min = 0, max = 100, message = "权限字符长度不能超过100个字符")
public String getRoleKey()
{
return roleKey;
}
public void setRoleKey(String roleKey)
{
this.roleKey = roleKey;
}
@NotNull(message = "显示顺序不能为空")
public Integer getRoleSort()
{
return roleSort;
}
public void setRoleSort(Integer roleSort)
{
this.roleSort = roleSort;
}
public String getDataScope()
{
return dataScope;
}
public void setDataScope(String dataScope)
{
this.dataScope = dataScope;
}
public boolean isMenuCheckStrictly()
{
return menuCheckStrictly;
}
public void setMenuCheckStrictly(boolean menuCheckStrictly)
{
this.menuCheckStrictly = menuCheckStrictly;
}
public boolean isDeptCheckStrictly()
{
return deptCheckStrictly;
}
public void setDeptCheckStrictly(boolean deptCheckStrictly)
{
this.deptCheckStrictly = deptCheckStrictly;
}
public String getStatus()
{
return status;
}
public void setStatus(String status)
{
this.status = status;
}
public String getDelFlag()
{
return delFlag;
}
public void setDelFlag(String delFlag)
{
this.delFlag = delFlag;
}
public boolean isFlag()
{
return flag;
}
public void setFlag(boolean flag)
{
this.flag = flag;
}
public Long[] getMenuIds()
{
return menuIds;
}
public void setMenuIds(Long[] menuIds)
{
this.menuIds = menuIds;
}
public Long[] getDeptIds()
{
return deptIds;
}
public void setDeptIds(Long[] deptIds)
{
this.deptIds = deptIds;
}
public Set<String> getPermissions()
{
return permissions;
}
public void setPermissions(Set<String> permissions)
{
this.permissions = permissions;
}
@Override
public String toString() {
return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
.append("roleId", getRoleId())
.append("roleName", getRoleName())
.append("roleKey", getRoleKey())
.append("roleSort", getRoleSort())
.append("dataScope", getDataScope())
.append("menuCheckStrictly", isMenuCheckStrictly())
.append("deptCheckStrictly", isDeptCheckStrictly())
.append("status", getStatus())
.append("delFlag", getDelFlag())
.append("createBy", getCreateBy())
.append("createTime", getCreateTime())
.append("updateBy", getUpdateBy())
.append("updateTime", getUpdateTime())
.append("remark", getRemark())
.toString();
}
}

View File

@ -0,0 +1,389 @@
package com.tcctyn.common.core.web.domain.entity;
import com.baomidou.mybatisplus.annotation.TableField;
import com.tcctyn.common.core.annotation.Excel;
import com.tcctyn.common.core.annotation.Excel.ColumnType;
import com.tcctyn.common.core.annotation.Excel.Type;
import com.tcctyn.common.core.annotation.Excels;
import com.tcctyn.common.core.web.domain.BaseEntity;
import com.tcctyn.common.core.xss.Xss;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import javax.validation.constraints.Email;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.Size;
import java.util.Date;
import java.util.List;
/**
* 用户对象 sys_user
*
* @author tcctyn
*/
public class SysUser extends BaseEntity
{
private static final long serialVersionUID = 1L;
/** 用户ID */
@Excel(name = "用户序号", type = Type.EXPORT, cellType = ColumnType.NUMERIC, prompt = "用户编号")
private Long userId;
/** 部门ID */
@Excel(name = "部门编号", type = Type.IMPORT)
private Long deptId;
/** 归属区域id */
private Long regionId;
/** 林区id */
private Long forestId;
/** 林场id */
private Long farmId;
/** 电子围栏id */
private Long fenceId;
/** 用户账号 */
@Excel(name = "登录名称")
private String userName;
/** 用户昵称 */
@Excel(name = "用户名称")
private String nickName;
/** 用户邮箱 */
@Excel(name = "用户邮箱")
private String email;
/** 手机号码 */
@Excel(name = "手机号码", cellType = ColumnType.TEXT)
private String phonenumber;
/** 用户性别 */
@Excel(name = "用户性别", readConverterExp = "0=男,1=女,2=未知")
private String sex;
/** 用户头像 */
private String avatar;
/** 密码 */
private String password;
/** 帐号状态0正常 1停用 */
@Excel(name = "帐号状态", readConverterExp = "0=正常,1=停用")
private String status;
/** 删除标志0代表存在 2代表删除 */
private String delFlag;
/** 最后登录IP */
@Excel(name = "最后登录IP", type = Type.EXPORT)
private String loginIp;
/** 最后登录时间 */
@Excel(name = "最后登录时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss", type = Type.EXPORT)
private Date loginDate;
/** 部门对象 */
@Excels({
@Excel(name = "部门名称", targetAttr = "deptName", type = Type.EXPORT),
@Excel(name = "部门负责人", targetAttr = "leader", type = Type.EXPORT)
})
@TableField(exist = false)
private SysDept dept;
@TableField(exist = false)
/** 归属林区 */
private RegionInfo region;
@TableField(exist = false)
/** 角色对象 */
private List<SysRole> roles;
@TableField(exist = false)
/** 角色组 */
private Long[] roleIds;
@TableField(exist = false)
/** 岗位组 */
private Long[] postIds;
@TableField(exist = false)
/** 角色ID */
private Long roleId;
public SysUser()
{
}
public SysUser(Long userId)
{
this.userId = userId;
}
public Long getUserId()
{
return userId;
}
public void setUserId(Long userId)
{
this.userId = userId;
}
public boolean isAdmin()
{
return isAdmin(this.userId);
}
public static boolean isAdmin(Long userId)
{
return userId != null && 1L == userId;
}
public Long getDeptId()
{
return deptId;
}
public void setDeptId(Long deptId)
{
this.deptId = deptId;
}
@Xss(message = "用户昵称不能包含脚本字符")
@Size(min = 0, max = 30, message = "用户昵称长度不能超过30个字符")
public String getNickName()
{
return nickName;
}
public void setNickName(String nickName)
{
this.nickName = nickName;
}
@Xss(message = "用户账号不能包含脚本字符")
@NotBlank(message = "用户账号不能为空")
@Size(min = 0, max = 30, message = "用户账号长度不能超过30个字符")
public String getUserName()
{
return userName;
}
public void setUserName(String userName)
{
this.userName = userName;
}
@Email(message = "邮箱格式不正确")
@Size(min = 0, max = 50, message = "邮箱长度不能超过50个字符")
public String getEmail()
{
return email;
}
public void setEmail(String email)
{
this.email = email;
}
@Size(min = 0, max = 11, message = "手机号码长度不能超过11个字符")
public String getPhonenumber()
{
return phonenumber;
}
public void setPhonenumber(String phonenumber)
{
this.phonenumber = phonenumber;
}
public String getSex()
{
return sex;
}
public void setSex(String sex)
{
this.sex = sex;
}
public String getAvatar()
{
return avatar;
}
public void setAvatar(String avatar)
{
this.avatar = avatar;
}
public String getPassword()
{
return password;
}
public void setPassword(String password)
{
this.password = password;
}
public String getStatus()
{
return status;
}
public void setStatus(String status)
{
this.status = status;
}
public String getDelFlag()
{
return delFlag;
}
public void setDelFlag(String delFlag)
{
this.delFlag = delFlag;
}
public String getLoginIp()
{
return loginIp;
}
public void setLoginIp(String loginIp)
{
this.loginIp = loginIp;
}
public Date getLoginDate()
{
return loginDate;
}
public void setLoginDate(Date loginDate)
{
this.loginDate = loginDate;
}
public SysDept getDept()
{
return dept;
}
public void setDept(SysDept dept)
{
this.dept = dept;
}
public List<SysRole> getRoles()
{
return roles;
}
public void setRoles(List<SysRole> roles)
{
this.roles = roles;
}
public Long[] getRoleIds()
{
return roleIds;
}
public void setRoleIds(Long[] roleIds)
{
this.roleIds = roleIds;
}
public Long[] getPostIds()
{
return postIds;
}
public void setPostIds(Long[] postIds)
{
this.postIds = postIds;
}
public Long getRoleId()
{
return roleId;
}
public void setFenceId(Long fenceId) {
this.fenceId = fenceId;
}
public void setRoleId(Long roleId)
{
this.roleId = roleId;
}
public Long getForestId() {
return forestId;
}
public void setForestId(Long forestId) {
this.forestId = forestId;
}
public Long getRegionId() {
return regionId;
}
public void setRegionId(Long regionId) {
this.regionId = regionId;
}
public Long getFarmId() {
return farmId;
}
public void setFarmId(Long farmId) {
this.farmId = farmId;
}
public Long getFenceId() {
return fenceId;
}
public RegionInfo getRegion() {
return region;
}
public void setRegion(RegionInfo region) {
this.region = region;
}
@Override
public String toString() {
return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
.append("userId", getUserId())
.append("deptId", getDeptId())
.append("userName", getUserName())
.append("nickName", getNickName())
.append("email", getEmail())
.append("phonenumber", getPhonenumber())
.append("sex", getSex())
.append("avatar", getAvatar())
.append("password", getPassword())
.append("status", getStatus())
.append("delFlag", getDelFlag())
.append("loginIp", getLoginIp())
.append("loginDate", getLoginDate())
.append("createBy", getCreateBy())
.append("createTime", getCreateTime())
.append("updateBy", getUpdateBy())
.append("updateTime", getUpdateTime())
.append("remark", getRemark())
.append("dept", getDept())
.toString();
}
}

View File

@ -0,0 +1,36 @@
package com.tcctyn.common.core.web.domain.model;
import lombok.Data;
import java.io.Serializable;
/**
* 数据字典展示实体类
*/
@Data
public class DictDataVO implements Serializable {
private static final long serialVersionUID = -9073442421377041774L;
public DictDataVO(Long dictSort, String dictLabel, String dictValue) {
this.dictSort = dictSort;
this.dictLabel = dictLabel;
this.dictValue = dictValue;
}
/**
* 字典排序
*/
private Long dictSort;
/**
* 字典标签
*/
private String dictLabel;
/**
* 字典键值
*/
private String dictValue;
}

View File

@ -0,0 +1,69 @@
package com.tcctyn.common.core.web.domain.model;
/**
* 用户登录对象
*
* @author tcctyn
*/
public class LoginBody
{
/**
* 用户名
*/
private String username;
/**
* 用户密码
*/
private String password;
/**
* 验证码
*/
private String code;
/**
* 唯一标识
*/
private String uuid;
public String getUsername()
{
return username;
}
public void setUsername(String username)
{
this.username = username;
}
public String getPassword()
{
return password;
}
public void setPassword(String password)
{
this.password = password;
}
public String getCode()
{
return code;
}
public void setCode(String code)
{
this.code = code;
}
public String getUuid()
{
return uuid;
}
public void setUuid(String uuid)
{
this.uuid = uuid;
}
}

View File

@ -0,0 +1,268 @@
package com.tcctyn.common.core.web.domain.model;
import com.alibaba.fastjson2.annotation.JSONField;
import com.tcctyn.common.core.web.domain.entity.SysUser;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import java.util.Collection;
import java.util.Set;
/**
* 登录用户身份权限
*
* @author tcctyn
*/
public class LoginUser implements UserDetails
{
private static final long serialVersionUID = 1L;
/**
* 用户ID
*/
private Long userId;
/**
* 部门ID
*/
private Long deptId;
/**
* 用户唯一标识
*/
private String token;
/**
* 登录时间
*/
private Long loginTime;
/**
* 过期时间
*/
private Long expireTime;
/**
* 登录IP地址
*/
private String ipaddr;
/**
* 登录地点
*/
private String loginLocation;
/**
* 浏览器类型
*/
private String browser;
/**
* 操作系统
*/
private String os;
/**
* 权限列表
*/
private Set<String> permissions;
/**
* 用户信息
*/
private SysUser user;
public LoginUser()
{
}
public LoginUser(SysUser user, Set<String> permissions)
{
this.user = user;
this.permissions = permissions;
}
public LoginUser(Long userId, Long deptId, SysUser user, Set<String> permissions)
{
this.userId = userId;
this.deptId = deptId;
this.user = user;
this.permissions = permissions;
}
public Long getUserId()
{
return userId;
}
public void setUserId(Long userId)
{
this.userId = userId;
}
public Long getDeptId()
{
return deptId;
}
public void setDeptId(Long deptId)
{
this.deptId = deptId;
}
public String getToken()
{
return token;
}
public void setToken(String token)
{
this.token = token;
}
@JSONField(serialize = false)
@Override
public String getPassword()
{
return user.getPassword();
}
@Override
public String getUsername()
{
return user.getUserName();
}
/**
* 账户是否未过期,过期无法验证
*/
@JSONField(serialize = false)
@Override
public boolean isAccountNonExpired()
{
return true;
}
/**
* 指定用户是否解锁,锁定的用户无法进行身份验证
*
* @return
*/
@JSONField(serialize = false)
@Override
public boolean isAccountNonLocked()
{
return true;
}
/**
* 指示是否已过期的用户的凭据(密码),过期的凭据防止认证
*
* @return
*/
@JSONField(serialize = false)
@Override
public boolean isCredentialsNonExpired()
{
return true;
}
/**
* 是否可用 ,禁用的用户不能身份验证
*
* @return
*/
@JSONField(serialize = false)
@Override
public boolean isEnabled()
{
return true;
}
public Long getLoginTime()
{
return loginTime;
}
public void setLoginTime(Long loginTime)
{
this.loginTime = loginTime;
}
public String getIpaddr()
{
return ipaddr;
}
public void setIpaddr(String ipaddr)
{
this.ipaddr = ipaddr;
}
public String getLoginLocation()
{
return loginLocation;
}
public void setLoginLocation(String loginLocation)
{
this.loginLocation = loginLocation;
}
public String getBrowser()
{
return browser;
}
public void setBrowser(String browser)
{
this.browser = browser;
}
public String getOs()
{
return os;
}
public void setOs(String os)
{
this.os = os;
}
public Long getExpireTime()
{
return expireTime;
}
public void setExpireTime(Long expireTime)
{
this.expireTime = expireTime;
}
public Set<String> getPermissions()
{
return permissions;
}
public void setPermissions(Set<String> permissions)
{
this.permissions = permissions;
}
public SysUser getUser()
{
return user;
}
public void setUser(SysUser user)
{
this.user = user;
}
@Override
public Collection<? extends GrantedAuthority> getAuthorities()
{
return null;
}
}

View File

@ -0,0 +1,11 @@
package com.tcctyn.common.core.web.domain.model;
/**
* 用户注册对象
*
* @author tcctyn
*/
public class RegisterBody extends LoginBody
{
}

View File

@ -0,0 +1,134 @@
package com.tcctyn.iot.forestfire.BO;
import lombok.Data;
import java.io.Serializable;
import java.util.Date;
@Data
public class FireWarningMQTTBO implements Serializable {
private static final long serialVersionUID = 184298993802545138L;
/** 火情预警id */
private Long id;
/**
* 发现火情设备编号
*/
private String deviceNo;
/**
* 设备类型
*/
private String deviceType;
/**
* 地址
*/
private String address;
/**
* 经度
*/
private String longitude;
/**
* 纬度
*/
private String latitude;
/**
* 高度
*/
private String height;
/**
* 所属区域id
*/
private Long regionId;
/**
* 火情标题
*/
private String fireTitle;
/**
* 火情级别
*/
private String fireLevel;
/**
* 起火原因
*/
private String fireCause;
/**
* 处置状态未处理已研判已上报已归档
*/
private String disposalStatus;
/**
* 火情图片
*/
private String firePicture;
/**
* 火情预警数据来源
*/
private String dataSource;
/**
* 备注信息
*/
private String remark;
/**
* 记录创建时间默认用服务器时间
*/
private Date createdTime;
/**
* 归属点位id
*/
private Long pointId;
/**
* 归属点位编号
*/
private String pointNo;
/**
* 归属点位名称
*/
private String pointName;
/**
* 归属点位地址
*/
private String pointAddress;
/**
* 归属点位经度
*/
private String pointLongitude;
/**
* 归属点位纬度
*/
private String pointLatitude;
/**
* 归属点位高度
*/
private String pointHeight;
/**
* 归属点位类型
*/
private String pointType;
/** 归属区域名称 */
private String regionName;
}

View File

@ -0,0 +1,35 @@
package com.tcctyn.iot.forestfire.BO;
import lombok.Data;
import java.io.Serializable;
/**
* 火情预警信息误判后消息推送
*/
@Data
public class FireWarningMisjudgeBO implements Serializable {
private static final long serialVersionUID = -1954870764499170410L;
/**
* 火情预警id
*/
private Long id;
/**
* 火情预警处理状态
*/
private String disposalStatus;
/**
* 误判标识
*/
private Integer misjudgeFlag;
/**
* 处理消息
*/
private String disposalMsg;
}

View File

@ -0,0 +1,83 @@
package com.tcctyn.iot.forestfire.BO;
import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.Data;
import java.io.Serializable;
import java.util.Date;
/**
* 打卡点巡护点业务对象
*/
@Data
public class PointInfoBO implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 点位记录id
*/
private Long id;
/**
* 归属地区id 可能是林区林场电子围栏巡护路径id
*/
private Long belongingRegionId;
@JsonIgnore
/**
* 林区id
*/
private Long forestId;
/**
* 林场id
*/
@JsonIgnore
private Long farmId;
/**
* 电子围栏id
*/
@JsonIgnore
private Long fenceId;
/**
* 经度
*/
private String longitude;
/**
* 纬度
*/
private String latitude;
/**
* 高度
*/
private String height;
/**
* 点位类型云台卡口打卡点巡护点
*/
private String pointType;
/**
* 点位顺序
*/
private Integer sortNo;
/**
* 打卡半径单位
*/
private String checkInRadius;
/**
* 是否打卡
*/
private boolean checkInFlag;
/**
* 打卡时间
*/
private Date checkInTime;
}

View File

@ -0,0 +1,28 @@
package com.tcctyn.iot.forestfire.BO;
import lombok.Data;
import java.io.Serializable;
/**
* 位置信息BO
*/
@Data
public class PositionBO implements Serializable {
private static final long serialVersionUID = 5127358619357602320L;
public PositionBO(String longitude, String latitude, String height) {
}
/** 经度 */
private String longitude;
/** 纬度 */
private String latitude;
/** 高度 */
private String height;
}

View File

@ -0,0 +1,36 @@
package com.tcctyn.iot.forestfire.BO;
import lombok.Data;
import java.io.Serializable;
/**
* 卫星热点数据模拟地图取点范围BO
*/
@Data
public class ScopeSimulationBO implements Serializable {
private static final long serialVersionUID = -4916623718291474020L;
public ScopeSimulationBO() {}
public ScopeSimulationBO(double minLongitude, double maxLongitude, double minLatitude, double maxLatitude) {
this.minLongitude = minLongitude;
this.maxLongitude = maxLongitude;
this.minLatitude = minLatitude;
this.maxLatitude = maxLatitude;
}
/** 最小经度 */
private double minLongitude;
/** 最大经度 */
private double maxLongitude;
/** 最小纬度 */
private double minLatitude;
/** 最大纬度 */
private double maxLatitude;
}

View File

@ -0,0 +1,45 @@
package com.tcctyn.iot.forestfire.BO;
import lombok.Data;
import java.io.Serializable;
/**
* 用户信息业务对象
*/
@Data
public class SysUserBO implements Serializable {
private static final long serialVersionUID = 6464645141599651914L;
/**
* 用户id
*/
private Long userId;
/**
* 用户账号
*/
private String userName;
/**
* 用户昵称
*/
private String nickName;
/**
* 用户邮箱
*/
private String email;
/**
* 手机号码
*/
private String phonenumber;
/**
* 用户性别
*/
private String sex;
}

View File

@ -0,0 +1,39 @@
package com.tcctyn.iot.forestfire.VO;
import lombok.Data;
import java.io.Serializable;
/**
* APP 端聚合统计接口返回值
*/
@Data
public class AggregationStatisticsVO implements Serializable {
private static final long serialVersionUID = -7851077263822626129L;
/**
* 未处理的火情预警数
*/
private Long unhandledFireWarningNum = 0L;
/**
* 未处理的火情上报数
*/
private Long unhandledFireReportNum = 0L;
/**
* 我未接受的任务数
*/
private Long unacceptedTaskNum = 0L;
/**
* 未审批的记录数
*/
private Long unapprovedNum = 0L;
/**
* 林区下未接受的任务数
*/
private Long unacceptedTaskNumByRegion = 0L;
}

View File

@ -0,0 +1,100 @@
package com.tcctyn.iot.forestfire.VO;
import lombok.Data;
import java.io.Serializable;
import java.util.List;
/**
* 查询火情风险点附近最近的机场VO
*/
@Data
public class AirportVO implements Serializable {
private static final long serialVersionUID = -1759830973473090526L;
/**
* 主键id
*/
private Long id;
/**
* 设备编号
*/
private String deviceNo;
/**
* 设备名称
*/
private String deviceName;
/**
* 设备型号
*/
private String deviceModel;
/**
* 设备厂商
*/
private String deviceManufacturer;
/**
* 设备协议
*/
private String deviceProtocol;
/**
* 接入方式
*/
private String accessMethod;
/**
* 设备类型
*/
private String deviceType;
/**
* 设备状态在线/离线
*/
private String deviceStatus;
/**
* 归属区域id,机场需要挂在地区下面
*/
private Long regionId;
/**
* 地址
*/
private String address;
/**
* 经度
*/
private String longitude;
/**
* 纬度
*/
private String latitude;
/**
* 高度
*/
private String height;
/**
* 设备启用状态0-停用/1-启用
*/
private Integer enableFlag;
/**
* 归属地区名称
*/
private String regionName;
/** 机场下的无人机列表 */
private List<DroneVO> droneList;
}

View File

@ -0,0 +1,78 @@
package com.tcctyn.iot.forestfire.VO;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import java.io.Serializable;
import java.util.Date;
/**
* 审批记录返回给前端VO
*/
@Data
public class ApprovalRecordVO implements Serializable {
private static final long serialVersionUID = -2678024258066273556L;
/**
* 主键id
*/
private Long id;
/**
* 业务类型
*/
private String businessType;
/**
* 业务数据id
*/
private Long businessDataId;
/**
* 业务数据内容
*/
private Object businessContent;
/**
* 审批标识0-未审批1-已审批
*/
private Integer approvalFlag;
/**
* 审批状态0-驳回1-通过
*/
private Integer approvalStatus;
/**
* 驳回说明
*/
private String rejectionStatement;
/**
* 审核人id
*/
private Long reviewerId;
/**
* 审核时间
*/
private Date reviewTime;
/**
* 备注信息
*/
private String remark;
/**
* 记录创建时间默认用服务器时间
*/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date createdTime;
/**
* 审批人姓名
*/
private String reviewerName;
}

View File

@ -0,0 +1,59 @@
package com.tcctyn.iot.forestfire.VO;
import lombok.Data;
import java.io.Serializable;
/**
* 摄像头设备VO
*/
@Data
public class CameraVO implements Serializable {
private static final long serialVersionUID = 4975876865936973836L;
/**
* 主键id
*/
private Long id;
/**
* 设备编号
*/
private String deviceNo;
/**
* 设备名称
*/
private String deviceName;
/**
* 设备型号
*/
private String deviceModel;
/**
* 设备厂商
*/
private String deviceManufacturer;
/**
* 设备类型
*/
private String deviceType;
/**
* 设备在线/离线状态
*/
private String deviceStatus;
/**
* 归属区域id
*/
private Long regionId;
/**
* 归属区域名称
*/
private String regionName;
}

View File

@ -0,0 +1,47 @@
package com.tcctyn.iot.forestfire.VO;
import lombok.Data;
import java.io.Serializable;
import java.util.Date;
/**
* 轮播图VO
*/
@Data
public class CarouselImageConfigVO implements Serializable {
private static final long serialVersionUID = -5616770476661134447L;
/**
* 主键id
*/
private Long id;
/**
* 图片主题
*/
private String imageTheme;
/**
* 图片
*/
private String image;
/**
* 序号
*/
private Integer sortNo;
/**
* 是否启用0-停用1-启用
*/
private Integer enableFlag;
/**
* 创建时间
*/
private Date createdTime;
}

View File

@ -0,0 +1,95 @@
package com.tcctyn.iot.forestfire.VO;
import lombok.Data;
import java.io.Serializable;
import java.util.Date;
/**
* 打卡记录VO
*/
@Data
public class CheckInRecordVO implements Serializable {
private static final long serialVersionUID = 8171630821682560531L;
/**
* 主键id
*/
private Long id;
/**
* 排班id
*/
private Long scheduleId;
/**
* 点位id
*/
private Long pointId;
/**
* 林区id
*/
private Long forestId;
/**
* 林场id
*/
private Long farmId;
/**
* 电子围栏id
*/
private Long fenceId;
/**
* 巡护路径id
*/
private Long pathId;
/**
* 用户id
*/
private Long userId;
/**
* 打卡时间
*/
private Date checkInTime;
/**
* 打卡地点
*/
private String location;
/**
* 经度
*/
private String longitude;
/**
* 纬度
*/
private String latitude;
/**
* 高度
*/
private String height;
/**
* 备注信息
*/
private String remark;
/**
* 打卡拍照
*/
private String checkPicture;
/**
* 护林员姓名
*/
private String userName;
}

View File

@ -0,0 +1,85 @@
package com.tcctyn.iot.forestfire.VO;
import lombok.Data;
import java.io.Serializable;
/**
* 设备信息及归属点位信息
*/
@Data
public class DeviceAndPointInfoVO implements Serializable {
private static final long serialVersionUID = 7032345348538117946L;
//设备信息
/**
* 主键id
*/
private Long id;
/**
* 设备编号
*/
private String deviceNo;
/**
* 设备型号
*/
private String deviceModel;
/**
* 设备厂商
*/
private String deviceManufacturer;
/**
* 设备类型
*/
private String deviceType;
//点位信息
/**
* 归属云台/卡口id
*/
private Long pointId;
/**
* 点位编号
*/
private String pointNo;
/**
* 点位名称
*/
private String pointName;
/**
* 经度
*/
private String longitude;
/**
* 纬度
*/
private String latitude;
/**
* 点位类型云台卡口打卡点巡护点
*/
private String pointType;
/**
* 点位描述信息
*/
private String pointDescription;
/**
* 点位图片多张以英文逗号分隔
*/
private String pointPicture;
}

View File

@ -0,0 +1,59 @@
package com.tcctyn.iot.forestfire.VO;
import lombok.Data;
import java.util.Date;
/**
* 设备通道返回给前端的VO
*/
@Data
public class DeviceChanelsVO {
//private static final long serialVersionUID = L;
/**
* 主键id
*/
private Long id;
/**
* 设备编号
*/
private String deviceNo;
/**
* 通道号
*/
private String chanelNo;
/**
* 名称
*/
private String name;
/**
* 流地址
*/
private String streamUrl;
/**
* 创建人员姓名
*/
private String createdBy;
/**
* 创建时间默认用服务器时间
*/
private Date createdTime;
/**
* 修改人员姓名
*/
private String updatedBy;
/**
* 修改时间默认用服务器时间
*/
private Date updatedTime;
}

View File

@ -0,0 +1,46 @@
package com.tcctyn.iot.forestfire.VO;
import lombok.Data;
/**
* 设备配置返回给前端的VO
*/
@Data
public class DeviceConfigVO {
/**
* 主键id
*/
private Long id;
/**
* 设备编号
*/
private String deviceNo;
/**
* 用户账户
*/
private String username;
/**
* 密码
*/
private String password;
/**
* IP地址
*/
private String ip;
/**
* 端口号
*/
private String port;
/**
* 备注
*/
private String remark;
}

View File

@ -0,0 +1,91 @@
package com.tcctyn.iot.forestfire.VO;
import lombok.Data;
import java.io.Serializable;
/**
* 简单的设备信息
* 云台卡口下的设备信息
*/
@Data
public class DeviceInfoSimpleVO implements Serializable {
private static final long serialVersionUID = -5550394669879020905L;
/**
* 主键id
*/
private Long id;
/**
* 设备编号
*/
private String deviceNo;
/**
* 设备名称
*/
private String deviceName;
/**
* 设备型号
*/
private String deviceModel;
/**
* 设备厂商
*/
private String deviceManufacturer;
/**
* 设备协议
*/
private String deviceProtocol;
/**
* 接入方式
*/
private String accessMethod;
/**
* 设备类型
*/
private String deviceType;
/**
* 设备状态在线/离线
*/
private String deviceStatus;
/**
* 归属区域id,机场需要挂在地区下面
*/
private Long regionId;
/**
* 归属云台/卡口id
*/
private Long pointId;
/**
* 设备启用状态0-停用/1-启用
*/
private Integer enableFlag;
/**
* 备注信息
*/
private String remark;
/**
* 归属地区名称
*/
private String regionName;
/**
* 归属点位名称
*/
private String pointName;
}

View File

@ -0,0 +1,179 @@
package com.tcctyn.iot.forestfire.VO;
import com.tcctyn.iot.forestfire.domain.DeviceConfig;
import lombok.Data;
import java.io.Serializable;
import java.util.Date;
import java.util.List;
/**
* 设备信息返回给前端的VO
*/
@Data
public class DeviceInfoVO implements Serializable {
private static final long serialVersionUID = 3428836874966786844L;
/**
* 主键id
*/
private Long id;
/**
* 设备编号
*/
private String deviceNo;
/**
* 设备名称
*/
private String deviceName;
/**
* 设备型号
*/
private String deviceModel;
/**
* 设备厂商
*/
private String deviceManufacturer;
/**
* 设备协议
*/
private String deviceProtocol;
/**
* 接入方式
*/
private String accessMethod;
/**
* 设备类型
*/
private String deviceType;
/**
* 设备状态在线/离线
*/
private String deviceStatus;
/**
* 归属区域id,机场需要挂在地区下面
*/
private Long regionId;
/**
* 归属云台/卡口id
*/
private Long pointId;
/**
* 林区id
*/
private Long forestId;
/**
* 林场id
*/
private Long farmId;
/**
* 电子围栏id
*/
private Long fenceId;
/**
* 机场id
*/
private Long airportId;
/**
* 地址
*/
private String address;
/**
* 经度
*/
private String longitude;
/**
* 纬度
*/
private String latitude;
/**
* 高度
*/
private String height;
/**
* 设备启用状态0-停用/1-启用
*/
private Integer enableFlag;
/**
* 备注信息
*/
private String remark;
/**
* 该条记录是否被删除1-已删除0-未删除
*/
private Integer delFlag;
/**
* 创建人员姓名
*/
private String createdBy;
/**
* 记录创建时间默认用服务器时间
*/
private Date createdTime;
/**
* 修改人员姓名
*/
private String updatedBy;
/**
* 记录修改时间默认用服务器时间
*/
private Date updatedTime;
//以下是包装给前端的名称字段
/**
* 归属地区名称
*/
private String regionName;
/**
* 归属点位名称
*/
private String pointName;
/**
* 归属机场名称
*/
private String airportName;
/**
* 归属名称统一点位名称与机场名称方便前端列表页面展示
*/
private String pointOrAirportName;
/**
* 设备配置信息表
*/
private DeviceConfig deviceConfig;
/**
* 设备通道信息表
*/
private List<DeviceChanelsVO> deviceChanelsVOList;
}

View File

@ -0,0 +1,35 @@
package com.tcctyn.iot.forestfire.VO;
import lombok.Data;
import java.io.Serializable;
/**
* 设备归属VO
*/
@Data
public class DeviceOwnerVO implements Serializable {
private static final long serialVersionUID = 8007964042205003964L;
public DeviceOwnerVO() {
}
public DeviceOwnerVO(Long id, String name) {
this.id = id;
this.name = name;
}
/**
* id
*/
private Long id;
/**
* 名称
*/
private String name;
}

View File

@ -0,0 +1,39 @@
package com.tcctyn.iot.forestfire.VO;
import lombok.Data;
import java.io.Serializable;
/**
* 统计云台卡口下的设备数量
*/
@Data
public class DeviceStatisticsByPointVO implements Serializable {
private static final long serialVersionUID = -6173268737974058330L;
/**
* 设备总数
*/
private Integer totalNum;
/**
* 云台设备数量
*/
private Integer ptzNum;
/**
* 卡口设备数量
*/
private Integer bayonetNum;
/**
* 总的在线设备
*/
private Integer onlineNum;
/**
* 总的设备在线率
*/
private String onlineRate;
}

View File

@ -0,0 +1,34 @@
package com.tcctyn.iot.forestfire.VO;
import lombok.Data;
import java.io.Serializable;
/**
* 设备列表上方的统计信息
*/
@Data
public class DeviceStatisticsByStatusVO implements Serializable {
private static final long serialVersionUID = 8173577365152550543L;
/**
* 设备总数量
*/
private Integer totalNum;
/**
* 在线设备数量
*/
private Integer onlineNum;
/**
* 离线设备数量
*/
private Integer offlineNum;
/**
* 未启用的设备数量
*/
private Integer disableNum;
}

View File

@ -0,0 +1,39 @@
package com.tcctyn.iot.forestfire.VO;
import lombok.Data;
import java.io.Serializable;
/**
* 大屏设备统计子类
*/
@Data
public class DeviceStatisticsSubVO implements Serializable {
private static final long serialVersionUID = -8015476506632502263L;
/**
* 设备类型
*/
private String type;
/**
* 在线数量
*/
private Integer onlineNum;
/**
* 离线数量
*/
private Integer offlineNum;
/**
* 总数量
*/
private Integer totalNum;
/**
* 在线率
*/
private String onlineRate;
}

View File

@ -0,0 +1,30 @@
package com.tcctyn.iot.forestfire.VO;
import lombok.Data;
import java.io.Serializable;
import java.util.List;
/**
* 大屏设备信息统计VO
*/
@Data
public class DeviceStatisticsVO implements Serializable {
private static final long serialVersionUID = -4514149323953101569L;
/**
* 设备总数量
*/
private Integer total;
/**
* 总的在线率
*/
private String overallOnlineRate;
/**
* 子对象列表
*/
private List<DeviceStatisticsSubVO> subList;
}

View File

@ -0,0 +1,29 @@
package com.tcctyn.iot.forestfire.VO;
import lombok.Data;
import java.io.Serializable;
/**
* 资源点下的设备统计信息
*/
@Data
public class DeviceUnderPointVO implements Serializable {
private static final long serialVersionUID = -3210088644519804874L;
/**
* 设备总数
*/
private Integer totalNum = 0;
/**
* 在线设备数
*/
private Integer onlineNum = 0;
/**
* 离线设备数
*/
private Integer offlineNum = 0;
}

View File

@ -0,0 +1,80 @@
package com.tcctyn.iot.forestfire.VO;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import lombok.Data;
import java.io.Serializable;
import java.util.Date;
/**
* 无人机任务返回给前端的VO
*/
@Data
public class DroneTaskPlanVO implements Serializable {
private static final long serialVersionUID = -4331918313693391285L;
/**
* 主键id
*/
@TableId(value = "id", type = IdType.AUTO)
private Long id;
/**
* 无人机编号
*/
private String droneNo;
/**
* 任务区域
*/
private Long regionId;
/**
* 任务名称
*/
private String taskName;
/**
* 任务类型周期性任务单次性任务
*/
private String taskType;
/**
* 单次任务标识0-非单次任务1-单次任务
*/
private Integer singleTaskFlag;
/**
* 执行周期每多少天执行一次
*/
private String executionCycle;
/**
* 任务状态未执行执行中已完成
*/
private String taskStatus;
/**
* 开始时间
*/
private Date startTime;
/**
* 结束时间
*/
private Date endTime;
/**
* 任务航线可以暂时存放经纬度信息给前端提供模拟的航线
*/
private String taskRoute;
//下面是VO展示的字段
/**
* 任务区域名称
*/
private String regionName;
}

View File

@ -0,0 +1,89 @@
package com.tcctyn.iot.forestfire.VO;
import lombok.Data;
import java.io.Serializable;
/**
* 机场下的无人机列表
*/
@Data
public class DroneVO implements Serializable {
private static final long serialVersionUID = 628168140318152935L;
/**
* 主键id
*/
private Long id;
/**
* 设备编号
*/
private String deviceNo;
/**
* 设备名称
*/
private String deviceName;
/**
* 设备型号
*/
private String deviceModel;
/**
* 设备厂商
*/
private String deviceManufacturer;
/**
* 设备协议
*/
private String deviceProtocol;
/**
* 接入方式
*/
private String accessMethod;
/**
* 设备类型
*/
private String deviceType;
/**
* 设备状态在线/离线
*/
private String deviceStatus;
/**
* 归属区域id,机场需要挂在地区下面
*/
private Long regionId;
/**
* 机场id
*/
private Long airportId;
/**
* 设备启用状态0-停用/1-启用
*/
private Integer enableFlag;
/**
* 备注信息
*/
private String remark;
/**
* 归属地区名称
*/
private String regionName;
/**
* 归属机场名称
*/
private String airportName;
}

View File

@ -0,0 +1,39 @@
package com.tcctyn.iot.forestfire.VO;
import lombok.Data;
import java.io.Serializable;
/**
* 历史火情统计信息VO
*/
@Data
public class FireReportStatisticsVO implements Serializable {
private static final long serialVersionUID = -5474081569984902993L;
/**
* 总的火灾数量
*/
private Integer totalNum;
/**
* 一般火灾数量
*/
private Integer generalFireNum;
/**
* 较大火灾
*/
private Integer majorFireNum;
/**
* 重大火灾
*/
private Integer seriousFireNum;
/**
* 特别重大火灾
*/
private Integer especiallySeriousFireNum;
}

View File

@ -0,0 +1,200 @@
package com.tcctyn.iot.forestfire.VO;
import lombok.Data;
import java.io.Serializable;
import java.util.Date;
/**
* 火情上报VO
*/
@Data
public class FireReportVO implements Serializable {
private static final long serialVersionUID = 7460119250284631833L;
/**
* 主键id
*/
private Long id;
/**
* 火情标题
*/
private String fireTitle;
/**
* 上报方式卫星上报无人机上报人工上报监测点云台/卡口上报
*/
private String reportMethod;
/**
* 来源火情预警id
*/
private Long fireWarningId;
/**
* 上报设备编号
*/
private String deviceNo;
/**
* 上报设备类型
*/
private String deviceType;
/**
* 上报人员id
*/
private Long reporterId;
/**
* 地址
*/
private String address;
/**
* 经度
*/
private String longitude;
/**
* 纬度
*/
private String latitude;
/**
* 高度
*/
private String height;
/**
* 归属区域id
*/
private Long regionId;
/**
* 林区id
*/
private Long forestId;
/**
* 林场id
*/
private Long farmId;
/**
* 电子围栏id
*/
private Long fenceId;
/**
* 火险等级有别于火情预警等级
*/
private String fireHazardLevel;
/**
* 起火原因
*/
private String fireCause;
/**
* 失火面积
*/
private String fireArea;
/**
* 预计损失金额
*/
private String amountLoss;
/**
* 火情图片
*/
private String firePicture;
/**
* 火情描述
*/
private String fireDescription;
/**
* 处置状态未处理已处理
*/
private Integer disposalStatus;
/**
* 处置说明
*/
private String disposalInstruction;
/**
* 扑救情况
*/
private String firefightingSituation;
/**
* 灾后情况说明
*/
private String disasterSituation;
/**
* 扑救单位
*/
private String firefightingUnit;
/**
* 主要负责人
*/
private String personInCharge;
/**
* 归档状态
*/
private Integer archiveStatus;
/**
* 归档时间
*/
private Date archiveTime;
/**
* 备注信息
*/
private String remark;
/**
* 该条记录是否被删除1-已删除0-未删除
*/
private Integer delFlag;
/**
* 创建人员姓名
*/
private String createdBy;
/**
* 记录创建时间默认用服务器时间
*/
private Date createdTime;
/**
* 修改人员姓名
*/
private String updatedBy;
/**
* 记录修改时间默认用服务器时间
*/
private Date updatedTime;
// 以下为给前端展示的字段
/** 上报人姓名 */
private String reporterName;
/** 地区名称 */
private String regionName;
}

View File

@ -0,0 +1,24 @@
package com.tcctyn.iot.forestfire.VO;
import lombok.Data;
import java.io.Serializable;
/**
* 根据火情等级进行统计
*/
@Data
public class FireWarningCountByLevelVO implements Serializable {
private static final long serialVersionUID = 8301796932960031829L;
/**
* 火情等级
*/
private String fireLevel;
/**
* 数量
*/
private Integer number;
}

View File

@ -0,0 +1,26 @@
package com.tcctyn.iot.forestfire.VO;
import lombok.Data;
import java.io.Serializable;
@Data
public class FireWarningCountByStatusVO implements Serializable {
private static final long serialVersionUID = 97763231488523638L;
/**
* 已处理数量
*/
private Integer unhandledNum;
/** 已上报数量 */
private Integer reportedNum;
/** 已研判数量 */
private Integer analyzedNum;
/** 已归档数量 */
private Integer archivedNum;
}

View File

@ -0,0 +1,145 @@
package com.tcctyn.iot.forestfire.VO;
import lombok.Data;
import java.io.Serializable;
import java.util.Date;
/**
* 火情信息VO
*/
@Data
public class FireWarningInfoVO implements Serializable {
private static final long serialVersionUID = 8848812242542233067L;
/**
* 主键id
*/
private Long id;
/**
* 发现火情设备编号
*/
private String deviceNo;
/**
* 设备类型
*/
private String deviceType;
/**
* 地址
*/
private String address;
/**
* 经度
*/
private String longitude;
/**
* 纬度
*/
private String latitude;
/**
* 高度
*/
private String height;
/**
* 所属区域id
*/
private Long regionId;
/**
* 区域名称
*/
private String regionName;
/**
* 林区id
*/
private Long forestId;
/**
* 林场id
*/
private Long farmId;
/**
* 电子围栏id
*/
private Long fenceId;
/**
* 火情标题
*/
private String fireTitle;
/**
* 火情级别
*/
private String fireLevel;
/**
* 起火原因
*/
private String fireCause;
/**
* 处置状态未处理已研判已上报已归档
*/
private String disposalStatus;
/**
* 研判结果说明
*/
private String analyzeInstruction;
/**
* 处置人
*/
private Long disposalBy;
/**
* 处置人姓名
*/
private String disposalByName;
/**
* 处置时间
*/
private Date disposalTime;
/**
* 失火面积
*/
private String fireArea;
/**
* 损失金额
*/
private String amountDamage;
/**
* 火情图片
*/
private String firePicture;
/**
* 火情预警数据来源
*/
private String dataSource;
/**
* 备注信息
*/
private String remark;
/**
* 创建时间
*/
private Date createdTime;
}

View File

@ -0,0 +1,29 @@
package com.tcctyn.iot.forestfire.VO;
import lombok.Data;
import java.io.Serializable;
/**
* 火情预警信息来源统计
*/
@Data
public class FireWarningStatisticsByDataSourceVO implements Serializable {
private static final long serialVersionUID = -2324434962571875389L;
/**
* 卫星热点
*/
private Integer satelliteHotspotNum;
/**
* 视频监控
*/
private Integer videoMonitorNum;
/**
* 巡护上报
*/
private Integer patrolReportNum;
}

View File

@ -0,0 +1,42 @@
package com.tcctyn.iot.forestfire.VO;
import lombok.Data;
import java.io.Serializable;
import java.util.List;
/**
* 火情预警周边分析VO
*/
@Data
public class FireWarningSurroundingVO implements Serializable {
private static final long serialVersionUID = -1610177596913751767L;
/**
* 负责单位可以是人也可以是企业
*/
private String belongingUnit;
/**
* 负责单位联系电话
*/
private String unitTel;
/**
* 护林员信息
*/
private List<SurroundingPersonVO> personVOList;
/**
* 仓库信息
*/
private List<SurroundingWareHouseVO> wareHouseVOList;
/**
* 水源地信息
*/
private List<SurroundingWaterSourceVO> waterSourceVOList;
}

View File

@ -0,0 +1,22 @@
package com.tcctyn.iot.forestfire.VO;
import lombok.Data;
/**
* 大屏页面护林员统计数据
*/
@Data
public class ForesterStatisticsVO {
// 当日值班人数
private Integer todayDutyNum;
// 当日打卡数
private Integer todayCheckNum;
// 当日总共打卡数
private Integer totalCheckNum;
// 临时任务数
private Integer tempTaskNum;
}

View File

@ -0,0 +1,90 @@
package com.tcctyn.iot.forestfire.VO;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import java.io.Serializable;
import java.util.Date;
/**
* 海康_硬件抓拍图片元数据表
* @author 13768238378
* @TableName hk_store_capture_pictures
*/
@Data
public class HkStoreCapturePicturesVO implements Serializable {
/**
* 主键ID
*/
// @TableId(value = "id", type = IdType.AUTO)
private Long id;
/**
* MinIO存储桶名称符合MinIO命名规范
*/
private String bucket;
/**
* MinIO对象唯一路径: images/user/2023/10/photo.jpg
*/
private String objectKey;
/**
* 原始文件名
*/
private String originalName;
/**
* 上传用户ID
*/
private Long userId;
/**
* 文件大小字节
*/
private Long fileSize;
/**
* 文件MIME类型如image/jpeg
*/
private String fileType;
/**
* 文件MD5哈希用于去重校验
*/
private String md5;
/**
* 是否公开0-私有1-公开
*/
private Integer isPublic;
/**
* 软删除标记0-未删除1-已删除
*/
private Integer isDeleted;
/**
* 上传时间
*/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date createdAt;
/**
* 更新时间
*/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date updatedAt;
/**
* 设备id
*/
private String deviceId;
/**
* 访问路径
*/
private String accessPath;
private static final long serialVersionUID = 1L;
}

Some files were not shown because too many files have changed in this diff Show More