Compare commits

...

16 Commits

@ -1,9 +1,9 @@
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/sz_admin_test?useUnicode=true&characterEncoding=UTF-8&serverTimezone=GMT%2B8&useSSL=false&allowPublicKeyRetrieval=true
url: jdbc:mysql://127.0.0.1:13306/sz_admin_test?useUnicode=true&characterEncoding=UTF-8&serverTimezone=GMT%2B8&useSSL=false&allowPublicKeyRetrieval=true
username: root
password: Yanfa2023@
password: 123456
hikari:
#连接池名
pool-name: HikariCP

@ -1,5 +1,5 @@
ZLMediaKit:
ip: 192.168.2.128
ip: 192.168.2.129
port: 8080
app: live
vhost: __defaultVhost__

@ -1,9 +1,9 @@
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/sz_admin_test?useUnicode=true&characterEncoding=UTF-8&serverTimezone=GMT%2B8&useSSL=false&allowPublicKeyRetrieval=true
url: jdbc:mysql://127.0.0.1:13306/sz_admin_test?useUnicode=true&characterEncoding=UTF-8&serverTimezone=GMT%2B8&useSSL=false&allowPublicKeyRetrieval=true
username: root
password: Yanfa2023@
password: 123456
hikari:
#连接池名
pool-name: HikariCP

@ -1,9 +1,9 @@
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/sz_admin_test?useUnicode=true&characterEncoding=UTF-8&serverTimezone=GMT%2B8&useSSL=false&allowPublicKeyRetrieval=true
url: jdbc:mysql://127.0.0.1:13306/sz_admin_test?useUnicode=true&characterEncoding=UTF-8&serverTimezone=GMT%2B8&useSSL=false&allowPublicKeyRetrieval=true
username: root
password: Yanfa2023@
password: 123456
hikari:
#连接池名
pool-name: HikariCP

@ -56,6 +56,12 @@ public class ApiResult<T> implements Serializable {
return apiResult;
}
// public static <T> ApiResult<T> error(T data) {
// ApiResult<T> apiResult = new ApiResult<>();
// apiResult.data = data;
// return apiResult;
// }
public static <T> ApiResult<T> success(T data, Object param) {
ApiResult<T> apiResult = new ApiResult<>();
apiResult.data = data;

@ -55,7 +55,7 @@ public class SaTokenConfig implements WebMvcConfigurer {
public void addResourceHandlers(ResourceHandlerRegistry registry) {
// D:/work/images/save/1.jpg
registry.addResourceHandler("/save/**")
.addResourceLocations("file:D:/work/images/");
.addResourceLocations("file:D:/work/images/","file:D:/work/temp/");
}
}

@ -101,6 +101,11 @@
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.im4java</groupId>
<artifactId>im4java</artifactId>
<version>1.4.0</version>
</dependency>
<!-- jna,ffmpeg的相关依赖-->
<dependency>
<groupId>cc.eguid</groupId>

@ -1,12 +1,19 @@
package com.sz;
import com.sz.admin.monitor.service.CameraService;
import jakarta.annotation.PostConstruct;
import jakarta.annotation.Resource;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.context.event.EventListener;
import org.springframework.scheduling.annotation.EnableScheduling;
@SpringBootApplication
@ -15,12 +22,14 @@ import org.springframework.scheduling.annotation.EnableScheduling;
@EnableScheduling
public class AdminApplication {
private static final Logger log = LoggerFactory.getLogger(AdminApplication.class);
@Value("${app.version}")
private String appVersion;
@Getter
private static String version;
@PostConstruct
public void init() {
setVersion(appVersion); // 通过辅助方法设置静态字段
@ -45,4 +54,6 @@ public class AdminApplication {
System.out.println(result);
}
}

@ -0,0 +1,28 @@
package com.sz.admin.monitor.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import java.util.concurrent.Executor;
import java.util.concurrent.ThreadPoolExecutor;
@Configuration
public class CameraThreadPoolConfig {
@Bean("cameraInspectionExecutor")
public Executor cameraInspectionExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
// 核心线程数:
executor.setCorePoolSize(10);
// 最大线程数:并发峰值
executor.setMaxPoolSize(50);
// 队列容量:如果超过核心线程数的任务,先放进队列排队
executor.setQueueCapacity(200);
// 线程前缀名,方便以后看日志排查问题
executor.setThreadNamePrefix("Camera-Inspect-");
// 拒绝策略:如果队列满了,由调用者所在线程(即定时任务主线程)自己去执行
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
executor.initialize();
return executor;
}
}

@ -11,8 +11,8 @@ public class RestTemplateConfig {
@Bean
public RestTemplate restTemplate() {
SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
factory.setConnectTimeout(5000);
factory.setReadTimeout(5000);
factory.setConnectTimeout(10000);
factory.setReadTimeout(10000);
return new RestTemplate(factory);
}
}

@ -0,0 +1,68 @@
package com.sz.admin.monitor.controller;
import com.mybatisflex.core.query.QueryWrapper;
import com.sz.admin.monitor.pojo.dto.blurDetection.BlurDetectionDTO;
import com.sz.admin.monitor.pojo.dto.blurDetection.BlurDetectionUpdateDTO;
import com.sz.admin.monitor.pojo.po.BlurDetection;
import com.sz.admin.monitor.pojo.vo.blurDetection.BlurDetectionVO;
import com.sz.admin.monitor.service.BlurDetectionService;
import com.sz.core.common.entity.ApiResult;
import com.sz.core.util.BeanCopyUtils;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
* ClassName: BlurDetectionController
* Package: com.sz.admin.monitor.controller
* Description:
*/
@Tag(name = "模糊检测")
@RestController
@RequestMapping("blur-detection")
@RequiredArgsConstructor
public class BlurDetectionController {
private final BlurDetectionService blurDetectionService;
/**
*
*/
@Operation(summary = "新增模糊检测配置")
@PostMapping("/add")
public ApiResult<Boolean> add(@RequestBody BlurDetectionDTO blurDetectionDTO) {
BlurDetection detection = BeanCopyUtils.copy(blurDetectionDTO, BlurDetection.class);
return ApiResult.success(blurDetectionService.save(detection));
}
/**
*
*/
@Operation(summary = "更新配置信息")
@PutMapping("/update")
public ApiResult<Boolean> update(@RequestBody BlurDetectionUpdateDTO blurDetectionUpdateDTO) {
return ApiResult.success(blurDetectionService.updateById(BeanCopyUtils.copy(blurDetectionUpdateDTO, BlurDetection.class)));
}
@Operation(summary = "新增或者更新配置信息")
@PostMapping("/addOrUpdate")
public ApiResult<Boolean> addOrUpdate(@RequestBody BlurDetectionDTO blurDetectionDTO) {
return ApiResult.success(blurDetectionService.saveOrUpdateBlur(blurDetectionDTO));
}
@GetMapping("/get")
@Operation(summary = "根据摄像头id查询模糊配置")
public ApiResult<BlurDetectionVO> getById(@RequestParam Long id) {
QueryWrapper wrapper = blurDetectionService.query().eq(BlurDetection::getCameraId, id);
BlurDetection blurDetection = blurDetectionService.getOne(wrapper);
if (blurDetection == null) {
return ApiResult.success(null);
}
return ApiResult.success(BeanCopyUtils.copy(blurDetection, BlurDetectionVO.class));
}
}

@ -0,0 +1,34 @@
package com.sz.admin.monitor.controller;
import com.sz.admin.monitor.pojo.po.ComputerRoom;
import com.sz.admin.monitor.service.ComputerRoomService;
import com.sz.core.common.entity.ApiResult;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Profile;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
/**
* ClassName: ComputerRootController
* Package: com.sz.admin.monitor.controller
* Description:
*/
@Tag(name = "机房表")
@RestController
@RequestMapping("computerRoom")
@RequiredArgsConstructor
@Profile({"dev", "local", "preview"})
public class ComputerRoomController {
private final ComputerRoomService computerRoomService;
@Operation(summary = "获取变电站下的机房列表")
@GetMapping("/list")
public ApiResult<List<ComputerRoom>> getList(@RequestParam("substationId") Long substationId) {
return ApiResult.success(computerRoomService.getComputerRoomList(substationId));
}
}

@ -0,0 +1,49 @@
package com.sz.admin.monitor.controller;
import cn.dev33.satoken.annotation.SaIgnore;
import com.sz.admin.monitor.pojo.dto.dataModel.DataModelDTO;
import com.sz.admin.monitor.pojo.que.dataModel.DataModelQue;
import com.sz.admin.monitor.service.impl.DataModelServiceImpl;
import com.sz.core.common.entity.ApiResult;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
/**
* @author xq
* @description:
* @date 2026/3/14 12:35
*/
@Slf4j
@RestController
@RequestMapping("/data/model")
public class DataModelController {
@Autowired
private DataModelServiceImpl dataModelService;
@PostMapping("/getModelData")
@SaIgnore
public ApiResult<DataModelDTO> getModelData(@RequestBody DataModelQue que) {
return dataModelService.getModelData(que);
}
/**
*
*
* @param dataModelDTO
* @return
*/
@PostMapping("/saveOrUpdate/modelData")
public ApiResult saveOrUpdateModelData(
@RequestBody DataModelDTO dataModelDTO, HttpServletRequest request, HttpServletResponse response) {
return dataModelService.saveOrUpdateModelData(dataModelDTO, request, response);
}
@GetMapping("/test")
public ApiResult test() {
return ApiResult.success(dataModelService.getList());
}
}

@ -11,6 +11,8 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
/**
* ClassName: DeviceController
* Package: com.sz.admin.monitor.controller
@ -30,10 +32,18 @@ public class DeviceController {
return ApiResult.success(deviceService.refresh(id,deviceType));
}
// 设备登录
@Operation(summary = "/设备登录")
@Operation(summary = "设备登录")
@GetMapping("/login")
public ApiResult<?> deviceLogin(@RequestParam("id") Long id)
{
return ApiResult.success(deviceService.deviceLogin(id));
}
// 整个NVR的历史视频的算法分析
@Operation(summary = "整个NVR的历史视频的算法分析")
@GetMapping("/history/analysis")
public ApiResult<?> captureHistoryAndCompose(@RequestParam("ids") List<Long> ids)
{
deviceService.captureHistoryAndCompose(ids);
return ApiResult.success();
}
}

@ -0,0 +1,67 @@
package com.sz.admin.monitor.controller;
import cn.dev33.satoken.annotation.SaIgnore;
import com.sz.admin.monitor.pojo.dto.file.FileEntityDTO;
import com.sz.admin.monitor.pojo.dto.file.FileStorageDTO;
import com.sz.admin.monitor.pojo.que.file.FileStorageQue;
import com.sz.admin.monitor.service.impl.FileServiceImpl;
import com.sz.core.common.entity.ApiResult;
import com.sz.core.common.entity.PageResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
/**
* @author xq
* @description:
* @date 2026/2/2 22:31
*/
@RestController
@RequestMapping("/fileStorage")
public class FileController {
@Autowired
private FileServiceImpl fileService;
@GetMapping("/deleteFileById")
public ApiResult<String> deleteFileById(@RequestParam("id") String id){
return fileService.deleteFileById(id);
}
@PostMapping("/editFileNameById")
public ApiResult<String> editFileNameById(@RequestBody FileEntityDTO dto){
return fileService.editFileNameById(dto);
}
@PostMapping("/file/list")
public ApiResult<PageResult<FileEntityDTO>> getFileObjectList(@RequestBody FileStorageQue que){
return fileService.getFileObjectList(que);
}
@GetMapping("/getPreviewFile/{id}")
@SaIgnore
public ResponseEntity<byte[]> getPreviewFile(@PathVariable String id){
return fileService.getPreviewFile(id);
}
@GetMapping("/getFile")
@SaIgnore
public ApiResult<FileStorageDTO> getFile(@RequestParam("id") String id) {
return fileService.getFile(id);
}
@PostMapping("/saveFile")
@SaIgnore
public ApiResult<FileStorageDTO> saveFile(@RequestParam("file") MultipartFile file) {
return fileService.saveFile(file);
}
@GetMapping("/test")
public void test01(){
fileService.test01();
}
}

@ -1,6 +1,7 @@
package com.sz.admin.monitor.controller;
import com.sz.admin.monitor.pojo.dto.edgebox.AlgorithmTaskDTO;
import com.sz.admin.monitor.pojo.po.RecordFile;
import com.sz.admin.monitor.pojo.vo.watchful.WatchfulVO;
import com.sz.admin.monitor.service.IpChannelService;
import com.sz.admin.monitor.utils.AlgMediaConfigResponse;
@ -11,6 +12,8 @@ import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Profile;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
* ClassName: IpChannelController
* Package: com.sz.admin.monitor.controller
@ -97,4 +100,21 @@ public class IpChannelController {
return ApiResult.success(ipChannelService.configAlg(algTaskConfigDto));
}
// 抓取历史视频的图片
@Operation(summary = "抓取历史视频的图片并进行对比")
@GetMapping("/capture/history")
public ApiResult<Void> captureHistoryAndCompose(@RequestParam("id") Long id) {
ipChannelService.captureHistoryAndCompose(id);
return ApiResult.success();
}
// 按照时间范围获取录像
@Operation(summary = "按照时间范围获取录像")
@GetMapping("/getVideoByTime")
public ApiResult<List<RecordFile>> getVideoByTime(@RequestParam("id") Long id,
@RequestParam("startTime") String startTime,
@RequestParam("endTime") String endTime) {
return ApiResult.success(ipChannelService.getVideoByTime(id, startTime, endTime));
}
}

@ -39,4 +39,9 @@ public class TreeController {
public ApiResult<List<TreeNodeVO>> getTreePreview() {
return ApiResult.success(treeService.buildTreePreview());
}
@Operation(summary = "获取变电站的机房的树型结构数据")
@GetMapping("/substation")
public ApiResult<List<TreeNodeVO>> getTreeSubstation() {
return ApiResult.success(treeService.buildTreeComputeRoom());
}
}

@ -13,7 +13,8 @@ public enum AlarmReportEnums {
FIRE_ALARM("Fire",2,"明烟明火报警"),
FACE_ID_ALARM("FaceId",3,"人脸识别报警"),
CAPTURE_FACE_ALARM("CaptureFace", 4, "抓拍到人脸报警"),
HELMET_ALARM("NoHelmet", 5, "未戴安全帽报警");
HELMET_ALARM("NoHelmet", 5, "未戴安全帽报警"),
BLUR_ALARM("Blur", 6, "模糊报警");
private final String alarmType;
private final Integer alarmCode;
private final String alarmDescription;

@ -0,0 +1,12 @@
package com.sz.admin.monitor.mapper;
import com.mybatisflex.core.BaseMapper;
import com.sz.admin.monitor.pojo.po.BlurDetection;
/**
* ClassName: BlurDetectionMapper
* Package: com.sz.admin.monitor.mapper
* Description:
*/
public interface BlurDetectionMapper extends BaseMapper<BlurDetection> {
}

@ -0,0 +1,13 @@
package com.sz.admin.monitor.mapper;
import com.mybatisflex.core.BaseMapper;
import com.sz.admin.monitor.pojo.po.CanvasCfgDO;
/**
* @description:
* @author xq
* @version 1.0
*/
public interface CanvasCfgMapper extends BaseMapper<CanvasCfgDO> {
}

@ -0,0 +1,12 @@
package com.sz.admin.monitor.mapper;
import com.mybatisflex.core.BaseMapper;
import com.sz.admin.monitor.pojo.po.ComputerRoom;
/**
* ClassName: ComputeRoomMapper
* Package: com.sz.admin.monitor.mapper
* Description:
*/
public interface ComputeRoomMapper extends BaseMapper<ComputerRoom> {
}

@ -0,0 +1,8 @@
package com.sz.admin.monitor.mapper;
import com.mybatisflex.core.BaseMapper;
import com.sz.admin.monitor.pojo.po.FileStorageDO;
public interface FileStorageMapper extends BaseMapper<FileStorageDO> {
}

@ -0,0 +1,13 @@
package com.sz.admin.monitor.mapper;
import com.mybatisflex.core.BaseMapper;
import com.sz.admin.monitor.pojo.po.GridCfgDO;
/**
* @description:
* @author xq
* @version 1.0
*/
public interface GridCfgMapper extends BaseMapper<GridCfgDO> {
}

@ -0,0 +1,25 @@
package com.sz.admin.monitor.mapper;
import com.mybatisflex.core.BaseMapper;
import com.mybatisflex.core.query.QueryWrapper;
import com.mybatisflex.core.update.UpdateChain;
import com.sz.admin.monitor.pojo.po.ModelContentDO;
import java.util.Set;
/**
* @description:
* @author xq
* @version 1.0
*/
public interface ModelContentMapper extends BaseMapper<ModelContentDO> {
default void deleteByRoomIds(Set<Long> roomIds)
{
QueryWrapper wrapper = QueryWrapper.create()
.select()
.from(ModelContentDO.class)
.where(ModelContentDO::getRoomId).in(roomIds);
this.deleteByQuery(wrapper);
}
}

@ -0,0 +1,8 @@
package com.sz.admin.monitor.mapper;
import com.mybatisflex.core.BaseMapper;
import com.sz.admin.monitor.pojo.po.Substation;
import com.sz.admin.monitor.pojo.po.UserModelContentDO;
public interface UserModelContentMapper extends BaseMapper<UserModelContentDO> {
}

@ -0,0 +1,13 @@
package com.sz.admin.monitor.pojo.dto.blurDetection;
import com.sz.admin.monitor.pojo.po.BlurDetection;
import lombok.Data;
/**
* ClassName: BlurDetectionDTO
* Package: com.sz.admin.monitor.pojo.dto.blurDetection
* Description:
*/
@Data
public class BlurDetectionDTO extends BlurDetection {
}

@ -0,0 +1,37 @@
package com.sz.admin.monitor.pojo.dto.blurDetection;
import com.mybatisflex.annotation.Id;
import com.mybatisflex.annotation.KeyType;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.io.Serial;
import java.time.LocalDateTime;
/**
* ClassName: BlurDetectionUpdateDTO
* Package: com.sz.admin.monitor.pojo.dto.blurDetection
* Description:
*/
@Data
@Schema(description = "BlurDetection更新DTO")
public class BlurDetectionUpdateDTO {
/**
*
*/
private Long id;
/**
* 0- 1-
*/
private Integer enable;
/**
* url
*/
private String url;
}

@ -0,0 +1,122 @@
package com.sz.admin.monitor.pojo.dto.dataModel;
import cn.hutool.core.bean.BeanUtil;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.sz.admin.monitor.pojo.po.CanvasCfgDO;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
*
*
* @author xq
* @description:
* @date 2026/1/29 11:32
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class CanvasCfgDTO {
/**
* id
*/
private String id;
/**
* id
*/
private String userId;
/**
*
*/
private Integer width;
/**
*
*/
private Integer height;
/**
*
*/
private Double scale;
/**
*
*/
private String color;
/**
*
*/
private String img;
/**
*
*/
private Boolean guide;
/**
*
*/
private Boolean adsorp;
/**
*
*/
@JsonProperty("adsorp_diff")
private Double adsorpDiff;
/**
* json
*/
@JsonProperty("transform_origin")
private CoordinatePoint transformOrigin;
/**
* json
*/
@JsonProperty("drag_offset")
private CoordinatePoint dragOffset;
@Data
@NoArgsConstructor
@AllArgsConstructor
public static class CoordinatePoint {
private Integer x;
private Integer y;
public void setX(Integer x) {
this.x = x;
}
public void setY(Integer y) {
this.y = y; // 修正这里的错误赋值
}
}
/**
*
*
* @param dto
* @return
*/
public static CanvasCfgDO dtoConvertDO(CanvasCfgDTO dto) {
CanvasCfgDO canvasCfgDO = BeanUtil.copyProperties(dto, CanvasCfgDO.class);
ObjectMapper objectMapper = new ObjectMapper();
try {
String transformOrigin = objectMapper.writeValueAsString(dto.getTransformOrigin());
String dragOffset = objectMapper.writeValueAsString(dto.getDragOffset());
canvasCfgDO.setTransformOrigin(transformOrigin);
canvasCfgDO.setDragOffset(dragOffset);
return canvasCfgDO;
} catch (JsonProcessingException e) {
throw new RuntimeException(e);
}
}
}

@ -0,0 +1,51 @@
package com.sz.admin.monitor.pojo.dto.dataModel;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
/**
* @author xq
* @description:
* @date 2026/1/29 11:47
*/
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class DataModelDTO {
/**
*
*/
private CanvasCfgDTO canvasCfg;
/**
* ID
*/
private Long substationId;
/**
*ID
*/
private Long roomId;
/**
*
*/
private GridCfgDTO gridCfg;
/**
*
*/
private List<ModelContentDTO> json;
/**
*
*/
private String menuType;
}

@ -0,0 +1,53 @@
package com.sz.admin.monitor.pojo.dto.dataModel;
import cn.hutool.core.bean.BeanUtil;
import com.sz.admin.monitor.pojo.po.GridCfgDO;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
*
* @description:
* @author xq
* @date 2026/1/29 11:35
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class GridCfgDTO {
/**
* id
*/
private String id;
/**
* id
*/
private String userId;
/**
*
*/
private Boolean enabled;
/**
*
*/
private Boolean align;
/**
*
*/
private Integer size;
/**
*
* @param dto
* @return
*/
public static GridCfgDO dtoConvertDO(GridCfgDTO dto){
GridCfgDO gridCfgDO = BeanUtil.copyProperties(dto, GridCfgDO.class);
return gridCfgDO;
}
}

@ -0,0 +1,154 @@
package com.sz.admin.monitor.pojo.dto.dataModel;
import cn.hutool.core.bean.BeanUtil;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.sz.admin.monitor.pojo.po.ModelContentDO;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.math.BigDecimal;
import java.util.List;
import java.util.Map;
/**
*
* @description:
* @author xq
* @version 1.0
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class ModelContentDTO {
/**
* id
*/
private String id;
/**
*
*/
private Integer modelIndex=99;
/**
* ID
*/
private Long substationId;
/**
*ID
*/
private Long roomId;
/**
*
*/
private String title;
/**
*
*/
private String type;
/**
* json
*/
private Place binfo;
/**
*
*/
private Boolean resize;
/**
*
*/
private Boolean rotate;
/**
*
*/
private Boolean lock;
/**
*
*/
private Boolean active;
/**
*
*/
private Boolean hide;
/**
* json
*/
private Map<String,String> props;
/**
* vue
*/
private String tag;
/**
* json
*/
@JsonProperty("common_animations")
private Animation commonAnimations;
/**
*
*/
private List<String> events;
@Data
@NoArgsConstructor
@AllArgsConstructor
public static class Place{
private BigDecimal left;
private BigDecimal top;
private BigDecimal width;
private BigDecimal height;
private BigDecimal angle;
}
@Data
@NoArgsConstructor
@AllArgsConstructor
public static class Animation{
private String val;
private String delay;
private String speed;
private String repeat;
}
/**
*
* @param dto
* @return
*/
public static ModelContentDO dtoConvertDO(ModelContentDTO dto){
ModelContentDO modelContentDO = BeanUtil.copyProperties(dto, ModelContentDO.class);
ObjectMapper objectMapper = new ObjectMapper();
try {
String binfo = objectMapper.writeValueAsString(dto.getBinfo());
String commonAnimations = objectMapper.writeValueAsString(dto.getCommonAnimations());
String props = objectMapper.writeValueAsString(dto.getProps());
modelContentDO.setBinfo(binfo);
modelContentDO.setCommonAnimations(commonAnimations);
modelContentDO.setProps(props);
} catch (JsonProcessingException e) {
throw new RuntimeException(e);
}
return modelContentDO;
}
}

@ -0,0 +1,38 @@
package com.sz.admin.monitor.pojo.dto.dataModel;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.Date;
/**
* @author xq
* @description:
* @date 2026/1/29 11:50
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class UserModelContentDTO {
/**
* id
*/
private String id;
/**
* id
*/
private String userId;
/**
*
*/
private String menuType;
/**
*
*/
private String modelContentId;
}

@ -23,17 +23,14 @@ public class BoxAlarmReportDto {
private String cameraNo;
@Schema(description = "摄像头ID")
private Long cameraId;
@Schema(description = "报警的url")
private String url;
@Schema(description = "报警的类型")
private String alarmReportType;
private String alarmTypeDesc;
@Schema(description = "报警的枚举值")
private Integer alarmType;
@Schema(description = "报警的时间")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime alarmReportTime;
private Long alarmTime;
@Schema(description = "基准图")
private String baseImage;
@Schema(description = "抓拍图")
private String captureImage;
@Schema(description = "报警的原因")
private String description;
@Schema(description = "报警图")
private String alarmImage;
}

@ -0,0 +1,38 @@
package com.sz.admin.monitor.pojo.dto.file;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @author xq
* @description:
* @date 2026/2/3 14:27
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class FileEntityDTO {
/**
* id
*/
private String id;
/**
*
*/
private String fileName;
/**
*
*/
private Long addTime;
/**
* path
*/
private String filePath;
}

@ -0,0 +1,61 @@
package com.sz.admin.monitor.pojo.dto.file;
import cn.hutool.core.bean.BeanUtil;
import com.sz.admin.monitor.pojo.po.FileStorageDO;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.Date;
/**
* @author xq
* @description:
* @date 2026/2/2 22:18
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class FileStorageDTO {
/**
* id
*/
private String id;
/**
*
*/
private String fileUrl;
/**
*
*/
private String fileSize;
/**
*
*/
private String fileName;
/**
*
*/
private String fileSuffix;
/**
* base64
*/
private String base64Data;
/**
*
*/
private Date addTime;
public static FileStorageDO dtoConvertDO(FileStorageDTO dto) {
return BeanUtil.copyProperties(dto, FileStorageDO.class);
}
}

@ -71,12 +71,7 @@ public class AlgorithmTask implements Serializable {
@Column(typeHandler = JacksonTypeHandler.class)
private JsonNode userData;
/**
* 0-1-
*/
@Column(isLogicDelete = true)
@Schema(description = "是否删除")
private String isDeleted;
/**
*

@ -0,0 +1,62 @@
package com.sz.admin.monitor.pojo.po;
import com.mybatisflex.annotation.Id;
import com.mybatisflex.annotation.KeyType;
import com.mybatisflex.annotation.Table;
import com.sz.mysql.EntityChangeListener;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
import java.time.LocalDateTime;
/**
* ClassName: BlurDetection
* Package: com.sz.admin.monitor.pojo.po
* Description:
*/
@Data
@Table(value = "ry_blur_detection", onInsert = EntityChangeListener.class, onUpdate = EntityChangeListener.class)
@Schema(description = "模糊检测表")
public class BlurDetection implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
*
*/
@Id(keyType = KeyType.Auto)
private Long id;
/**
* id
*/
private Long cameraId;
/**
*
*/
private String cameraName;
/**
* 0- 1-
*/
private Integer enable;
/**
* url
*/
private String url;
/**
*
*/
private LocalDateTime createTime;
/**
*
*/
private LocalDateTime updateTime;
}

@ -79,12 +79,7 @@ public class Camera implements Serializable {
@Schema(description = "在线状态1-在线, 0-离线")
private Integer status;
/**
* 0-1-
*/
@Column(isLogicDelete = true)
@Schema(description = "是否删除")
private String isDeleted;
@Schema(description = "创建时间")
private LocalDateTime createTime;

@ -50,7 +50,7 @@ public class CameraAlarm implements Serializable {
@Schema(description = "告警区域id")
private Long alarmAreaId;
@Schema(description = "报警类型: 1-移位, 2-明烟明火报警,3-人脸识别,4-脸部抓拍,5-安全帽检测")
@Schema(description = "报警类型: 1-移位, 2-明烟明火报警,3-人脸识别,4-脸部抓拍,5-安全帽检测,6-模糊")
private Integer alarmType;
@Schema(description = "基准图路径 ")

@ -39,18 +39,12 @@ public class CameraSnapshot implements Serializable {
@Schema(description = "图片保存路径")
private String imagePath;
@Schema(description = "1-定时巡检, 2-守望归位检测, 3-手动抓拍")
@Schema(description = "1-定时巡检, 2-守望归位检测, 3-手动抓拍,4-模糊检测")
private Integer checkType;
@Schema(description = "0-正常, 1-移位")
private Integer isAbnormal;
/**
* 0-1-
*/
@Column(isLogicDelete = true)
@Schema(description = "是否删除")
private String isDeleted;
@Schema(description = "抓拍时间")
private LocalDateTime createTime;

@ -0,0 +1,159 @@
package com.sz.admin.monitor.pojo.po;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.mybatisflex.annotation.Id;
import com.mybatisflex.annotation.KeyType;
import com.mybatisflex.annotation.Table;
import com.sz.admin.monitor.pojo.dto.dataModel.CanvasCfgDTO;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
*
* @description:
* @author xq
* @date 2026/1/29 11:32
*/
@Table("ry_canvas_cfg")
@Schema(description = "画布配置数据对象")
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class CanvasCfgDO {
/**
* id
*/
@Id(keyType = KeyType.Generator, value = "uuid")
@Schema(description = "面板id")
private String id;
/**
* id
*/
@Schema(description = "用户id")
private String userId;
/**
*
*/
@Schema(description = "宽度")
private Integer width;
/**
*
*/
@Schema(description = "高度")
private Integer height;
/**
*
*/
@Schema(description = "比例")
private Double scale;
/**
*
*/
@Schema(description = "颜色")
private String color;
/**
*
*/
@Schema(description = "图片")
private String img;
/**
*
*/
@Schema(description = "指南")
private Boolean guide;
/**
*
*/
@Schema(description = "吸附")
private Boolean adsorp;
/**
*
*/
@Schema(description = "吸附差分")
private Double adsorpDiff;
/**
* json
*/
@Schema(description = "原点json格式")
private String transformOrigin;
/**
* json
*/
@Schema(description = "拖拽json格式")
private String dragOffset;
/**
* DTO
* @param canvasCfgDO
* @return
*/
@Schema(description = "模型id")
public static CanvasCfgDTO doConvertDTO(CanvasCfgDO canvasCfgDO){
// 创建新的CanvasCfgDTO实例先复制其他属性
CanvasCfgDTO canvasCfgDTO = new CanvasCfgDTO();
// 手动复制除transformOrigin和dragOffset之外的所有基本类型属性
canvasCfgDTO.setId(canvasCfgDO.getId());
canvasCfgDTO.setUserId(canvasCfgDO.getUserId());
canvasCfgDTO.setWidth(canvasCfgDO.getWidth());
canvasCfgDTO.setHeight(canvasCfgDO.getHeight());
canvasCfgDTO.setScale(canvasCfgDO.getScale());
canvasCfgDTO.setColor(canvasCfgDO.getColor());
canvasCfgDTO.setImg(canvasCfgDO.getImg());
canvasCfgDTO.setGuide(canvasCfgDO.getGuide());
canvasCfgDTO.setAdsorp(canvasCfgDO.getAdsorp());
canvasCfgDTO.setAdsorpDiff(canvasCfgDO.getAdsorpDiff());
ObjectMapper objectMapper = new ObjectMapper();
String transformOrigin = canvasCfgDO.getTransformOrigin();
String dragOffset = canvasCfgDO.getDragOffset();
try {
// 单独处理JSON转换 - 添加空值检查
if (transformOrigin != null && !transformOrigin.trim().isEmpty() && !transformOrigin.equals("null")) {
CanvasCfgDTO.CoordinatePoint originPoint = objectMapper.readValue(transformOrigin, CanvasCfgDTO.CoordinatePoint.class);
canvasCfgDTO.setTransformOrigin(originPoint);
}
if (dragOffset != null && !dragOffset.trim().isEmpty() && !dragOffset.equals("null")) {
CanvasCfgDTO.CoordinatePoint dragPoint = objectMapper.readValue(dragOffset, CanvasCfgDTO.CoordinatePoint.class);
canvasCfgDTO.setDragOffset(dragPoint);
}
return canvasCfgDTO;
} catch (JsonProcessingException e) {
throw new RuntimeException("JSON parsing error: " + e.getMessage() + ", JSON: " + transformOrigin, e);
}
}
public static final String ID="id";
public static final String USER_ID="user_id";
public static final String WIDTH = "width";
public static final String HEIGHT = "height";
public static final String SCALE = "scale";
public static final String COLOR = "color";
public static final String IMG = "img";
public static final String GUIDE = "guide";
public static final String ADSORP = "adsorp";
public static final String ADSORP_DIFF = "adsorp_diff";
public static final String TRANSFORM_ORIGIN = "transform_origin";
public static final String DRAG_OFFSET = "drag_offset";
}

@ -0,0 +1,28 @@
package com.sz.admin.monitor.pojo.po;
import com.mybatisflex.annotation.Id;
import com.mybatisflex.annotation.KeyType;
import com.mybatisflex.annotation.Table;
import com.sz.mysql.EntityChangeListener;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
/**
* ClassName: ComputerRoom
* Package: com.sz.admin.monitor.pojo.po
* Description:
*/
@Data
@Table(value = "ry_computer_room", onInsert = EntityChangeListener.class, onUpdate = EntityChangeListener.class)
@Schema(description = "机房表")
public class ComputerRoom {
@Id(keyType = KeyType.Auto)
@Schema(description = "id")
private Long id;
@Schema(description = "名称")
private String name;
@Schema(description = "描述")
private String description;
@Schema(description = "变电站ID")
private Long substationId;
}

@ -0,0 +1,69 @@
package com.sz.admin.monitor.pojo.po;
import com.mybatisflex.annotation.Id;
import com.mybatisflex.annotation.KeyType;
import com.mybatisflex.annotation.Table;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.Date;
/**
* @author xq
* @description:
* @date 2026/2/2 22:18
*/
@Table("ry_file_storage")
@Schema(description = "文件存储数据对象")
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class FileStorageDO {
/**
* id
*/
@Id(keyType = KeyType.Generator, value = "uuid")
@Schema(description = "主键ID")
private String id;
/**
*
*/
@Schema(description = "文件路径")
private String fileUrl;
/**
*
*/
@Schema(description = "文件大小")
private String fileSize;
/**
*
*/
@Schema(description = "文件名称")
private String fileName;
/**
*
*/
@Schema(description = "文件后缀")
private String fileSuffix;
/**
*
*/
@Schema(description = "添加时间")
private Date addTime;
public static final String ID="id";
public static final String FILE_URL="file_url";
public static final String FILE_SIZE="file_size";
public static final String FILE_NAME="file_name";
public static final String FILE_SUFFIX="file_suffix";
public static final String ADD_TIME="add_time";
}

@ -0,0 +1,74 @@
package com.sz.admin.monitor.pojo.po;
import cn.hutool.core.bean.BeanUtil;
import com.mybatisflex.annotation.Id;
import com.mybatisflex.annotation.KeyType;
import com.mybatisflex.annotation.Table;
import com.sz.admin.monitor.pojo.dto.dataModel.GridCfgDTO;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
*
* @description:
* @author xq
* @date 2026/1/29 11:35
*/
@Table("ry_grid_cfg")
@Schema(description = "存储网格的基本配置信息")
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class GridCfgDO {
/**
* id
*/
@Id(keyType = KeyType.Generator, value = "uuid")
@Schema(description = "主键ID")
private String id;
/**
* id
*/
@Schema(description = "用户id")
private String userId;
/**
*
*/
@Schema(description = "网格是否启用")
private Boolean enabled;
/**
*
*/
@Schema(description = "对齐")
private Boolean align;
/**
*
*/
@Schema(description = "大小")
private Integer size;
/**
* DTO
* @param gridCfgDO
* @return
*/
public static GridCfgDTO doConvertDTO(GridCfgDO gridCfgDO){
GridCfgDTO gridCfgDTO = BeanUtil.copyProperties(gridCfgDO, GridCfgDTO.class);
return gridCfgDTO;
}
public static final String ID = "id";
public static final String USER_ID = "user_id";
public static final String ENABLED = "enabled";
public static final String ALIGN = "align";
public static final String SIZE = "size";
}

@ -0,0 +1,188 @@
package com.sz.admin.monitor.pojo.po;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.mybatisflex.annotation.Id;
import com.mybatisflex.annotation.KeyType;
import com.mybatisflex.annotation.Table;
import com.sz.admin.monitor.pojo.dto.dataModel.ModelContentDTO;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.ArrayList;
import java.util.HashMap;
/**
*
* @description:
* @author xq
* @version 1.0
*/
@Table("ry_model_content")
@Schema(description = "存储模型的基本信息和配置")
@Data
@NoArgsConstructor
@AllArgsConstructor
public class ModelContentDO {
/**
* id
*/
@Id(keyType = KeyType.Generator, value = "uuid")
@Schema(description = "模型id")
private String id;
/**
* ID
*/
@Schema(description = "变电站ID")
private Long substationId;
/**
*ID
*/
@Schema(description = "机房ID")
private Long roomId;
/**
*
*/
@Schema(description = "模型索引")
private Integer modelIndex=99;
/**
*
*/
@Schema(description = "模型名称")
private String title;
/**
*
*/
@Schema(description = "模型类型")
private String type;
/**
* json
*/
@Schema(description = "位置json格式")
private String binfo;
/**
*
*/
@Schema(description = "调整大小")
private Boolean resize;
/**
*
*/
@Schema(description = "旋转")
private Boolean rotate;
/**
*
*/
@Schema(description = "锁定")
private Boolean lock;
/**
*
*/
@Schema(description = "动作")
private Boolean active;
/**
*
*/
@Schema(description = "隐藏")
private Boolean hide;
/**
* json
*/
@Schema(description = "属性json格式")
private String props;
/**
* vue
*/
@Schema(description = "vue组件名称")
private String tag;
/**
* json
*/
@Schema(description = "动画json格式")
private String commonAnimations;
/**
*
*/
@Schema(description = "事件")
private String events;
public static final String ID = "id";
public static final String MODEL_INDEX = "model_index";
public static final String TITLE = "title";
public static final String TYPE = "type";
public static final String BINFO = "binfo";
public static final String RESIZE = "resize";
public static final String ROTATE = "rotate";
public static final String LOCK = "lock";
public static final String ACTIVE = "active";
public static final String HIDE = "hide";
public static final String PROPS = "props";
public static final String TAG = "tag";
public static final String COMMON_ANIMATIONS = "common_animations";
public static final String EVENTS = "events";
public static ModelContentDTO doConvertDTO(ModelContentDO modelContentDO) {
if (modelContentDO == null) {
return null;
}
ModelContentDTO modelContentDTO = new ModelContentDTO();
// 基础字段映射
modelContentDTO.setId(modelContentDO.getId());
modelContentDTO.setTitle(modelContentDO.getTitle());
modelContentDTO.setType(modelContentDO.getType());
modelContentDTO.setResize(modelContentDO.getResize());
modelContentDTO.setRotate(modelContentDO.getRotate());
modelContentDTO.setLock(modelContentDO.getLock());
modelContentDTO.setActive(modelContentDO.getActive());
modelContentDTO.setHide(modelContentDO.getHide());
modelContentDTO.setTag(modelContentDO.getTag());
modelContentDTO.setEvents(new ArrayList<>());
ObjectMapper objectMapper = new ObjectMapper();
try {
// JSON 字段转换 - 位置信息
if (modelContentDO.getBinfo() != null && !modelContentDO.getBinfo().trim().isEmpty() && !"null".equals(modelContentDO.getBinfo())) {
ModelContentDTO.Place binfoObj = objectMapper.readValue(modelContentDO.getBinfo(), ModelContentDTO.Place.class);
modelContentDTO.setBinfo(binfoObj);
}
// JSON 字段转换 - 属性
if (modelContentDO.getProps() != null && !modelContentDO.getProps().trim().isEmpty() && !"null".equals(modelContentDO.getProps())) {
HashMap propsObj = objectMapper.readValue(modelContentDO.getProps(), HashMap.class);
modelContentDTO.setProps(propsObj);
}
// JSON 字段转换 - 动画
if (modelContentDO.getCommonAnimations() != null && !modelContentDO.getCommonAnimations().trim().isEmpty() && !"null".equals(modelContentDO.getCommonAnimations())) {
ModelContentDTO.Animation animationsObj = objectMapper.readValue(modelContentDO.getCommonAnimations(), ModelContentDTO.Animation.class);
modelContentDTO.setCommonAnimations(animationsObj);
}
} catch (JsonProcessingException e) {
throw new RuntimeException("JSON parsing error in ModelContentDO conversion: " + e.getMessage(), e);
}
return modelContentDTO;
}
}

@ -44,12 +44,7 @@ public class Preset {
@Schema(description = "上报的url")
private String presetUrl;
/**
* 0-1-
*/
@Column(isLogicDelete = true)
@Schema(description = "是否删除")
private String isDeleted;
@Schema(description = "创建时间")
private LocalDateTime createdTime;

@ -0,0 +1,53 @@
package com.sz.admin.monitor.pojo.po;
import com.mybatisflex.annotation.Id;
import com.mybatisflex.annotation.KeyType;
import com.mybatisflex.annotation.Table;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
import java.util.Date;
/**
* @description:
* @author xq
* @version 1.0
*/
@Table("ry_user_model_content")
@Schema(description = "用户模型中间表")
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class UserModelContentDO implements Serializable {
/**
* id
*/
@Id(keyType = KeyType.Generator, value = "uuid")
@Schema(description = "主键ID")
private String id;
/**
* id
*/
@Schema(description = "用户id")
private String userId;
/**
*
*/
@Schema(description = "目录类型")
private String menuType;
/**
*
*/
@Schema(description = "模型内容")
private String modelContentId;
public static final String ID="id";
public static final String USER_ID="user_id";
public static final String MENU_TYPE="menu_type";
public static final String MODEL_CONTENT_ID="model_content_id";
}

@ -0,0 +1,36 @@
package com.sz.admin.monitor.pojo.que;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
/**
* @author xq
* @description:
* @date 2026/2/3 14:21
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class BasePage<T> {
private List<T> list;
/**
*
*/
private long total;
/**
*
*/
private long size;
/**
*
*/
private long current;
/**
*
*/
private long pages;
}

@ -0,0 +1,38 @@
package com.sz.admin.monitor.pojo.que;
import cn.hutool.core.util.ObjectUtil;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @author xq
* @description:
* @date 2026/2/3 13:36
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class BaseQue {
/**
*
*/
private Integer pageNum;
/**
*
*/
private Integer pageSize;
/**
*
* @param base
*/
// public static <T> Page<T> init(BaseQue base,Class<T> cla){
// if(ObjectUtil.isEmpty(base))
// return null;
// base.setPageNum(ObjectUtil.isNotEmpty(base.getPageNum())?base.getPageNum():0);
// base.setPageSize(ObjectUtil.isNotEmpty(base.getPageSize())?base.getPageSize():10);
// return new Page<>(base.getPageNum(), base.getPageSize());
// }
}

@ -0,0 +1,31 @@
package com.sz.admin.monitor.pojo.que.dataModel;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @author xq
* @description:
* @date 2026/1/29 21:47
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class DataModelQue {
/**
* ID
*/
private String userId;
/**
*
*/
private String menuType;
/**
* ID
*/
private Long roomId;
}

@ -0,0 +1,46 @@
package com.sz.admin.monitor.pojo.que.file;
import com.sz.admin.monitor.pojo.que.BaseQue;
import com.sz.core.common.entity.PageQuery;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import java.util.Date;
/**
* @author xq
* @description:
* @date 2026/2/3 13:35
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode(callSuper = true)
@Schema(description = "文件查询Que")
public class FileStorageQue extends PageQuery {
/**
* id
*/
@Schema(description = "id")
private String id;
/**
*
*/
@Schema(description = "文件名称")
private String fileName;
/**
*
*/
@Schema(description = "开始时间")
private Long startTime;
/**
*
*/
@Schema(description = "结束时间")
private Long endTime;
}

@ -0,0 +1,56 @@
package com.sz.admin.monitor.pojo.vo.blurDetection;
import com.mybatisflex.annotation.Id;
import com.mybatisflex.annotation.KeyType;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.io.Serial;
import java.time.LocalDateTime;
/**
* ClassName: BlurDetectionVO
* Package: com.sz.admin.monitor.pojo.vo.blurDetection
* Description:
*/
@Data
@Schema(description = "BlurDetection返回vo")
public class BlurDetectionVO {
/**
*
*/
private Long id;
/**
* id
*/
private Long cameraId;
/**
*
*/
private String cameraName;
/**
* 0- 1-
*/
private Integer enable;
/**
* url
*/
private String url;
/**
*
*/
private LocalDateTime createTime;
/**
*
*/
private LocalDateTime updateTime;
}

@ -32,7 +32,7 @@ public class CameraSnapshotVO {
@Schema(description = "图片保存路径")
private String imagePath;
@Schema(description = "1-定时巡检, 2-守望归位检测, 3-手动抓拍")
@Schema(description = "1-定时巡检, 2-守望归位检测, 3-手动抓拍,4-模糊检测")
private Integer checkType;
@Schema(description = "0-正常, 1-移位")

@ -0,0 +1,13 @@
package com.sz.admin.monitor.pojo.vo.tree;
import lombok.Data;
/**
* ClassName: ComputerRoomNodeVO
* Package: com.sz.admin.monitor.pojo.vo.tree
* Description:
*/
@Data
public class ComputerRoomNodeVO extends TreeNodeVO{
private Long substationId; //所属变电站
}

@ -17,7 +17,7 @@ import java.util.List;
public class TreeNodeVO {
private Long id;
private String name;
private Integer type; // 0: Region, 1: Substation, 2: NVR,3: Camera
private Integer type; // 0: Region, 1: Substation, 2: NVR,3: Camera,4: room
private List<TreeNodeVO> children;
public TreeNodeVO(Long id, String name, Integer type) {
this.id = id;

@ -1,5 +1,7 @@
package com.sz.admin.monitor.sdk;
import com.sz.admin.monitor.sdk.hkSdk.HCNetSDK;
/**
* ClassName: AbstractNVR
* Package: com.sz.admin.monitor.hik
@ -39,4 +41,14 @@ public abstract class AbstractNVR {
* @return true false
*/
public abstract String capturePic(int luerId,int iChannel,String fileName);
/**
*
*/
public abstract boolean captureHistoryImage(int luerId, int iChannel,
HCNetSDK.NET_DVR_TIME startDvrTime,
HCNetSDK.NET_DVR_TIME stopDvrTime,
String tempVideoPath,
String finalImagePath);
}

@ -1,6 +1,8 @@
package com.sz.admin.monitor.sdk;
import cn.hutool.core.lang.UUID;
import cn.hutool.core.util.RandomUtil;
import com.mybatisflex.core.query.QueryWrapper;
import com.sz.admin.monitor.pojo.po.Camera;
import com.sz.admin.monitor.pojo.po.Nvr;
@ -34,6 +36,10 @@ import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicInteger;
/**
* NVR
@ -56,13 +62,14 @@ public class ManageNVR {
private VcrlUserIdContainer vcrlUserIdContainer;
@Resource
private DataScopeProperties dataScopeProperties;
private final ExecutorService executor = Executors.newFixedThreadPool(5);
/**
* sdknvr
*/
@Bean
public Object nvrInit() {
//海康sdk注册
// //海康sdk注册
HCNetSDK hcNetSDK = hkNVR.registerPlugin();
Nvr nvr = new Nvr();
nvr.setDriver(0);
@ -749,4 +756,124 @@ public class ManageNVR {
Map<String, Integer> map = hkNVR.NET_DVR_GetPTZPos(userId, camera.getChannelId());
return BeanCopyUtils.copy(map, PTZVO.class);
}
// 进行历史视频的抓图
public void captureHistoryImage(String taskDir, Long id) {
Camera camera = cameraService.getById(id);
Integer userId = (Integer) vcrlUserIdContainer.getlUserId(camera.getNvrId().intValue());
// 收集前一个月的每个小时的时间点
List<LocalDateTime> points = new ArrayList<>();
LocalDateTime endTime = LocalDateTime.now().withMinute(0).withSecond(0);
LocalDateTime startTime = endTime.minusDays(7);
LocalDateTime current = startTime;
while (current.isBefore(endTime) || current.equals(endTime)) {
points.add(current);
current = current.plusHours(1);
}
int totalSizes = points.size();
// 创建固定大小的线程池
ExecutorService threadPool = Executors.newFixedThreadPool(5);
// 统计进度的原子类
AtomicInteger successCount = new AtomicInteger(0);
AtomicInteger failCount = new AtomicInteger(0);
AtomicInteger finishedCount = new AtomicInteger(0);
DateTimeFormatter fmt = DateTimeFormatter.ofPattern("yyyyMMdd_HHmmss");
List<CompletableFuture<Void>> futures = new ArrayList<>();
// 将任务全部丢进线程池
for (LocalDateTime time : points) {
CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
String fileName = "history_"+camera.getId()+ time.format(fmt) + ".jpg";
File file = captureAtTime(userId, camera.getChannelId(), time, taskDir, fileName);
// 记录当前完成的次数
int currentFinished = finishedCount.incrementAndGet();
if (file != null) {
successCount.incrementAndGet();
// System.out.println(String.format("[进度 %d/%d] 成功: %s", currentFinished, totalSizes, fileName));
} else {
failCount.incrementAndGet();
// System.out.println(String.format("[进度 %d/%d] 失败: %s", currentFinished, totalSizes, fileName));
}
}, threadPool);
// 添加任务
futures.add(future);
}
// 阻塞主线程等待所有720个任务全部跑完
CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])).join();
// 关闭线程池
executor.shutdown();
// System.out.println("总任务数量:" + totalSizes);
// System.out.println("成功抓取:" + successCount.get() + "张");
// System.out.println("失败:" + failCount.get() + "张");
// System.out.println("图片已全部保存在:" + "D:\\work\\temp\\");
}
/**
*
*
* @param userId userId
* @param channelId
* @param time (Java 8 LocalDateTime)
* @param dir ( / \\ "D:/temp/")
* @param fileName ( "pic_120000.jpg")
* @return File File null
*/
private File captureAtTime(int userId, int channelId, LocalDateTime time, String dir, String fileName) {
LocalDateTime stopTime = time.plusSeconds(5);
// 将 Java 的 LocalDateTime 翻译成海康 SDK 认识的底层结构体
HCNetSDK.NET_DVR_TIME startDvrTime = convertToDvrTime(time);
HCNetSDK.NET_DVR_TIME stopDvrTime = convertToDvrTime(stopTime);
String tempVideoPath = dir + "temp_slice_" + UUID.randomUUID() + ".mp4";
String finalImagePath = dir + fileName;
try {
hkNVR.captureHistoryImage(
userId,
channelId,
startDvrTime,
stopDvrTime,
tempVideoPath,
finalImagePath
);
// 抓图流程走完后,检查图片是否真的生成成功了
File resultImage = new File(finalImagePath);
if (resultImage.exists() && resultImage.length() > 0) {
return resultImage;
} else {
return null; // 抓图失败(可能是那个时间点设备断网或无录像)
}
} catch (Exception e) {
return null;
} finally {
File tempFile = new File(tempVideoPath);
if (tempFile.exists()) {
tempFile.delete();
}
}
}
private HCNetSDK.NET_DVR_TIME convertToDvrTime(LocalDateTime currentTime) {
HCNetSDK.NET_DVR_TIME netDvrTime = new HCNetSDK.NET_DVR_TIME();
netDvrTime.dwYear = (short) currentTime.getYear();
netDvrTime.dwMonth = (short) currentTime.getMonthValue();
netDvrTime.dwDay = (short) currentTime.getDayOfMonth();
netDvrTime.dwHour = (short) currentTime.getHour();
netDvrTime.dwMinute = (short) currentTime.getMinute();
netDvrTime.dwSecond = (short) currentTime.getSecond();
return netDvrTime;
}
// 按照时间范围获取录像文件
public List<RecordFile> getRecordFileByTime(Long id, LocalDateTime startTime, LocalDateTime endTime) {
Camera camera = cameraService.getById(id);
List<RecordFile> recordFile = new ArrayList<>();
Integer userId = (Integer) vcrlUserIdContainer.getlUserId(camera.getNvrId().intValue());
try {
recordFile = hkNVR.findRecordFile(userId, camera.getChannelId(), startTime, endTime);
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(e);
}
return recordFile;
}
}

@ -688,7 +688,7 @@ public interface HCNetSDK extends Library {
public static final int NET_DVR_GET_CCDPARAMCFG_EX = 3368;//获取前端参数(扩展)
public static final int NET_DVR_SET_CCDPARAMCFG_EX = 3369;//设置前端参数(扩展)
public static final int NET_DVR_GET_FOCUSMODECFG = 3305;//获取快球聚焦模式信息
public static final int NET_DVR_SET_FOCUSMODECFG = 3306;//设置快球聚焦模式信息
public static final int NET_DVR_SET_FOCUSMODECFG = 13306;//设置快球聚焦模式信息
public static final int NET_DVR_GET_SUPPLEMENTLIGHT = 3728; //获取内置补光灯配置协议
public static final int NET_DVR_SET_SUPPLEMENTLIGHT = 3729; //设置内置补光灯配置协议

@ -14,6 +14,8 @@ import com.sz.admin.monitor.utils.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
@ -139,6 +141,81 @@ public class HkNVR extends AbstractNVR {
public String capturePic(int luerId, int iChannel,String fileName) {
return captureP(luerId, iChannel,fileName);
}
@Override
public boolean captureHistoryImage(int luerId, int iChannel,
HCNetSDK.NET_DVR_TIME startDvrTime,
HCNetSDK.NET_DVR_TIME stopDvrTime,
String tempVideoPath,
String finalImagePath) {
// 1. 构建下载条件结构体
HCNetSDK.NET_DVR_PLAYCOND downloadCond = new HCNetSDK.NET_DVR_PLAYCOND();
downloadCond.dwChannel = iChannel;
// 设置开始时间
downloadCond.struStartTime.dwYear = startDvrTime.dwYear;
downloadCond.struStartTime.dwMonth = startDvrTime.dwMonth;
downloadCond.struStartTime.dwDay = startDvrTime.dwDay;
downloadCond.struStartTime.dwHour = startDvrTime.dwHour;
downloadCond.struStartTime.dwMinute = startDvrTime.dwMinute;
downloadCond.struStartTime.dwSecond = startDvrTime.dwSecond;
// 设置结束时间
downloadCond.struStopTime.dwYear = stopDvrTime.dwYear;
downloadCond.struStopTime.dwMonth = stopDvrTime.dwMonth;
downloadCond.struStopTime.dwDay = stopDvrTime.dwDay;
downloadCond.struStopTime.dwHour = stopDvrTime.dwHour;
downloadCond.struStopTime.dwMinute = stopDvrTime.dwMinute;
downloadCond.struStopTime.dwSecond = stopDvrTime.dwSecond;
downloadCond.write();
// 2. 获取下载句柄
int lDownloadHandle = hCNetSDK.NET_DVR_GetFileByTime_V40(luerId, tempVideoPath, downloadCond);
if (lDownloadHandle == -1) {
System.out.println("建立下载通道失败,错误码:" + hCNetSDK.NET_DVR_GetLastError());
return false;
}
// 3. 发送下载控制指令
boolean playControl = hCNetSDK.NET_DVR_PlayBackControl_V40(lDownloadHandle, HCNetSDK.NET_DVR_PLAYSTART, null, 0, null, null);
if (!playControl) {
System.out.println("发送下载控制指令失败,错误码:" + hCNetSDK.NET_DVR_GetLastError());
hCNetSDK.NET_DVR_StopGetFile(lDownloadHandle); //下载用的接口,停止必须用 StopGetFile不能用 StopPlayBack
return false; // 如果指令发送失败,必须 return 终止,不能往下走
}
// 给操作系统 1 秒钟的缓冲时间,确保视频文件彻底写入硬盘并解除占用
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
// 7. 调用 ffmpeg 进行抽取图片
ProcessBuilder processBuilder = new ProcessBuilder(
"ffmpeg", "-y", "-err_detect", "ignore_err", "-i", tempVideoPath, "-vframes", "1", "-q:v", "2", "-f", "image2", finalImagePath
);
// 重定向 FFmpeg 的输出流,防止缓冲区撑满导致 Java 进程死锁卡住
processBuilder.redirectErrorStream(true);
try {
Process process = processBuilder.start();
java.io.InputStream inputStream = process.getInputStream();
byte[] buffer = new byte[1024];
while (inputStream.read(buffer) != -1) {
// 静默读取,不打印,清空缓冲区
}
// 等待 FFmpeg 执行完毕
int exitCode = process.waitFor();
if (exitCode == 0) {
return true;
} else {
return false;
}
} catch (IOException | InterruptedException e) {
System.out.println("ffmpeg 执行失败:" + e);
return false;
}
}
/**
*
*

@ -0,0 +1,14 @@
package com.sz.admin.monitor.service;
import com.mybatisflex.core.service.IService;
import com.sz.admin.monitor.pojo.dto.blurDetection.BlurDetectionDTO;
import com.sz.admin.monitor.pojo.po.BlurDetection;
/**
* ClassName: BlurDetectionService
* Package: com.sz.admin.monitor.service
* Description:
*/
public interface BlurDetectionService extends IService<BlurDetection> {
Boolean saveOrUpdateBlur(BlurDetectionDTO blurDetectionDTO);
}

@ -25,4 +25,7 @@ public interface CameraSnapshotService extends IService<CameraSnapshot> {
// 根据摄像头ID查询快照列表
List<CameraSnapshotVO> getExistSnapshotList(Long id);
void deleteByCameraIdAndType(Long cameraId, int i);
CameraSnapshotVO selectByCameraIdAndType(Long cameraId, int i);
}

@ -0,0 +1,15 @@
package com.sz.admin.monitor.service;
import com.mybatisflex.core.service.IService;
import com.sz.admin.monitor.pojo.dto.dataModel.CanvasCfgDTO;
import com.sz.admin.monitor.pojo.po.CanvasCfgDO;
/**
* @description:
* @author xq
* @version 1.0
*/
public interface CanvasCfgService extends IService<CanvasCfgDO> {
void saveOrUpdateCanvas(CanvasCfgDTO canvasCfgDTO);
}

@ -0,0 +1,17 @@
package com.sz.admin.monitor.service;
import com.mybatisflex.core.service.IService;
import com.sz.admin.monitor.pojo.po.CanvasCfgDO;
import com.sz.admin.monitor.pojo.po.ComputerRoom;
import java.util.List;
/**
* ClassName: ComputerRoomService
* Package: com.sz.admin.monitor.service
* Description:
*/
public interface ComputerRoomService extends IService<ComputerRoom> {
// 获取变电站的机房列表
List<ComputerRoom> getComputerRoomList(Long substationId);
}

@ -3,6 +3,8 @@ package com.sz.admin.monitor.service;
import com.mybatisflex.core.service.IService;
import com.sz.admin.monitor.pojo.po.Nvr;
import java.util.List;
/**
* ClassName: DeviceService
* Package: com.sz.admin.monitor.service
@ -13,4 +15,7 @@ public interface DeviceService extends IService<Nvr> {
// 设备登录
Object deviceLogin(Long id);
// 历史视频的算法分析
void captureHistoryAndCompose(List<Long> ids);
}

@ -0,0 +1,13 @@
package com.sz.admin.monitor.service;
import com.mybatisflex.core.service.IService;
import com.sz.admin.monitor.pojo.po.FileStorageDO;
/**
* @author xq
* @description:
* @date 2026/2/2 22:18
*/
public interface FileStorageService extends IService<FileStorageDO> {
}

@ -13,5 +13,5 @@ public interface ForwardService {
/**
*
*/
void enrichAndForward(BoxAlarmReportDto boxAlarm);
void enrichAndForward(String url,BoxAlarmReportDto boxAlarm);
}

@ -0,0 +1,15 @@
package com.sz.admin.monitor.service;
import com.mybatisflex.core.service.IService;
import com.sz.admin.monitor.pojo.dto.dataModel.GridCfgDTO;
import com.sz.admin.monitor.pojo.po.GridCfgDO;
/**
* @author xq
* @description:
* @date 2026/1/29 11:45
*/
public interface GridCfgService extends IService<GridCfgDO> {
void saveOrUpdateGrid(GridCfgDTO gridCfgDTO);
}

@ -3,9 +3,12 @@ package com.sz.admin.monitor.service;
import com.mybatisflex.core.service.IService;
import com.sz.admin.monitor.pojo.dto.edgebox.AlgorithmTaskDTO;
import com.sz.admin.monitor.pojo.po.Camera;
import com.sz.admin.monitor.pojo.po.RecordFile;
import com.sz.admin.monitor.pojo.vo.watchful.WatchfulVO;
import com.sz.admin.monitor.utils.AlgMediaConfigResponse;
import java.util.List;
/**
* ClassName: IpChannelService
* Package: com.sz.admin.monitor.service
@ -35,5 +38,9 @@ public interface IpChannelService extends IService<Camera> {
// 配置算法任务
AlgMediaConfigResponse configAlg(AlgorithmTaskDTO algTaskConfigDto);
void captureHistoryAndCompose(Long id);
List<RecordFile> getVideoByTime(Long id, String startTime, String endTime);
// void resetSentinel(int channelId, int watchTime, int presetIndex);
}

@ -0,0 +1,18 @@
package com.sz.admin.monitor.service;
import com.mybatisflex.core.service.IService;
import com.sz.admin.monitor.pojo.dto.dataModel.ModelContentDTO;
import com.sz.admin.monitor.pojo.po.ModelContentDO;
import java.util.HashMap;
import java.util.List;
/**
* @description:
* @author xq
* @version 1.0
*/
public interface ModelContentService extends IService<ModelContentDO> {
void saveOrUpdateModel(List<ModelContentDTO> list,String menuType);
}

@ -17,4 +17,7 @@ public interface TreeService {
// 获取视频预览的树型结构数据
List<TreeNodeVO> buildTreePreview();
List<TreeNodeVO> buildTreeComputeRoom();
}

@ -0,0 +1,12 @@
package com.sz.admin.monitor.service;
import com.mybatisflex.core.service.IService;
import com.sz.admin.monitor.pojo.dto.dataModel.ModelContentDTO;
import com.sz.admin.monitor.pojo.po.Substation;
import com.sz.admin.monitor.pojo.po.UserModelContentDO;
import java.util.List;
public interface UserModelContentService extends IService<UserModelContentDO> {
public void saveOrUpdateModel(List<ModelContentDTO> list);
}

@ -39,6 +39,7 @@ import java.io.File;
import java.io.FileOutputStream;
import java.io.Serializable;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.util.Base64;
import java.util.HashMap;
@ -142,17 +143,22 @@ public class AlgorithmTaskServiceImpl extends ServiceImpl<AlgorithmTaskMapper, A
websocketRedisService.sendServiceToWs(msg);
// 统一处理报警信息后,将摄像头信息+报警信息上报给别人服务器
BoxAlarmReportDto reportDto = new BoxAlarmReportDto();
reportDto.setAlarmReportTime(LocalDateTime.parse(alarmReportDto.getTime(), formatter));
reportDto.setAlarmReportType(alarmReportEnums.getAlarmDescription());
reportDto.setDescription(alarmReportDto.getResult().getDescription());
// 1. 获取你的时间字符串
String timeStr = alarmReportDto.getTime();
DateTimeFormatter timeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
LocalDateTime localDateTime = LocalDateTime.parse(timeStr, timeFormatter);
// 转成时间戳(毫秒)
long timestamp = localDateTime.toInstant(ZoneOffset.ofHours(8)).toEpochMilli();
reportDto.setAlarmTime(timestamp);
reportDto.setAlarmTypeDesc(alarmReportEnums.getAlarmDescription());
reportDto.setAlarmType(alarmReportEnums.getAlarmCode());
reportDto.setBaseImage(imageData);
reportDto.setCaptureImage(imageDataLabeled);
reportDto.setUrl(algorithmTask.getUrl());
reportDto.setAlarmImage(imageDataLabeled);
reportDto.setCameraName(camera.getName());
reportDto.setCameraId(cameraId);
reportDto.setCameraNo(camera.getCameraNo());
try {
forwardService.enrichAndForward(reportDto);
forwardService.enrichAndForward(algorithmTask.getUrl(),reportDto);
}catch ( Exception e)
{
log.error("报警信息上报失败", e);

@ -0,0 +1,65 @@
package com.sz.admin.monitor.service.impl;
import cn.hutool.core.util.ObjUtil;
import com.mybatisflex.core.update.UpdateChain;
import com.mybatisflex.spring.service.impl.ServiceImpl;
import com.sz.admin.monitor.mapper.BlurDetectionMapper;
import com.sz.admin.monitor.mapper.CameraSnapshotMapper;
import com.sz.admin.monitor.pojo.dto.blurDetection.BlurDetectionDTO;
import com.sz.admin.monitor.pojo.po.BlurDetection;
import com.sz.admin.monitor.service.BlurDetectionService;
import com.sz.admin.monitor.service.CameraSnapshotService;
import com.sz.core.common.exception.common.BusinessException;
import com.sz.core.util.BeanCopyUtils;
import com.sz.platform.enums.AdminResponseEnum;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.time.LocalDateTime;
/**
* ClassName: BlurDetectionServiceImpl
* Package: com.sz.admin.monitor.service.impl
* Description:
*/
@Service
public class BlurDetectionServiceImpl extends ServiceImpl<BlurDetectionMapper, BlurDetection> implements BlurDetectionService {
@Resource
private BlurDetectionMapper blurDetectionMapper;
@Resource
private CameraSnapshotService cameraSnapshotService;
@Override
@Transactional
public Boolean saveOrUpdateBlur(BlurDetectionDTO blurDetectionDTO) {
Long id = blurDetectionDTO.getId();
Integer enable = blurDetectionDTO.getEnable();
if(ObjUtil.isNotNull(id))
{
// 修改
if(enable==0)
{
// 关闭直接将enable状态修改成0
boolean update = UpdateChain.of(BlurDetection.class)
.set(BlurDetection::getEnable, 0)
.where(BlurDetection::getId)
.eq(id)
.update();
}else {
// 删除之前的基准图。抓拍一张最新的基准图保存到数据库
// cameraSnapshotService.deleteByCameraIdAndType(cameraId,4);
// cameraSnapshotService.captureAndSave(cameraId, 4);
// 保存数据库
blurDetectionMapper.update(BeanCopyUtils.copy(blurDetectionDTO, BlurDetection.class));
}
}else {
// 新增
// cameraSnapshotService.captureAndSave(cameraId, 4);
BlurDetection detection = BeanCopyUtils.copy(blurDetectionDTO, BlurDetection.class);
detection.setCreateTime(LocalDateTime.now());
detection.setUpdateTime(LocalDateTime.now());
blurDetectionMapper.insert(detection);
}
return true;
}
}

@ -7,7 +7,6 @@ import com.sz.admin.monitor.mapper.CameraMapper;
import com.sz.admin.monitor.mapper.CameraSnapshotMapper;
import com.sz.admin.monitor.pojo.po.Camera;
import com.sz.admin.monitor.pojo.po.CameraSnapshot;
import com.sz.admin.monitor.pojo.po.table.CameraSnapshotTableDef;
import com.sz.admin.monitor.pojo.vo.camerasnapshot.CameraSnapshotVO;
import com.sz.admin.monitor.sdk.ManageNVR;
import com.sz.admin.monitor.service.CameraService;
@ -44,7 +43,6 @@ public class CameraSnapshotServiceImpl extends ServiceImpl<CameraSnapshotMapper,
snapshot.setImagePath(path);
snapshot.setCameraId(id);
snapshot.setCheckType(triggerType);
// 先删除,后插入
cameraSnapshotMapper.insert(snapshot);
return BeanCopyUtils.copy(snapshot, CameraSnapshotVO.class);
}
@ -83,6 +81,25 @@ public class CameraSnapshotServiceImpl extends ServiceImpl<CameraSnapshotMapper,
return BeanCopyUtils.copyList(cameraSnapshotMapper.selectListByQuery(wrapper), CameraSnapshotVO.class);
}
@Override
public void deleteByCameraIdAndType(Long cameraId, int i) {
QueryWrapper wrapper = QueryWrapper.create().select().from(CameraSnapshot.class)
.where(CameraSnapshot::getCameraId).eq(cameraId)
.and(CameraSnapshot::getCheckType).eq(i);
CameraSnapshot cameraSnapshot = cameraSnapshotMapper.selectOneByQuery(wrapper);
if (cameraSnapshot != null) {
cameraSnapshotMapper.delete(cameraSnapshot);
}
}
@Override
public CameraSnapshotVO selectByCameraIdAndType(Long cameraId, int i) {
QueryWrapper wrapper = QueryWrapper.create().select().from(CameraSnapshot.class)
.where(CameraSnapshot::getCameraId).eq(cameraId)
.and(CameraSnapshot::getCheckType).eq(i);
CameraSnapshot cameraSnapshot = cameraSnapshotMapper.selectOneByQuery(wrapper);
return BeanCopyUtils.copy(cameraSnapshot, CameraSnapshotVO.class);
}
private void deleteSnapshotByChannelIdAndPresetIndex(Long id, int presetIndex) {

@ -0,0 +1,51 @@
package com.sz.admin.monitor.service.impl;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.mybatisflex.core.query.QueryWrapper;
import com.mybatisflex.spring.service.impl.ServiceImpl;
import com.sz.admin.monitor.mapper.CanvasCfgMapper;
import com.sz.admin.monitor.pojo.dto.dataModel.CanvasCfgDTO;
import com.sz.admin.monitor.pojo.po.CanvasCfgDO;
import com.sz.admin.monitor.service.CanvasCfgService;
import org.springframework.stereotype.Service;
/**
* @author xq
* @description:
* @date 2026/1/29 11:34
*/
@Service
public class CanvasCfgServiceImpl extends ServiceImpl<CanvasCfgMapper, CanvasCfgDO> implements CanvasCfgService {
@Override
public void saveOrUpdateCanvas(CanvasCfgDTO canvasCfgDTO) {
if(ObjectUtil.isEmpty(canvasCfgDTO))
return;
CanvasCfgDO canvasCfgDO = CanvasCfgDTO.dtoConvertDO(canvasCfgDTO);
if(StrUtil.isEmpty(canvasCfgDO.getUserId())) {
saveOrUpdate(canvasCfgDO);
return;
}
QueryWrapper queryWrapper = QueryWrapper
.create()
.from(CanvasCfgDO.class)
.eq(CanvasCfgDO.USER_ID, canvasCfgDTO.getUserId())
.limit(1);
CanvasCfgDO one = getOne(queryWrapper);
// CanvasCfgDO one = getOne(new QueryWrapper<CanvasCfgDO>()
// .eq(CanvasCfgDO.USER_ID, canvasCfgDTO.getUserId())
// .last("limit 1")
// );
if(ObjectUtil.isEmpty(one)) {
saveOrUpdate(canvasCfgDO);
return;
}
canvasCfgDO.setId(one.getId());
saveOrUpdate(canvasCfgDO);
}
}

@ -0,0 +1,48 @@
package com.sz.admin.monitor.service.impl;
import com.mybatisflex.core.BaseMapper;
import com.mybatisflex.core.query.QueryWrapper;
import com.mybatisflex.spring.service.impl.ServiceImpl;
import com.sz.admin.monitor.mapper.ComputeRoomMapper;
import com.sz.admin.monitor.mapper.NvrMapper;
import com.sz.admin.monitor.pojo.po.ComputerRoom;
import com.sz.admin.monitor.pojo.po.ModelContentDO;
import com.sz.admin.monitor.pojo.po.Nvr;
import com.sz.admin.monitor.pojo.po.table.ComputerRoomTableDef;
import com.sz.admin.monitor.pojo.po.table.ModelContentDOTableDef;
import com.sz.admin.monitor.pojo.po.table.NvrTableDef;
import com.sz.admin.monitor.service.ComputerRoomService;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* ClassName: ComputerRoomServiceImpl
* Package: com.sz.admin.monitor.service.impl
* Description:
*/
@Service
public class ComputerRoomServiceImpl extends ServiceImpl<ComputeRoomMapper, ComputerRoom> implements ComputerRoomService {
@Resource
private ComputeRoomMapper computerRoomMapper;
@Override
public List<ComputerRoom> getComputerRoomList(Long substationId) {
// 构建 EXISTS 子查询
QueryWrapper queryWrapper = QueryWrapper.create()
.select(
ComputerRoomTableDef.COMPUTER_ROOM.ID,
ComputerRoomTableDef.COMPUTER_ROOM.SUBSTATION_ID,
ComputerRoomTableDef.COMPUTER_ROOM.NAME,
ComputerRoomTableDef.COMPUTER_ROOM.DESCRIPTION
)
.from(ComputerRoomTableDef.COMPUTER_ROOM)
.where(ComputerRoomTableDef.COMPUTER_ROOM.SUBSTATION_ID.eq(substationId))
.and(ComputerRoomTableDef.COMPUTER_ROOM.ID.in(
QueryWrapper.create()
.select(ModelContentDOTableDef.MODEL_CONTENT_DO.ROOM_ID)
.from(ModelContentDOTableDef.MODEL_CONTENT_DO)
));
return computerRoomMapper.selectListByQuery(queryWrapper);
}
}

@ -0,0 +1,195 @@
package com.sz.admin.monitor.service.impl;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.mybatisflex.core.query.QueryWrapper;
import com.sz.admin.monitor.pojo.dto.dataModel.CanvasCfgDTO;
import com.sz.admin.monitor.pojo.dto.dataModel.DataModelDTO;
import com.sz.admin.monitor.pojo.dto.dataModel.GridCfgDTO;
import com.sz.admin.monitor.pojo.dto.dataModel.ModelContentDTO;
import com.sz.admin.monitor.pojo.po.CanvasCfgDO;
import com.sz.admin.monitor.pojo.po.GridCfgDO;
import com.sz.admin.monitor.pojo.po.ModelContentDO;
import com.sz.admin.monitor.pojo.po.UserModelContentDO;
import com.sz.admin.monitor.pojo.que.dataModel.DataModelQue;
import com.sz.admin.monitor.service.CanvasCfgService;
import com.sz.admin.monitor.service.GridCfgService;
import com.sz.admin.monitor.service.ModelContentService;
import com.sz.admin.monitor.service.UserModelContentService;
import com.sz.core.common.entity.ApiResult;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
/**
* @author xq
* @description:
* @date 2026/1/29 10:51
*/
@Service
public class DataModelServiceImpl {
@Autowired
private CanvasCfgService canvasCfgService; // 画板
@Autowired
private GridCfgService gridCfgService; // 网格
@Autowired
private ModelContentService modelContentService; //模型
@Autowired
private UserModelContentService userModelContentService; //用户模型中间表
private static final String userId = "1";
public ApiResult<DataModelDTO> getModelData(DataModelQue que) {
if (StrUtil.isEmpty(que.getUserId()))
que.setUserId(userId);
QueryWrapper queryWrapper = QueryWrapper.create()
.from(CanvasCfgDO.class)
.eq(CanvasCfgDO.USER_ID, que.getUserId())
.limit(1);
// 获取画板数据
CanvasCfgDO canvasCfgDO = canvasCfgService.getOne(queryWrapper);
if (ObjectUtil.isEmpty(canvasCfgDO)) {
canvasCfgDO = initCanvasCfg();
canvasCfgService.saveOrUpdate(canvasCfgDO);
}
// 获取网格数据
GridCfgDO gridCfgDO = gridCfgService.getOne(QueryWrapper.create()
.from(GridCfgDO.class)
.eq(GridCfgDO.USER_ID, que.getUserId())
.limit(1)
);
if (ObjectUtil.isEmpty(gridCfgDO)) {
gridCfgDO = initGridCfg();
gridCfgService.saveOrUpdate(gridCfgDO);
}
//中间表
List<UserModelContentDO> userModelList = userModelContentService.list(QueryWrapper.create()
.from(UserModelContentDO.class)
.eq(UserModelContentDO.USER_ID, userId)
.eq(UserModelContentDO.MENU_TYPE, que.getMenuType())
);
ArrayList<ModelContentDTO> objects = new ArrayList<>();
if (CollectionUtil.isEmpty(userModelList)) {
DataModelDTO build = DataModelDTO.builder()
.canvasCfg(CanvasCfgDO.doConvertDTO(canvasCfgDO))
.gridCfg(GridCfgDO.doConvertDTO(gridCfgDO))
.json(objects)
.build();
return ApiResult.success(build);
}
// List<String> collect = userModelList.stream()
// .map(item -> item.getModelContentId())
// .collect(Collectors.toList());
List<ModelContentDO> modelContentDOS = modelContentService.list(QueryWrapper.create()
.from(ModelContentDO.class)
.eq(ModelContentDO::getRoomId, que.getRoomId())
// .in(ModelContentDO.ID, collect)
.orderBy(ModelContentDO.MODEL_INDEX, true)
);
for (ModelContentDO modelContentDO : modelContentDOS) {
objects.add(ModelContentDO.doConvertDTO(modelContentDO));
}
DataModelDTO build = DataModelDTO.builder()
.canvasCfg(CanvasCfgDO.doConvertDTO(canvasCfgDO))
.gridCfg(GridCfgDO.doConvertDTO(gridCfgDO))
.json(objects)
.build();
return ApiResult.success(build);
}
/**
*
*
* @return
*/
public GridCfgDO initGridCfg() {
return GridCfgDO.builder()
.userId(userId)
.enabled(true)
.align(true)
.size(10)
.build();
}
/**
*
*
* @return
*/
public CanvasCfgDO initCanvasCfg() {
return CanvasCfgDO.builder()
.width(1920)
.userId(userId)
.height(1080)
.scale(1D)
.color("")
.img("")
.guide(true)
.adsorp(true)
.adsorpDiff(5D)
.transformOrigin("{\"x\":0,\"y\":0}")
.dragOffset("{\"x\":0,\"y\":0}")
.build();
}
/**
*
*
* @param dataModelDTO
* @param request
* @param response
* @return
*/
@Transactional
public ApiResult saveOrUpdateModelData(DataModelDTO dataModelDTO, HttpServletRequest request, HttpServletResponse response) {
if (ObjectUtil.isEmpty(dataModelDTO))
throw new IllegalArgumentException("传值错误");
CanvasCfgDTO canvasCfg = dataModelDTO.getCanvasCfg();
GridCfgDTO gridCfg = dataModelDTO.getGridCfg();
List<ModelContentDTO> json=new ArrayList<>();
for (int i = 0; i < dataModelDTO.getJson().size(); i++) {
ModelContentDTO modelContentDTO = dataModelDTO.getJson().get(i);
modelContentDTO.setModelIndex(i);
modelContentDTO.setSubstationId(dataModelDTO.getSubstationId());
modelContentDTO.setRoomId(dataModelDTO.getRoomId());
json.add(modelContentDTO);
}
//保存、更新面板
canvasCfg.setUserId(userId);
canvasCfgService.saveOrUpdateCanvas(canvasCfg);
//保存、更新网格
gridCfg.setUserId(userId);
gridCfgService.saveOrUpdateGrid(gridCfg);
//保存数据模型
modelContentService.saveOrUpdateModel(json, dataModelDTO.getMenuType());
return ApiResult.success();
}
public List<UserModelContentDO> getList() {
return null;
}
}

@ -8,6 +8,7 @@ import com.sz.admin.monitor.pojo.po.Camera;
import com.sz.admin.monitor.pojo.po.Nvr;
import com.sz.admin.monitor.sdk.ManageNVR;
import com.sz.admin.monitor.service.DeviceService;
import com.sz.admin.monitor.service.IpChannelService;
import com.sz.admin.monitor.utils.AiBoxRequestUtil;
import com.sz.admin.monitor.utils.AlgMediaConfigResponse;
import com.sz.admin.monitor.utils.RtspUtil;
@ -30,6 +31,10 @@ import java.io.UnsupportedEncodingException;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.stream.Collectors;
/**
@ -49,11 +54,8 @@ public class DeviceServiceImpl extends ServiceImpl<NvrMapper, Nvr> implements De
@Resource
private NvrMapper nvrMapper;
@Resource
private SocketService socketService;
@Resource
private WebsocketRedisService websocketRedisService;
@Resource
private AiBoxRequestUtil aiBoxRequestUtil;
private IpChannelService ipChannelService;
@Override
public Object deviceLogin(Long id) {
@ -68,6 +70,37 @@ public class DeviceServiceImpl extends ServiceImpl<NvrMapper, Nvr> implements De
return result;
}
@Override
public void captureHistoryAndCompose(List<Long> ids) {
if(ids==null || ids.isEmpty())
{
throw new BusinessException(AdminResponseEnum.OPERATION_FAIL,null,"数据为空");
}
ExecutorService threadPool = Executors.newFixedThreadPool(1);
CompletableFuture.runAsync(()->{
try {
List<Nvr> nvrs = nvrMapper.selectListByIds(ids);
// 对每个NVR进行分析
for (Nvr nvr : nvrs) {
// 查询出所有的通道
List<Camera> cameraList = cameraMapper.selectByNvrId(nvr.getId());
// 遍历所有的通道,进行分析
for (Camera camera : cameraList) {
try {
ipChannelService.captureHistoryAndCompose(camera.getId());
}catch (Exception e)
{
log.error("处理camera异常NVRID:{},CameraID:{}",nvr.getId(),camera.getId());
}
}
}
}catch (Exception e)
{
log.error("执行批量分析任务发生全局异常", e);
}
},threadPool);
}
/**
*
* @param id NVRid

@ -0,0 +1,274 @@
package com.sz.admin.monitor.service.impl;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.codec.Base64;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.mybatisflex.core.paginate.Page;
import com.mybatisflex.core.query.QueryWrapper;
import com.sz.admin.monitor.pojo.dto.camera.CameraListDTO;
import com.sz.admin.monitor.pojo.dto.file.FileEntityDTO;
import com.sz.admin.monitor.pojo.dto.file.FileStorageDTO;
import com.sz.admin.monitor.pojo.po.Camera;
import com.sz.admin.monitor.pojo.po.FileStorageDO;
import com.sz.admin.monitor.pojo.po.Nvr;
import com.sz.admin.monitor.pojo.que.file.FileStorageQue;
import com.sz.admin.monitor.pojo.vo.camera.CameraVO;
import com.sz.admin.monitor.service.FileStorageService;
import com.sz.core.common.entity.ApiResult;
import com.sz.core.common.entity.PageResult;
import com.sz.core.datascope.SimpleDataScopeHelper;
import com.sz.core.util.PageUtils;
import com.sz.core.util.Utils;
import com.sz.platform.enums.AdminResponseEnum;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
import java.util.*;
/**
* @author xq
* @description:
* @date 2026/3/13 15:28
*/
@Service
public class FileServiceImpl {
@Autowired
private FileStorageService fileStorageService;
@Value("${file.object.storage.targetDir:/defaultFile}")
private String targetDir;
// 获取当前操作系统的文件分隔符
private static String separator = "/";
//获取文件流路径(请求路径)
private static String path = "/fileStorage/getPreviewFile/";
/**
*
*
* @param id
* @return
*/
public ApiResult<String> deleteFileById(String id) {
if (ObjectUtil.isEmpty(id))
return ApiResult.error(AdminResponseEnum.OPERATION_FAIL);
FileStorageDO fileStorageDO = fileStorageService.getById(id);
if (ObjectUtil.isEmpty(fileStorageDO))
return ApiResult.error(AdminResponseEnum.OPERATION_FAIL);
fileStorageService.removeById(id);
return ApiResult.success("删除成功");
}
/**
*
*
* @param dto
* @return
*/
public ApiResult<String> editFileNameById(FileEntityDTO dto) {
if (ObjectUtil.isEmpty(dto.getId()))
return ApiResult.error(AdminResponseEnum.OPERATION_FAIL);
FileStorageDO fileStorageDO = fileStorageService.getById(dto.getId());
if (ObjectUtil.isEmpty(fileStorageDO))
return ApiResult.error(AdminResponseEnum.OPERATION_FAIL);
fileStorageDO.setFileName(dto.getFileName());
fileStorageService.saveOrUpdate(fileStorageDO);
return ApiResult.success("修改成功");
}
/**
*
*
* @param que
* @return
*/
public ApiResult<PageResult<FileEntityDTO>> getFileObjectList(FileStorageQue que) {
SimpleDataScopeHelper.start(FileStorageDO.class); // 指定要追加条件的表PO实体
QueryWrapper queryWrapper = QueryWrapper.create()
.from(FileStorageDO.class)
.eq(FileStorageDO.ID, que.getId(), ObjectUtil.isNotEmpty(que.getId()))
.like(FileStorageDO.FILE_NAME, que.getFileName(), ObjectUtil.isNotEmpty(que.getFileName()));
if (ObjectUtil.isNotEmpty(que.getStartTime()) && ObjectUtil.isNotEmpty(que.getEndTime())) {
queryWrapper.between(
FileStorageDO.ADD_TIME,
new Date(que.getStartTime()),
new Date(que.getEndTime())
);
}
queryWrapper.orderBy(FileStorageDO.ADD_TIME, false);
Page<FileStorageDO> page = fileStorageService.pageAs(PageUtils.getPage(que), queryWrapper, FileStorageDO.class);// 调试sql
if (ObjectUtil.isEmpty(page) || page.getRecords().isEmpty())
return ApiResult.success(new PageResult<>(que.getPage().longValue(), que.getLimit().longValue(), 0, 0, new ArrayList<>()));
List<FileEntityDTO> fileEntityDTOS = new ArrayList<>();
for (FileStorageDO record : page.getRecords()) {
FileEntityDTO fileEntityDTO = BeanUtil.copyProperties(record, FileEntityDTO.class);
fileEntityDTO.setFilePath(path + record.getId());
fileEntityDTOS.add(fileEntityDTO);
}
return ApiResult.success(new PageResult<>(
page.getPageNumber(),
page.getPageSize(),
page.getTotalPage(),
page.getTotalRow(),
fileEntityDTOS));
}
// public ApiResult<PageResult<FileEntityDTO>> getFileObjectList(FileStorageQue que) {
// Page<FileStorageDO> doPage = BaseQue.init(que, FileStorageDO.class);
// Page<FileStorageDO> page = fileStorageService.page(doPage, new QueryWrapper<FileStorageDO>()
// .eq(ObjectUtil.isNotEmpty(que.getId()), FileStorageDO.ID, que.getId())
// .like(ObjectUtil.isNotEmpty(que.getFileName()), FileStorageDO.FILE_NAME, que.getFileName())
// .between(
// ObjectUtil.isNotEmpty(que.getStartTime()) && ObjectUtil.isNotEmpty(que.getEndTime())
// , FileStorageDO.ADD_TIME
// , que.getStartTime(), que.getEndTime())
// .orderByDesc(FileStorageDO.ADD_TIME)
// );
// if(ObjectUtil.isEmpty(page) || page.getRecords().isEmpty())
// return ResponseBody.ok();
//
// BasePage<FileEntityDTO> basePage = new BasePage();
// basePage.setTotal(page.getTotal());
// basePage.setSize(page.getSize());
// basePage.setCurrent(page.getCurrent());
// basePage.setPages(page.getPages());
//
// List<FileEntityDTO> fileEntityDTOS = new ArrayList<>();
// for (FileStorageDO record : page.getRecords()) {
// FileEntityDTO fileEntityDTO = BeanUtil.copyProperties(record, FileEntityDTO.class);
// fileEntityDTO.setFilePath(path+record.getId());
// fileEntityDTOS.add(fileEntityDTO);
// }
// basePage.setList(fileEntityDTOS);
// return ApiResult.success(basePage);
// }
/**
*
*
* @param id
* @return
*/
public ResponseEntity<byte[]> getPreviewFile(String id) {
FileStorageDO fileStorageDO = fileStorageService.getById(id);
String filePath = fileStorageDO.getFileUrl();
// 使用Hutool读取文件并转换为Base64编码
byte[] imageBytes = FileUtil.readBytes(filePath);
String mimeType = getMimeType(filePath);
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.parseMediaType(mimeType));
headers.setContentLength(imageBytes.length);
return new ResponseEntity<>(imageBytes, headers, HttpStatus.OK);
}
/**
*
*
* @param id
* @return
*/
public ApiResult<FileStorageDTO> getFile(String id) {
FileStorageDO fileStorageDO = fileStorageService.getById(id);
if (ObjectUtil.isEmpty(fileStorageDO))
return ApiResult.error(AdminResponseEnum.OPERATION_FAIL);
String filePath = fileStorageDO.getFileUrl();
// 使用Hutool读取文件并转换为Base64编码
byte[] fileBytes = FileUtil.readBytes(filePath);
String base64Data = Base64.encode(fileBytes);
String mimeType = getMimeType(filePath);
String dataUrl = "data:" + mimeType + ";base64," + base64Data;
FileStorageDTO fileStorageDTO = BeanUtil.copyProperties(fileStorageDO, FileStorageDTO.class);
fileStorageDTO.setBase64Data(dataUrl);
return ApiResult.success(fileStorageDTO);
}
/**
*
*
* @param file
* @return
*/
public ApiResult<FileStorageDTO> saveFile(MultipartFile file) {
Map<String, Object> result = new HashMap<>();
if (file.isEmpty())
return ApiResult.error(AdminResponseEnum.OPERATION_FAIL);
String path = targetDir;
try {
FileUtil.mkdir(path);
// 生成唯一文件名
String fileName = System.currentTimeMillis() + "_" + file.getOriginalFilename();
String filePath = path + separator + fileName;
// 使用Hutool保存文件
FileUtil.writeBytes(file.getBytes(), filePath);
String mimeType = getMimeType(filePath);
FileStorageDTO fileDTO = FileStorageDTO.builder()
.fileUrl(filePath)
.fileSize(ObjectUtil.isNotEmpty(file.getSize()) ? String.valueOf(file.getSize()) : "0")
.fileName(file.getOriginalFilename())
.fileSuffix(mimeType)
.addTime(new Date())
.build();
FileStorageDO fileStorageDO = FileStorageDTO.dtoConvertDO(fileDTO);
fileStorageService.saveOrUpdate(fileStorageDO);
fileDTO.setId(fileStorageDO.getId());
String base64Data = Base64.encode(file.getBytes());
String dataUrl = "data:" + mimeType + ";base64," + base64Data;
fileDTO.setBase64Data(dataUrl);
return ApiResult.success(fileDTO);
} catch (IOException e) {
result.put("success", false);
result.put("message", "文件上传失败: " + e.getMessage());
return ApiResult.error(null);
}
}
public void test01() {
fileStorageService.list().forEach(System.out::println);
}
/**
* MIME
*/
private String getMimeType(String filePath) {
String lowerPath = filePath.toLowerCase();
if (lowerPath.endsWith(".jpg") || lowerPath.endsWith(".jpeg")) {
return "image/jpeg";
} else if (lowerPath.endsWith(".png")) {
return "image/png";
} else if (lowerPath.endsWith(".gif")) {
return "image/gif";
} else if (lowerPath.endsWith(".bmp")) {
return "image/bmp";
} else {
return "image/jpeg"; // 默认JPEG类型
}
}
}

@ -0,0 +1,17 @@
package com.sz.admin.monitor.service.impl;
import com.mybatisflex.spring.service.impl.ServiceImpl;
import com.sz.admin.monitor.mapper.FileStorageMapper;
import com.sz.admin.monitor.pojo.po.FileStorageDO;
import com.sz.admin.monitor.service.FileStorageService;
import org.springframework.stereotype.Service;
/**
* @author xq
* @description:
* @date 2026/2/2 22:18
*/
@Service
public class FileStorageServiceImpl extends ServiceImpl<FileStorageMapper, FileStorageDO> implements FileStorageService {
}

@ -19,7 +19,7 @@ public class ForwardServiceImpl implements ForwardService {
@Resource
private RestTemplate restTemplate;
@Override
public void enrichAndForward(BoxAlarmReportDto boxAlarm) {
ResponseEntity<String> response = restTemplate.postForEntity(boxAlarm.getUrl(), boxAlarm, String.class);
public void enrichAndForward(String url,BoxAlarmReportDto boxAlarm) {
ResponseEntity<String> response = restTemplate.postForEntity(url, boxAlarm, String.class);
}
}

@ -0,0 +1,49 @@
package com.sz.admin.monitor.service.impl;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.mybatisflex.core.query.QueryWrapper;
import com.mybatisflex.spring.service.impl.ServiceImpl;
import com.sz.admin.monitor.mapper.GridCfgMapper;
import com.sz.admin.monitor.pojo.dto.dataModel.GridCfgDTO;
import com.sz.admin.monitor.pojo.po.GridCfgDO;
import com.sz.admin.monitor.service.GridCfgService;
import org.springframework.stereotype.Service;
/**
* @author xq
* @description:
* @date 2026/1/29 11:45
*/
@Service
public class GridCfgServiceImpl extends ServiceImpl<GridCfgMapper, GridCfgDO> implements GridCfgService {
@Override
public void saveOrUpdateGrid(GridCfgDTO dto) {
if (ObjectUtil.isEmpty(dto))
return;
GridCfgDO gridCfgDO = GridCfgDTO.dtoConvertDO(dto);
if (StrUtil.isEmpty(gridCfgDO.getUserId())) {
saveOrUpdate(gridCfgDO);
return;
}
QueryWrapper queryWrapper = QueryWrapper.create()
.from(GridCfgDO.class)
.eq(GridCfgDO.USER_ID, gridCfgDO.getUserId())
.limit(1);
GridCfgDO one = getOne(queryWrapper);
// GridCfgDO one = getOne(new QueryWrapper<GridCfgDO>()
// .eq(GridCfgDO.USER_ID, gridCfgDO.getUserId())
// .last("limit 1")
// );
if (ObjectUtil.isEmpty(one)) {
saveOrUpdate(gridCfgDO);
return;
}
gridCfgDO.setId(one.getId());
saveOrUpdate(gridCfgDO);
}
}

@ -1,5 +1,6 @@
package com.sz.admin.monitor.service.impl;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.lang.UUID;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
@ -8,16 +9,10 @@ import com.fasterxml.jackson.databind.ObjectMapper;
import com.mybatisflex.core.query.QueryWrapper;
import com.mybatisflex.spring.service.impl.ServiceImpl;
import com.sz.admin.monitor.enums.HCPlayControlEnum;
import com.sz.admin.monitor.mapper.AlgorithmTaskMapper;
import com.sz.admin.monitor.mapper.CameraMapper;
import com.sz.admin.monitor.mapper.EdgeBoxMapper;
import com.sz.admin.monitor.mapper.NvrMapper;
import com.sz.admin.monitor.mapper.*;
import com.sz.admin.monitor.pojo.dto.Ipchannel.ControlDTO;
import com.sz.admin.monitor.pojo.dto.edgebox.AlgorithmTaskDTO;
import com.sz.admin.monitor.pojo.po.AlgorithmTask;
import com.sz.admin.monitor.pojo.po.Camera;
import com.sz.admin.monitor.pojo.po.EdgeBox;
import com.sz.admin.monitor.pojo.po.Nvr;
import com.sz.admin.monitor.pojo.po.*;
import com.sz.admin.monitor.pojo.vo.camerasnapshot.CameraSnapshotVO;
import com.sz.admin.monitor.pojo.vo.ptz.PTZVO;
import com.sz.admin.monitor.pojo.vo.watchful.WatchfulVO;
@ -25,10 +20,7 @@ import com.sz.admin.monitor.sdk.ManageNVR;
import com.sz.admin.monitor.service.CameraSnapshotService;
import com.sz.admin.monitor.service.IpChannelService;
import com.sz.admin.monitor.service.PresetService;
import com.sz.admin.monitor.utils.AiBoxRequestUtil;
import com.sz.admin.monitor.utils.AlgMediaConfigResponse;
import com.sz.admin.monitor.utils.RtspUtil;
import com.sz.admin.monitor.utils.ZLMediaKitUtils;
import com.sz.admin.monitor.utils.*;
import com.sz.core.common.entity.TransferMessage;
import com.sz.core.common.exception.common.BusinessException;
import com.sz.core.util.BeanCopyUtils;
@ -42,7 +34,9 @@ import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.io.File;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.TimeUnit;
@ -67,7 +61,7 @@ public class IpChannelServiceImpl extends ServiceImpl<CameraMapper, Camera> impl
private AlgorithmTaskMapper algorithmTaskMapper;
@Resource
private PresetService presetService;
private CameraAlarmMapper cameraAlarmMapper;
@Resource
private AiBoxRequestUtil aiBoxRequestUtil;
@ -128,6 +122,10 @@ public class IpChannelServiceImpl extends ServiceImpl<CameraMapper, Camera> impl
// 进行拉流代理
JSONObject jsonObject =zlMediaKitUtils.addStreamProxy(String.valueOf(id), mainRtsp);
// JSONObject jsonObject = zlMediaKitUtils.addStreamProxy("test", "rtsp://132.239.12.145:554/axis-media/media.amp");
log.info("进行拉流代理的结果:{}", jsonObject.toString());
if ("-1".equals(jsonObject.get("code").toString())) {
throw new BusinessException(AdminResponseEnum.DEVICE_ADD_PROXY_FAIL, null, "服务失败");
}
if ("0".equals(jsonObject.get("code").toString())) {
//拉流代理成功
return zlMediaKitUtils.getPlayUrl(String.valueOf(id));
@ -336,7 +334,6 @@ public class IpChannelServiceImpl extends ServiceImpl<CameraMapper, Camera> impl
algorithmTaskDTO.setUserData(userDataDto);
// DTO转PO
AlgorithmTask algorithmTask = BeanCopyUtils.copy(algorithmTaskDTO, AlgorithmTask.class);
algorithmTask.setIsDeleted("F");
algorithmTask.setCreateTime(createTime);
ObjectMapper mapper = new ObjectMapper();
try {
@ -375,6 +372,98 @@ public class IpChannelServiceImpl extends ServiceImpl<CameraMapper, Camera> impl
}
return response;
}
@Override
public void captureHistoryAndCompose(Long id) {
DateTimeFormatter fmt = DateTimeFormatter.ofPattern("yyyyMMdd_HHmmss");
// 生成本次任务的专属批次号
String batchId=LocalDateTime.now().format(fmt);
// 拼接出本次任务的专属目录
String baseDir="D:/work/temp/";
String taskDir=baseDir+"task_"+batchId+"/";
File taskDirect = new File(taskDir);
if (!taskDirect.exists()) {
boolean created = taskDirect.mkdirs();
if (!created) {
log.error("创建专属工作目录失败,请检查 D 盘权限!路径: {}", taskDir);
return;
}
}
log.info("保存文件的路径:{}",taskDir);
manageNVR.captureHistoryImage(taskDir,id);
startSequentialComparison(taskDir,id);
}
// 执行相邻图片的滑动窗口对比任务
private void startSequentialComparison(String imageDirPath,Long id) {
// 图片存储目录文件夹
File dir = new File(imageDirPath);
Camera camera = this.getById(id);
Nvr nvr = nvrMapper.selectOneById(camera.getNvrId());
// 获取该目录下所有的.jpg图片
File[] imageFiles = dir.listFiles((d, name) -> name.toLowerCase().endsWith(".jpg") && name.contains("history_"+camera.getId()));
if (imageFiles == null || imageFiles.length < 2) {
log.error("图片数据不足,无法对比");
return;
}
// 将图片进行排序
Arrays.sort(imageFiles, Comparator.comparing(File::getName));
List<CameraAlarm> cameraAlarmList=new ArrayList<>();
for (int i = 0; i < imageFiles.length - 1; i++) {
File currentImg = imageFiles[i];
File nextImg = imageFiles[i + 1];
// System.out.println("正在对比:" + currentImg.getName() + "VS " + nextImg.getName());
// 调用算法进行对比
// 1. 移位对比
Map<String, Object> map = RobustImageMatcherUtil.calculateOffset(currentImg.getPath(), nextImg.getPath());
// 如果出现差异化,直接生成一条记录,保存到报警记录表中
int value = (int) map.get("value");
if (value == 1) {
CameraAlarm cameraAlarm = new CameraAlarm();
cameraAlarm.setCameraId(camera.getId());
cameraAlarm.setCameraName(camera.getName());
cameraAlarm.setCameraNo(camera.getCameraNo());
cameraAlarm.setChannelId(camera.getChannelId());
cameraAlarm.setAlarmAreaId(nvr.getStationId());
cameraAlarm.setAlarmType(1);
cameraAlarm.setStatus(0);
cameraAlarm.setBaseImage(currentImg.getPath());
cameraAlarm.setCaptureImage(nextImg.getPath());
cameraAlarm.setAlgoResult((String) map.get("description"));
cameraAlarmList.add(cameraAlarm);
}
// 2. 模糊对比
BlurDetectorV4.DetectResult detectResult = BlurDetectorV4.doubleDetectBlur(currentImg.getPath(), nextImg.getPath());
if ("1".equals(detectResult.value)){
CameraAlarm cameraAlarm = new CameraAlarm();
cameraAlarm.setCameraId(camera.getId());
cameraAlarm.setCameraName(camera.getName());
cameraAlarm.setCameraNo(camera.getCameraNo());
cameraAlarm.setChannelId(camera.getChannelId());
cameraAlarm.setAlarmAreaId(nvr.getStationId());
cameraAlarm.setAlarmType(6);
cameraAlarm.setStatus(0);
cameraAlarm.setBaseImage(currentImg.getPath());
cameraAlarm.setCaptureImage(nextImg.getPath());
cameraAlarm.setAlgoResult((String) map.get("description"));
cameraAlarmList.add(cameraAlarm);
}
}
// 保存到数据库
cameraAlarmMapper.insertBatch(cameraAlarmList);
}
@Override
public List<RecordFile> getVideoByTime(Long id, String startTime, String endTime) {
List<RecordFile> recordFiles = new ArrayList<>();
try {
recordFiles = manageNVR.getRecordFileByTime(id, LocalDateTime.parse(startTime, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")), LocalDateTime.parse(endTime, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
} catch (Exception e) {
throw new RuntimeException("获取视频失败", e);
}
return recordFiles;
}
// 在这里接收透传过来的 websocket信息进行业务处理
@Override
public void handlerMsg(TransferMessage transferMessage) {

@ -0,0 +1,76 @@
package com.sz.admin.monitor.service.impl;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.mybatisflex.core.query.QueryWrapper;
import com.mybatisflex.spring.service.impl.ServiceImpl;
import com.sz.admin.monitor.mapper.ModelContentMapper;
import com.sz.admin.monitor.pojo.dto.dataModel.ModelContentDTO;
import com.sz.admin.monitor.pojo.po.ModelContentDO;
import com.sz.admin.monitor.pojo.po.UserModelContentDO;
import com.sz.admin.monitor.service.ModelContentService;
import com.sz.admin.monitor.service.UserModelContentService;
import jakarta.annotation.Resource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
/**
* @author xq
* @description:
* @date 2026/1/29 11:30
*/
@Component
public class ModelContentServiceImpl extends ServiceImpl<ModelContentMapper, ModelContentDO> implements ModelContentService {
@Autowired
private UserModelContentService userModelContentService;
@Resource
private ModelContentMapper modelContentMapper;
/**
*
*
* @param list
* @param menuType
* @return map key addIdModelsid updateIdModelsid
*/
@Override
public void saveOrUpdateModel(List<ModelContentDTO> list, String menuType) {
if (CollectionUtil.isEmpty(list))
return;
// 获取所有roomIds
Set<Long> roomIds = list.stream().map(ModelContentDTO::getRoomId).collect(Collectors.toSet());
// DELETE FROM ry_model_content WHERE room_id in '1'
if (!roomIds.isEmpty())
{
modelContentMapper.deleteByRoomIds(roomIds);
}
for (ModelContentDTO modelContentDTO : list) {
ModelContentDO modelContentDO = ModelContentDTO.dtoConvertDO(modelContentDTO);
disposeDO(modelContentDO);
save(modelContentDO);
}
}
/**
* DOid
*
* @param modelContentDO
*/
public void disposeDO(ModelContentDO modelContentDO) {
//这里是空肯定是add
if (StrUtil.isEmpty(modelContentDO.getId()))
return;
//判断是否是前端生成的id
if (!modelContentDO.getId().matches("\\d+"))
modelContentDO.setId(null);
}
}

@ -1,16 +1,11 @@
package com.sz.admin.monitor.service.impl;
import com.mybatisflex.core.query.QueryWrapper;
import com.sz.admin.monitor.mapper.CameraMapper;
import com.sz.admin.monitor.mapper.NvrMapper;
import com.sz.admin.monitor.mapper.RegionMapper;
import com.sz.admin.monitor.mapper.SubstationMapper;
import com.sz.admin.monitor.mapper.*;
import com.sz.admin.monitor.pojo.po.Camera;
import com.sz.admin.monitor.pojo.po.Nvr;
import com.sz.admin.monitor.pojo.po.Region;
import com.sz.admin.monitor.pojo.po.Substation;
import com.sz.admin.monitor.pojo.po.*;
import com.sz.admin.monitor.pojo.vo.tree.CameraNodeVO;
import com.sz.admin.monitor.pojo.vo.tree.ComputerRoomNodeVO;
import com.sz.admin.monitor.pojo.vo.tree.NvrNodeVO;
import com.sz.admin.monitor.pojo.vo.tree.TreeNodeVO;
import com.sz.admin.monitor.service.TreeService;
@ -38,6 +33,8 @@ public class TreeServiceImpl implements TreeService {
private NvrMapper nvrMapper;
@Resource
private CameraMapper cameraMapper;
@Resource
private ComputeRoomMapper computeRoomMapper;
@Override
public List<TreeNodeVO> buildTree() {
@ -68,6 +65,37 @@ public class TreeServiceImpl implements TreeService {
return treeRootList;
}
@Override
public List<TreeNodeVO> buildTreeComputeRoom() {
// 查询出所有的边电站
List<Substation> substationList = substationMapper.selectAll();
List<TreeNodeVO> treeRootList = new ArrayList<>();
for (Substation substation : substationList) {
TreeNodeVO rootNode = new TreeNodeVO(substation.getId(), substation.getName(), 1, null);
List<TreeNodeVO> computeChildren = loadChildrenForRoom(substation.getId());
rootNode.setChildren(computeChildren);
treeRootList.add(rootNode);
}
return treeRootList;
}
private List<TreeNodeVO> loadChildrenForRoom(Long id) {
QueryWrapper computeRoomQuery = new QueryWrapper();
computeRoomQuery.eq("substation_id", id);
List<ComputerRoom> computeRoomList = computeRoomMapper.selectListByQuery(computeRoomQuery);
List<TreeNodeVO> children = new ArrayList<>();
for (ComputerRoom computeRoom : computeRoomList) {
ComputerRoomNodeVO computeRoomNode =new ComputerRoomNodeVO();
computeRoomNode.setId(computeRoom.getId());
computeRoomNode.setName(computeRoom.getName());
computeRoomNode.setType(4);
computeRoomNode.setSubstationId(computeRoom.getSubstationId());
computeRoomNode.setChildren(null);
children.add(computeRoomNode);
}
return children;
}
private List<TreeNodeVO> loadChildrenForRegion(Long id) {
QueryWrapper childRegionQuery = new QueryWrapper();
childRegionQuery.eq("parent_id", id);

@ -0,0 +1,34 @@
package com.sz.admin.monitor.service.impl;
import cn.hutool.core.collection.CollectionUtil;
import com.mybatisflex.spring.service.impl.ServiceImpl;
import com.sz.admin.monitor.mapper.SubstationMapper;
import com.sz.admin.monitor.mapper.UserModelContentMapper;
import com.sz.admin.monitor.pojo.dto.dataModel.ModelContentDTO;
import com.sz.admin.monitor.pojo.po.Substation;
import com.sz.admin.monitor.pojo.po.UserModelContentDO;
import com.sz.admin.monitor.service.SubstationService;
import com.sz.admin.monitor.service.UserModelContentService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* @author xq
* @description:
* @date 2026/3/13 10:23
*/
@Service
@RequiredArgsConstructor
public class UserModelContentServiceImpl extends ServiceImpl<UserModelContentMapper, UserModelContentDO> implements UserModelContentService {
@Override
public void saveOrUpdateModel(List<ModelContentDTO> list) {
if(CollectionUtil.isEmpty(list))
return;
for (ModelContentDTO modelContentDTO : list) {
ModelContentDTO.dtoConvertDO(modelContentDTO);
}
}
}

@ -8,25 +8,18 @@ import com.sz.admin.monitor.mapper.CameraAlarmMapper;
import com.sz.admin.monitor.mapper.CameraMapper;
import com.sz.admin.monitor.mapper.NvrMapper;
import com.sz.admin.monitor.pojo.dto.edgebox.BoxAlarmReportDto;
import com.sz.admin.monitor.pojo.po.Camera;
import com.sz.admin.monitor.pojo.po.CameraAlarm;
import com.sz.admin.monitor.pojo.po.Nvr;
import com.sz.admin.monitor.pojo.po.Preset;
import com.sz.admin.monitor.pojo.po.*;
import com.sz.admin.monitor.pojo.vo.camerasnapshot.CameraSnapshotVO;
import com.sz.admin.monitor.sdk.ManageNVR;
import com.sz.admin.monitor.service.CameraService;
import com.sz.admin.monitor.service.CameraSnapshotService;
import com.sz.admin.monitor.service.ForwardService;
import com.sz.admin.monitor.service.PresetService;
import com.sz.admin.monitor.utils.ImageNameUtils;
import com.sz.admin.monitor.utils.OffsetCalculator;
import com.sz.admin.monitor.utils.RobustImageMatcherUtil;
import com.sz.admin.monitor.service.*;
import com.sz.admin.monitor.utils.*;
import com.sz.admin.system.pojo.dto.sysmessage.Message;
import com.sz.admin.system.service.SysMessageService;
import com.sz.core.common.entity.SocketMessage;
import com.sz.core.common.entity.TransferMessage;
import com.sz.core.common.enums.MessageTransferScopeEnum;
import com.sz.core.common.enums.SocketChannelEnum;
import com.sz.core.util.JsonUtils;
import com.sz.redis.WebsocketRedisService;
import com.sz.security.core.util.LoginUtils;
import jakarta.annotation.Resource;
@ -40,10 +33,14 @@ import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.util.Base64;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executor;
/**
* ClassName: ScheduleTask
@ -71,7 +68,10 @@ public class ScheduledTask {
private SysMessageService sysMessageService;
@Resource
private ForwardService forwardService;
@Resource
private BlurDetectionService blurDetectionService;
@Resource(name = "cameraInspectionExecutor")
private Executor cameraInspectionExecutor;
// @Scheduled(cron = "0/5 * * * * ?")
public void test()
@ -89,10 +89,209 @@ public class ScheduledTask {
msg.setToPushAll(true);
websocketRedisService.sendServiceToWs(msg);
}
// 定期模糊检测
// @Scheduled(cron = "0/20 * * * * ?")
public void executeFuzzyDetection() {
log.info("执行模糊检测");
// 遍历模糊检测表
List<BlurDetection> blurDetectionList = blurDetectionService.list();
// 过滤掉关闭的状态
blurDetectionList = blurDetectionList.stream().filter(blurDetection -> blurDetection.getEnable() == 1).toList();
if (blurDetectionList.isEmpty()) {
log.info("无启用的模糊检测任务");
return;
}
int count = 0;
for (BlurDetection blurDetection : blurDetectionList) {
Long cameraId = blurDetection.getCameraId();
try {
Camera camera = cameraService.getById(cameraId);
// 获取基准图
String imagePath1 = camera.getHomeImagePath();
// 检查基准图是否存在
boolean isExists = true;
if (imagePath1 == null || imagePath1.trim().isEmpty()) {
log.warn("摄像头[{}] 未设置基准图路径", cameraId);
isExists = false;
} else {
File file1 = new File(imagePath1);
if (!file1.exists() || !file1.isFile()) {
log.error("基准图文件物理路径不存在:{}", imagePath1);
isExists = false;
}
}
// 抓取当前图
String filename = ImageNameUtils.generateFileName("CAPTURE", cameraId);
String imagePath2 = manageNVR.capturePic(cameraId.intValue(), filename);
if (imagePath2 == null || imagePath2.isEmpty()) {
log.error("抓拍图片失败,摄像头 ID: {}", cameraId);
continue;
}
// 检查抓拍图是否存在
File file2 = new File(imagePath2);
if (!file2.exists() || !file2.isFile()) {
log.error("抓拍图不存在:{}", imagePath2);
continue;
}
count++;
// 进行单一背景检测
// BackgroundDetector.DetectResult result = BackgroundDetector.detectBackground(imagePath2);
// if("1".equals(result.value))
// {
// // 当前摄像头面对的是白墙,直接进行报警
// handleAnalysisResult(blurDetection, imagePath2, result);
// continue;
// }
// 进行模糊图片对比
BlurDetectorV4.DetectResult detectResult = null;
if (isExists) {
// 基准图存在,使用双图对比功能
// 检查是否对着墙壁或者特征不明显的地方
BlurrinessComparator.DetectResult result = BlurrinessComparator.compareBlurriness(imagePath1, imagePath2);
if (result.value.equals("1")) {
// 当前摄像头面对的是白墙,直接进行报警
handleAnalysisResult(blurDetection, imagePath2, result);
continue;
}
detectResult = BlurDetectorV4.doubleDetectBlur(imagePath1, imagePath2);
} else {
// 基准图不存在,使用单图对比功能
detectResult = BlurDetectorV4.detectBlur(imagePath2);
}
log.info("模糊检测结果:{}", detectResult);
handleAnalysisResult(blurDetection, imagePath1, imagePath2, detectResult, isExists);
log.info("模糊检测完成,共检测{}个摄像头", count);
} catch (Exception e) {
log.error("摄像头 ID [{}] 模糊检测过程中发生未知异常", cameraId, e);
}
}
}
//Result{type='bpmh', value='1', code='2000', desc='模糊 score=39.82', conf=1.0, score=39.82, ratio=0.00}
public record DetectResult(String desc,double score) {
}
// 分析背景检测结果并且报警
private void handleAnalysisResult(BlurDetection blurDetection, String imagePath, BlurrinessComparator.DetectResult result) throws IOException {
Camera camera = cameraService.getById(blurDetection.getCameraId());
CameraAlarm cameraAlarm = new CameraAlarm();
cameraAlarm.setCameraId(camera.getId());
Nvr nvr = nvrMapper.selectOneById(camera.getNvrId());
cameraAlarm.setAlarmType(6);
cameraAlarm.setAlarmAreaId(nvr.getStationId());
cameraAlarm.setChannelId(camera.getChannelId());
cameraAlarm.setCameraNo(camera.getCameraNo());
cameraAlarm.setCameraName(camera.getName());
cameraAlarm.setCaptureImage(imagePath);
DetectResult backgroundResult = new DetectResult(result.desc, result.score);
cameraAlarm.setAlgoResult(JsonUtils.toJsonString(backgroundResult));
cameraAlarm.setStatus(0);
cameraAlarmMapper.insert(cameraAlarm);
SocketMessage bean = new SocketMessage();
Map<String, Object> data = new HashMap<>();
data.put("title", "摄像头报警");
data.put("content", "摄像头[" + camera.getId() + "]发生模糊,请及时处理!");
bean.setData(JSON.toJSONString(data));
bean.setChannel(SocketChannelEnum.MESSAGE);
bean.setScope(MessageTransferScopeEnum.SOCKET_CLIENT);
TransferMessage msg = new TransferMessage();
msg.setMessage(bean);
msg.setFromUser("system");
msg.setToPushAll(true);
websocketRedisService.sendServiceToWs(msg);
BoxAlarmReportDto reportDto = new BoxAlarmReportDto();
// 获取时间字符串
String timeStr = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
DateTimeFormatter timeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
LocalDateTime localDateTime = LocalDateTime.parse(timeStr, timeFormatter);
// 转成时间戳(毫秒)
long timestamp = localDateTime.toInstant(ZoneOffset.ofHours(8)).toEpochMilli();
reportDto.setAlarmTime(timestamp);
reportDto.setAlarmTypeDesc(AlarmReportEnums.BLUR_ALARM.getAlarmDescription());
byte[] CaptureFileContent = Files.readAllBytes(Paths.get(imagePath));
reportDto.setAlarmImage(Base64.getEncoder().encodeToString(CaptureFileContent));
reportDto.setCameraName(camera.getName());
reportDto.setAlarmType(AlarmReportEnums.BLUR_ALARM.getAlarmCode());
reportDto.setCameraId(camera.getId());
reportDto.setCameraNo(camera.getCameraNo());
try {
forwardService.enrichAndForward(blurDetection.getUrl(),reportDto);
}catch (Exception e)
{
log.error("模糊报警上报失败,摄像头 ID: {}, 相机编号:{}",
camera.getId(), camera.getCameraNo(), e);
}
}
// 分析模糊算法并且报警
private void handleAnalysisResult(BlurDetection blurDetection, String imagePath1, String imagePath2, BlurDetectorV4.DetectResult detectResult, boolean isExists) throws IOException {
if ("1".equals(detectResult.value)) {
// 发生了模糊,需要保存报警信息等人工处理
Camera camera = cameraService.getById(blurDetection.getCameraId());
CameraAlarm cameraAlarm = new CameraAlarm();
cameraAlarm.setCameraId(camera.getId());
// 设置告警区域
// 根据摄像头查询它对应的nvr
Nvr nvr = nvrMapper.selectOneById(camera.getNvrId());
// 设置告警区域
cameraAlarm.setAlarmType(6);
cameraAlarm.setAlarmAreaId(nvr.getStationId());
cameraAlarm.setChannelId(camera.getChannelId());
cameraAlarm.setCameraNo(camera.getCameraNo());
cameraAlarm.setCameraName(camera.getName());
cameraAlarm.setBaseImage(imagePath1);
cameraAlarm.setCaptureImage(imagePath2);
// 算法的结果
DetectResult result = new DetectResult(detectResult.desc, detectResult.score);
cameraAlarm.setAlgoResult(JsonUtils.toJsonString(result));
// 状态为未处理
cameraAlarm.setStatus(0);
cameraAlarmMapper.insert(cameraAlarm);
// log.info("生成模糊报警: 通道{}, 模糊信息: {}", camera.getChannelId(), detectResult.getDescription());
// 向前端主动推送消息
SocketMessage bean = new SocketMessage();
Map<String, Object> data = new HashMap<>();
data.put("title", "摄像头报警");
data.put("content", "摄像头[" + camera.getId() + "]发生模糊,请及时处理!");
bean.setData(JSON.toJSONString(data));
bean.setChannel(SocketChannelEnum.MESSAGE);
bean.setScope(MessageTransferScopeEnum.SOCKET_CLIENT);
TransferMessage msg = new TransferMessage();
msg.setMessage(bean);
msg.setFromUser("system");
msg.setToPushAll(true);
websocketRedisService.sendServiceToWs(msg);
// 统一处理报警信息后,将摄像头信息+报警信息上报给别人服务器
BoxAlarmReportDto reportDto = new BoxAlarmReportDto();
// 获取时间字符串
String timeStr = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
DateTimeFormatter timeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
LocalDateTime localDateTime = LocalDateTime.parse(timeStr, timeFormatter);
// 转成时间戳(毫秒)
long timestamp = localDateTime.toInstant(ZoneOffset.ofHours(8)).toEpochMilli();
reportDto.setAlarmTime(timestamp);
reportDto.setAlarmTypeDesc(AlarmReportEnums.BLUR_ALARM.getAlarmDescription());
if(isExists && imagePath1 !=null) {
byte[] BaseFileContent = Files.readAllBytes(Paths.get(imagePath1));
reportDto.setBaseImage(Base64.getEncoder().encodeToString(BaseFileContent));
}
byte[] CaptureFileContent = Files.readAllBytes(Paths.get(imagePath2));
reportDto.setAlarmImage(Base64.getEncoder().encodeToString(CaptureFileContent));
reportDto.setCameraName(camera.getName());
reportDto.setAlarmType(AlarmReportEnums.BLUR_ALARM.getAlarmCode());
reportDto.setCameraId(camera.getId());
reportDto.setCameraNo(camera.getCameraNo());
try {
forwardService.enrichAndForward(blurDetection.getUrl(),reportDto);
}catch (Exception e)
{
log.error("模糊报警上报失败,摄像头 ID: {}, 相机编号:{}",
camera.getId(), camera.getCameraNo(), e);
}
}
}
// 定期检查
@Scheduled(cron = "0/20 * * * * ?")
@SneakyThrows
public void executeInspection() {
public void executeInspection() throws InterruptedException {
// 从摄像头表中获取设置了抓图对比和在线的摄像头
List<Camera> cameraList = cameraService.selectListByInspection();
// 然后根据摄像头id查询设置为标准位的预置位
@ -104,36 +303,53 @@ public class ScheduledTask {
}
List<Preset> presetList = presetService.selectByCameraIds(cameraIds);
for (Preset preset : presetList) {
// 调用SDK让摄像头回归到该预置位
boolean ok = manageNVR.ptzPresets(preset.getCameraId().intValue(), 39, String.valueOf(preset.getPresetId()), preset.getPresetName());
// 延时5秒
CompletableFuture.runAsync(() -> {
// 调用具体的单次检测逻辑
processSinglePreset(preset);
}, cameraInspectionExecutor).exceptionally(e -> {
// 捕获线程池级别或执行过程中的严重异常
log.error("预置位[{}]异步巡检任务执行失败", preset.getPresetId(), e);
return null;
});
}
}
private void processSinglePreset(Preset preset) {
Long cameraId = preset.getCameraId();
try {
boolean ok = manageNVR.ptzPresets(cameraId.intValue(), 39, String.valueOf(preset.getPresetId()), preset.getPresetName());
// 这里的 sleep 现在是在独立的异步线程中执行的,不会阻塞主线程!
Thread.sleep(5000);
if (ok) {
// 抓取一张图片
String filename = ImageNameUtils.generateFileName("CAPTURE",preset.getCameraId());
//String image2 = "D:\\work\\images\\CAPTURE_367_20260212092406664_2d117293.jpg";
// String image2 = "D:\\work\\images\\CAPTURE_19_20260302152457977_db33f5a8.jpg";
String image2 = manageNVR.capturePic(preset.getCameraId().intValue(), filename);
// 从图片表中根据预置位摄像机id类型为巡检为条件查询出基准图
CameraSnapshotVO cameraSnapshotVO = cameraSnapshotService.selectByCameraIdAndPresetIndex(preset.getCameraId(), preset.getPresetId());
if (cameraSnapshotVO == null || cameraSnapshotVO.getImagePath() == null) {
log.warn("摄像机[{}] 未设置基准图,无法对比", preset.getCameraId());
continue;
String filename = ImageNameUtils.generateFileName("CAPTURE", cameraId);
String image2 = manageNVR.capturePic(cameraId.intValue(), filename);
//String image2="D:\\work\\images\\CAPTURE_258_20260331104152476_de86220b.jpg";
// 抓图合法性校验
if (image2 == null || image2.isBlank()) {
log.error("摄像机[{}] 抓拍失败,无法获取当前图片", cameraId);
return; // 结束当前预置位的处理
}
CameraSnapshotVO cameraSnapshotVO = cameraSnapshotService.selectByCameraIdAndPresetIndex(cameraId, preset.getPresetId());
if (cameraSnapshotVO == null || cameraSnapshotVO.getImagePath() == null || cameraSnapshotVO.getImagePath().isBlank()) {
log.warn("摄像机[{}] 未设置预置位基准图,无法对比", cameraId);
return;
}
// 调用图片对比算法,校验摄像头是否移位
// 基准图
String image1 = cameraSnapshotVO.getImagePath();
// 对比
Map<String, Object> map = RobustImageMatcherUtil.calculateOffset(image1, image2);
log.info("图片对比结果:{}", map);
// 判断结果并报警
handleAnalysisResult(preset, cameraSnapshotVO.getImagePath(), image2, map);
log.info("摄像机[{}] 预置位[{}] 对比结果:{}", cameraId, preset.getPresetId(), map);
if (map != null && map.containsKey("value")) {
handleAnalysisResult(preset, image1, image2, map);
}
}
} catch (InterruptedException ie) {
log.error("摄像机[{}] 等待云台转动被中断", cameraId);
Thread.currentThread().interrupt();
} catch (Exception e) {
log.error("摄像机[{}] 预置位[{}] 巡检过程中发生业务异常", cameraId, preset.getPresetId(), e);
}
}
//判断结果并报警
//判断移位算法结果并报警
private void handleAnalysisResult(Preset preset, String imagePath, String image2, Map<String, Object> map) throws IOException {
int value = (int) map.get("value");
if (value == 1) {
@ -147,6 +363,7 @@ public class ScheduledTask {
// 设置告警区域
cameraAlarm.setAlarmAreaId(nvr.getStationId());
cameraAlarm.setChannelId(camera.getChannelId());
cameraAlarm.setCameraNo(camera.getCameraNo());
cameraAlarm.setCameraName(camera.getName());
cameraAlarm.setPresetIndex(preset.getPresetId());
// 标记为移位报警
@ -174,18 +391,29 @@ public class ScheduledTask {
websocketRedisService.sendServiceToWs(msg);
// 统一处理报警信息后,将摄像头信息+报警信息上报给别人服务器
BoxAlarmReportDto reportDto = new BoxAlarmReportDto();
reportDto.setAlarmReportTime(LocalDateTime.now());
reportDto.setAlarmReportType(AlarmReportEnums.DISPLACEMENT_ALARM.getAlarmDescription());
reportDto.setDescription("摄像头发生移位");
// 获取时间字符串
String timeStr = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
DateTimeFormatter timeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
LocalDateTime localDateTime = LocalDateTime.parse(timeStr, timeFormatter);
// 转成时间戳(毫秒)
long timestamp = localDateTime.toInstant(ZoneOffset.ofHours(8)).toEpochMilli();
reportDto.setAlarmTime(timestamp);
reportDto.setAlarmTypeDesc(AlarmReportEnums.DISPLACEMENT_ALARM.getAlarmDescription());
byte[] BaseFileContent = Files.readAllBytes(Paths.get(imagePath));
reportDto.setBaseImage(Base64.getEncoder().encodeToString(BaseFileContent));
byte[] CaptureFileContent = Files.readAllBytes(Paths.get(image2));
reportDto.setCaptureImage(Base64.getEncoder().encodeToString(CaptureFileContent));
reportDto.setUrl(preset.getPresetUrl());
reportDto.setAlarmImage(Base64.getEncoder().encodeToString(CaptureFileContent));
reportDto.setCameraName(camera.getName());
reportDto.setCameraId(camera.getId());
reportDto.setAlarmType(AlarmReportEnums.DISPLACEMENT_ALARM.getAlarmCode());
reportDto.setCameraNo(camera.getCameraNo());
forwardService.enrichAndForward(reportDto);
try {
forwardService.enrichAndForward(preset.getPresetUrl(),reportDto);
}catch (Exception e)
{
log.error("移位报警上报失败,摄像头 ID: {}, 相机编号:{}",
camera.getId(), camera.getCameraNo(), e);
}
}
}

@ -0,0 +1,234 @@
package com.sz.admin.monitor.utils;
import org.bytedeco.javacpp.indexer.FloatIndexer;
import org.bytedeco.javacpp.indexer.IntIndexer;
import org.bytedeco.javacpp.indexer.UByteIndexer;
import org.bytedeco.opencv.opencv_core.Mat;
import org.bytedeco.opencv.opencv_core.MatVector;
import org.bytedeco.opencv.opencv_core.Size;
import org.bytedeco.opencv.opencv_core.TermCriteria;
import java.util.HashMap;
import java.util.Map;
import static org.bytedeco.opencv.global.opencv_core.*;
import static org.bytedeco.opencv.global.opencv_imgcodecs.imread;
import static org.bytedeco.opencv.global.opencv_imgproc.*;
public class BackgroundDetector {
// ===============================
// 统一的对外返回结果类 (与 V3/V4 一致)
// ===============================
public static class DetectResult {
public String type;
public String value;
public String code;
public String desc;
public double conf;
public double score;
public double ratio;
public DetectResult(String type, String value, String code, String desc, double conf, double score, double ratio) {
this.type = type;
this.value = value;
this.code = code;
this.desc = desc;
this.conf = conf;
this.score = score;
this.ratio = ratio;
}
@Override
public String toString() {
return String.format("Result{type='%s', value='%s', code='%s', desc='%s', conf=%.1f, score=%.2f, ratio=%.2f}",
type, value, code, desc, conf, score, ratio);
}
}
// ===============================
// 内部使用的算法基础数据封装
// ===============================
private static class InternalDetectionResult {
public boolean hasLargeBackground;
public double continuousBackgroundRatio;
public double totalMaxLabelRatio;
public Map<String, Integer> mainBackgroundColor;
}
// ===============================
// 对外暴露的公共访问方法 (默认参数)
// ===============================
public static DetectResult detectBackground(String imagePath) {
// 默认参数设定
int nClusters = 3;
double areaThreshold = 0.55;
int kernelSize = 5;
boolean useGray = false;
double clusterThreshold = 0.55;
return detectBackground(imagePath, nClusters, areaThreshold, kernelSize, useGray, clusterThreshold);
}
// ===============================
// 对外暴露的公共访问方法 (支持自定义参数)
// ===============================
public static DetectResult detectBackground(String imagePath, int nClusters, double areaThreshold,
int kernelSize, boolean useGray, double clusterThreshold) {
Mat img = imread(imagePath);
if (img == null || img.empty()) {
throw new IllegalArgumentException("无法读取图片或图片不存在: " + imagePath);
}
try {
// 调用核心算法
InternalDetectionResult internalResult = detectLargeContinuousBackground(
img, nClusters, areaThreshold, kernelSize, useGray, clusterThreshold);
// 将连续背景占比转化为 0-100 的 score 形式便于理解
double score = internalResult.continuousBackgroundRatio * 100.0;
// 拼接详细描述信息
String desc = String.format("连续背景占比:%.2f%%, 最大聚类占比:%.2f%%, 主颜色:%s",
score,
internalResult.totalMaxLabelRatio * 100.0,
internalResult.mainBackgroundColor.toString());
String detectTypeKey = "background";
if (internalResult.hasLargeBackground) {
// value="1" 表示检测出大片连续背景 (异常状态)code 给 4001
return new DetectResult(detectTypeKey, "1", "4001", "大片连续/纯色背景 [" + desc + "]", 1.0, score, 0.0);
} else {
// value="0" 表示正常图片
return new DetectResult(detectTypeKey, "0", "2000", "正常背景 [" + desc + "]", 1.0, score, 0.0);
}
} finally {
// 确保释放读取的图片内存
img.close();
}
}
// ===============================
// 核心算法实现:基于颜色聚类+连通域
// ===============================
private static InternalDetectionResult detectLargeContinuousBackground(
Mat img, int nClusters, double areaThreshold, int kernelSize, boolean useGray, double clusterThreshold) {
int h = img.rows();
int w = img.cols();
int totalPixels = h * w;
Mat processed = new Mat();
Mat reshaped32f = new Mat();
// 1. 预处理
if (useGray) {
cvtColor(img, processed, COLOR_BGR2GRAY);
Mat kernel = getStructuringElement(MORPH_RECT, new Size(kernelSize, kernelSize));
morphologyEx(processed, processed, MORPH_OPEN, kernel);
} else {
GaussianBlur(img, processed, new Size(3, 3), 0);
}
// 重塑为K-Means输入格式
Mat reshaped = processed.reshape(1, totalPixels);
reshaped.convertTo(reshaped32f, CV_32F);
// 2. K-Means颜色聚类
Mat labels = new Mat();
Mat centers = new Mat();
TermCriteria criteria = new TermCriteria(CV_TERMCRIT_EPS + CV_TERMCRIT_ITER, 10, 1.0);
kmeans(reshaped32f, nClusters, labels, criteria, 10, KMEANS_PP_CENTERS, centers);
// 3. 统计最大类
int[] labelCounts = new int[nClusters];
IntIndexer labelIndexer = labels.createIndexer();
for (int i = 0; i < totalPixels; i++) {
int label = labelIndexer.get(i, 0);
labelCounts[label]++;
}
int maxLabel = 0;
int maxCount = 0;
for (int i = 0; i < nClusters; i++) {
if (labelCounts[i] > maxCount) {
maxCount = labelCounts[i];
maxLabel = i;
}
}
double maxLabelRatio = (double) maxCount / totalPixels;
// 4. 生成最大类的掩码并分析连通域
Mat mask = new Mat(h, w, CV_8UC1);
UByteIndexer maskIndexer = mask.createIndexer();
int pixelIdx = 0;
for (int y = 0; y < h; y++) {
for (int x = 0; x < w; x++) {
int label = labelIndexer.get(pixelIdx++, 0);
maskIndexer.put(y, x, label == maxLabel ? 255 : 0);
}
}
MatVector contours = new MatVector();
Mat hierarchy = new Mat();
findContours(mask, contours, hierarchy, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE);
double largestContourArea = 0;
for (int i = 0; i < contours.size(); i++) {
double area = contourArea(contours.get(i));
if (area > largestContourArea) {
largestContourArea = area;
}
}
double continuousBackgroundRatio = largestContourArea / totalPixels;
boolean hasLargeBackground = (continuousBackgroundRatio >= areaThreshold) && (maxLabelRatio >= clusterThreshold);
// 5. 提取主颜色
FloatIndexer centersIndexer = centers.createIndexer();
Map<String, Integer> mainColor = new HashMap<>();
if (useGray) {
mainColor.put("gray", (int) centersIndexer.get(maxLabel, 0));
} else {
mainColor.put("B", (int) centersIndexer.get(maxLabel, 0));
mainColor.put("G", (int) centersIndexer.get(maxLabel, 1));
mainColor.put("R", (int) centersIndexer.get(maxLabel, 2));
}
// 6. 构造内部返回结果
InternalDetectionResult result = new InternalDetectionResult();
result.hasLargeBackground = hasLargeBackground;
result.continuousBackgroundRatio = continuousBackgroundRatio;
result.totalMaxLabelRatio = maxLabelRatio;
result.mainBackgroundColor = mainColor;
// 释放临时对象
processed.close();
reshaped32f.close();
reshaped.close();
labels.close();
centers.close();
mask.close();
hierarchy.close();
return result;
}
// ===============================
// 测试入口
// ===============================
public static void main(String[] args) {
// 替换为你的真实测试图片路径
String path = "D:\\work\\ceshi\\bai.jpg";
try {
System.out.println("===== 开始检测 =====");
// 直接调用极简的封装方法
DetectResult result = detectBackground(path);
System.out.println(result.toString());
} catch (Exception e) {
e.printStackTrace();
}
}
}

@ -0,0 +1,326 @@
package com.sz.admin.monitor.utils;
import org.bytedeco.opencv.opencv_core.*;
import org.bytedeco.opencv.opencv_imgproc.*;
import static org.bytedeco.opencv.global.opencv_core.*;
import static org.bytedeco.opencv.global.opencv_imgcodecs.*;
import static org.bytedeco.opencv.global.opencv_imgproc.*;
public class BlurDetectorV2 {
// ===============================
// 数据返回类 (替代 Python 中的 dict)
// ===============================
public static class DetectResult {
public String type;
public String value;
public String code;
public String desc;
public double conf;
public double score; // 显式记录分数,替代正则解析
public double ratio; // 双图比较时的比率
public DetectResult(String type, String value, String code, String desc, double conf, double score, double ratio) {
this.type = type;
this.value = value;
this.code = code;
this.desc = desc;
this.conf = conf;
this.score = score;
this.ratio = ratio;
}
@Override
public String toString() {
return String.format("Result{value='%s', code='%s', desc='%s'}", value, code, desc);
}
}
// ===============================
// 光照归一化
// ===============================
private static Mat normalizeLighting(Mat gray) {
Mat dst = new Mat();
try (CLAHE clahe = createCLAHE(3.0, new Size(8, 8))) {
clahe.apply(gray, dst);
}
return dst;
}
// ===============================
// Laplacian 清晰度
// ===============================
private static double laplacianScore(Mat gray) {
try (Mat lap = new Mat(); Mat mean = new Mat(); Mat stddev = new Mat()) {
Laplacian(gray, lap, CV_64F);
meanStdDev(lap, mean, stddev);
double sd = stddev.createIndexer().getDouble();
return sd * sd; // 方差
}
}
// ===============================
// Tenengrad 梯度
// ===============================
private static double tenengradScore(Mat gray) {
try (Mat gx = new Mat(); Mat gy = new Mat();
Mat gx2 = new Mat(); Mat gy2 = new Mat();
Mat g = new Mat()) {
Sobel(gray, gx, CV_64F, 1, 0, 3, 1.0, 0.0, BORDER_DEFAULT);
Sobel(gray, gy, CV_64F, 0, 1, 3, 1.0, 0.0, BORDER_DEFAULT);
multiply(gx, gx, gx2);
multiply(gy, gy, gy2);
add(gx2, gy2, g);
return mean(g).get(0);
}
}
// ===============================
// Edge Density边缘密度
// ===============================
private static double edgeDensity(Mat gray) {
try (Mat edges = new Mat()) {
Canny(gray, edges, 80, 150);
int nonZero = countNonZero(edges);
return (double) nonZero / (edges.rows() * edges.cols());
}
}
// ===============================
// FFT 高频能量 (最终完美版)
// ===============================
private static double fftHighFrequency(Mat gray) {
// 第一层:初始化所有基础操作矩阵,这些变量在此块内不可被重新赋值
try (Mat f32 = new Mat();
Mat zeros = Mat.zeros(gray.size(), CV_32F).asMat();
MatVector planes = new MatVector(2);
Mat complexI = new Mat();
Mat mag = new Mat();
Mat ones = Mat.ones(gray.size(), CV_32F).asMat();
Mat tmp = new Mat()) {
// 1. 转为浮点并合并为双通道复数矩阵
gray.convertTo(f32, CV_32F);
planes.put(0, f32);
planes.put(1, zeros);
merge(planes, complexI);
// 2. 傅里叶变换
dft(complexI, complexI);
// 3. 计算幅度: magnitude = log(abs(fshift) + 1)
split(complexI, planes);
magnitude(planes.get(0), planes.get(1), mag);
add(mag, ones, mag);
log(mag, mag);
// 4. fftshift 平移 (将低频移到中心)
// 声明新的变量 croppedMag 来接收裁剪结果,避免给 mag 重新赋值引发报错
try (Mat croppedMag = new Mat(mag, new Rect(0, 0, mag.cols() & -2, mag.rows() & -2))) {
int cx = croppedMag.cols() / 2;
int cy = croppedMag.rows() / 2;
// 第三层:声明所有的子矩阵 (ROI) 和 mask确保它们用完后被自动释放
try (Mat q0 = new Mat(croppedMag, new Rect(0, 0, cx, cy));
Mat q1 = new Mat(croppedMag, new Rect(cx, 0, cx, cy));
Mat q2 = new Mat(croppedMag, new Rect(0, cy, cx, cy));
Mat q3 = new Mat(croppedMag, new Rect(cx, cy, cx, cy));
Mat mask = new Mat(croppedMag.size(), CV_32F, new Scalar(1.0))) {
// 象限交换 (Shift)
q0.copyTo(tmp);
q3.copyTo(q0);
tmp.copyTo(q3);
q1.copyTo(tmp);
q2.copyTo(q1);
tmp.copyTo(q2);
// 5. Mask 屏蔽中心低频
int r = Math.min(cx, cy) / 4;
rectangle(mask,
new Point(cx - r, cy - r),
new Point(cx + r, cy + r),
new Scalar(0.0),
-1, 8, 0);
// 6. 对应元素相乘 (只保留高频部分)
multiply(croppedMag, mask, croppedMag);
// 7. 计算整体高频均值
return mean(croppedMag).get(0);
}
}
}
}
// ===============================
// 白墙和纯色背景图检测
// ===============================
private static boolean isWhiteWall(Mat image) {
try (Mat hsv = new Mat();
Mat mask = new Mat();
Mat lower = new Mat(1, 1, CV_8UC3, new Scalar(0, 0, 200, 0));
Mat upper = new Mat(1, 1, CV_8UC3, new Scalar(180, 40, 255, 0));
Mat gray = new Mat()) {
cvtColor(image, hsv, COLOR_BGR2HSV);
inRange(hsv, lower, upper, mask);
double ratio = (double) countNonZero(mask) / (mask.rows() * mask.cols());
cvtColor(image, gray, COLOR_BGR2GRAY);
double lap = laplacianScore(gray);
double edge = edgeDensity(gray);
if (ratio > 0.7 && lap < 15) {
return true;
}
if (lap < 10 && edge < 0.02) {
return true;
}
return false;
}
}
// ===============================
// ROI中心区域 (切片等价实现)
// ===============================
private static Mat extractRoi(Mat image) {
int h = image.rows();
int w = image.cols();
int y = h / 5;
int x = w / 5;
int roiH = (4 * h / 5) - y;
int roiW = (4 * w / 5) - x;
return new Mat(image, new Rect(x, y, roiW, roiH));
}
// ===============================
// 模糊检测单图主函数
// ===============================
public static DetectResult detectBlur(Mat image, String detectTypeKey, double threshold) {
if (image == null || image.empty()) {
throw new IllegalArgumentException("image read error");
}
// ===============================
// 白墙过滤
// ===============================
if (isWhiteWall(image)) {
return new DetectResult(detectTypeKey, "1", "4001", "白墙/纯色背景 score=0", 0.0, 0.0, 0.0);
}
try (Mat roiImage = extractRoi(image);
Mat gray = new Mat()) {
cvtColor(roiImage, gray, COLOR_BGR2GRAY);
try (Mat normGray = normalizeLighting(gray)) {
// ===============================
// 计算指标
// ===============================
double lap = laplacianScore(normGray);
double ten = tenengradScore(normGray);
double edge = edgeDensity(normGray);
double fft = fftHighFrequency(normGray);
// ===============================
// 归一化
// ===============================
double lap_n = Math.min(lap / 2000.0, 1.0);
double ten_n = Math.min(ten / 10000.0, 1.0);
double edge_n = Math.min(edge * 10.0, 1.0);
double fft_n = Math.min(fft / 10.0, 1.0);
// ===============================
// 综合评分
// ===============================
double score = (0.35 * lap_n + 0.30 * ten_n + 0.20 * edge_n + 0.15 * fft_n) * 100.0;
String descStr = String.format("score=%.2f", score);
// ===============================
// 判断
// ===============================
if (score < threshold) {
return new DetectResult(detectTypeKey, "1", "2000", "模糊 " + descStr, 1.0, score, 0.0);
} else {
return new DetectResult(detectTypeKey, "0", "2000", "正常 " + descStr, 1.0, score, 0.0);
}
}
}
}
public static DetectResult detectBlur(String imagePath) {
try (Mat img = imread(imagePath)) {
return detectBlur(img, "bpmh", 90.0);
}
}
// ===============================
// 双图检测
// ===============================
public static DetectResult doubleDetectBlur(String imgPath, String refPath, double ratioThreshold) {
boolean useRef = true;
if (refPath == null || refPath.isEmpty()) {
useRef = false;
}
try (Mat imgMat = imread(imgPath);
Mat refMat = useRef ? imread(refPath) : null) {
if (refMat == null || refMat.empty()) {
useRef = false;
}
// 单图模式兜底
if (!useRef) {
return detectBlur(imgMat, "bpmh", 60.0);
}
// 双图模式
DetectResult imgResult = detectBlur(imgMat, "bpmh", 60.0);
DetectResult refResult = detectBlur(refMat, "bpmh", 60.0);
double scoreImg = imgResult.score;
double scoreRef = refResult.score;
if (scoreRef < 1e-6) {
return new DetectResult("bpmh", "0", "2000", "参考图异常", 0.0, scoreImg, 0.0);
}
double ratio = scoreRef / scoreImg;
System.out.println(scoreImg + ", " + scoreRef);
if (ratio < ratioThreshold) {
return new DetectResult("bpmh", "1", "2000", String.format("模糊 ratio=%.2f", ratio), 1.0, scoreImg, ratio);
} else {
return new DetectResult("bpmh", "0", "2000", String.format("正常 ratio=%.2f", ratio), 1.0, scoreImg, ratio);
}
}
}
// ===============================
// 测试入口
// ===============================
public static void main(String[] args) {
String img = "D:\\work\\images\\CAPTURE_265_20260319160327655_79b39c57.jpg"; // 基准图提前给定
String ref = "D:\\work\\images\\CAPTURE_266_20260319160512854_13b52e7e.jpg"; // 摄像头后面传入图像
//Result{value='0', code='2000', desc='正常 ratio=1.01'}
// Result{value='1', code='2000', desc='模糊 ratio=0.69'}
// 默认 ratio_threshold=0.85
// DetectResult result = doubleDetectBlur(img, ref, 0.85);
// 60 到 70
DetectResult detectResult = detectBlur(ref);
System.out.println("单图检测:"+detectResult.toString());
// System.out.println(result.toString());
}
}

@ -0,0 +1,324 @@
package com.sz.admin.monitor.utils;
import org.bytedeco.opencv.opencv_core.*;
import org.bytedeco.opencv.opencv_imgproc.CLAHE;
import static org.bytedeco.opencv.global.opencv_core.*;
import static org.bytedeco.opencv.global.opencv_imgcodecs.imread;
import static org.bytedeco.opencv.global.opencv_imgproc.*;
public class BlurDetectorV3 {
// ===============================
// 数据返回类 (替代 Python 中的 dict)
// ===============================
public static class DetectResult {
public String type;
public String value;
public String code;
public String desc;
public double conf;
public double score; // 显式记录分数,替代正则解析
public double ratio; // 双图比较时的比率
public DetectResult(String type, String value, String code, String desc, double conf, double score, double ratio) {
this.type = type;
this.value = value;
this.code = code;
this.desc = desc;
this.conf = conf;
this.score = score;
this.ratio = ratio;
}
@Override
public String toString() {
return String.format("Result{value='%s', code='%s', desc='%s'}", value, code, desc);
}
}
// ===============================
// 光照归一化
// ===============================
private static Mat normalizeLighting(Mat gray) {
Mat dst = new Mat();
try (CLAHE clahe = createCLAHE(1.5, new Size(8, 8))) {
clahe.apply(gray, dst);
}
return dst;
}
// ===============================
// Laplacian 清晰度
// ===============================
private static double laplacianScore(Mat gray) {
try (Mat lap = new Mat(); Mat mean = new Mat(); Mat stddev = new Mat()) {
Laplacian(gray, lap, CV_64F);
meanStdDev(lap, mean, stddev);
double sd = stddev.createIndexer().getDouble();
return sd * sd; // 方差
}
}
// ===============================
// Tenengrad 梯度
// ===============================
private static double tenengradScore(Mat gray) {
try (Mat gx = new Mat(); Mat gy = new Mat();
Mat gx2 = new Mat(); Mat gy2 = new Mat();
Mat g = new Mat()) {
Sobel(gray, gx, CV_64F, 1, 0, 3, 1.0, 0.0, BORDER_DEFAULT);
Sobel(gray, gy, CV_64F, 0, 1, 3, 1.0, 0.0, BORDER_DEFAULT);
multiply(gx, gx, gx2);
multiply(gy, gy, gy2);
add(gx2, gy2, g);
return mean(g).get(0);
}
}
// ===============================
// Edge Density边缘密度
// ===============================
private static double edgeDensity(Mat gray) {
try (Mat edges = new Mat()) {
Canny(gray, edges, 80, 150);
int nonZero = countNonZero(edges);
return (double) nonZero / (edges.rows() * edges.cols());
}
}
// ===============================
// FFT 高频能量 (最终完美版)
// ===============================
private static double fftHighFrequency(Mat gray) {
// 第一层:初始化所有基础操作矩阵,这些变量在此块内不可被重新赋值
try (Mat f32 = new Mat();
Mat zeros = Mat.zeros(gray.size(), CV_32F).asMat();
MatVector planes = new MatVector(2);
Mat complexI = new Mat();
Mat mag = new Mat();
Mat ones = Mat.ones(gray.size(), CV_32F).asMat();
Mat tmp = new Mat()) {
// 1. 转为浮点并合并为双通道复数矩阵
gray.convertTo(f32, CV_32F);
planes.put(0, f32);
planes.put(1, zeros);
merge(planes, complexI);
// 2. 傅里叶变换
dft(complexI, complexI);
// 3. 计算幅度: magnitude = log(abs(fshift) + 1)
split(complexI, planes);
magnitude(planes.get(0), planes.get(1), mag);
add(mag, ones, mag);
log(mag, mag);
// 4. fftshift 平移 (将低频移到中心)
// 声明新的变量 croppedMag 来接收裁剪结果,避免给 mag 重新赋值引发报错
try (Mat croppedMag = new Mat(mag, new Rect(0, 0, mag.cols() & -2, mag.rows() & -2))) {
int cx = croppedMag.cols() / 2;
int cy = croppedMag.rows() / 2;
// 第三层:声明所有的子矩阵 (ROI) 和 mask确保它们用完后被自动释放
try (Mat q0 = new Mat(croppedMag, new Rect(0, 0, cx, cy));
Mat q1 = new Mat(croppedMag, new Rect(cx, 0, cx, cy));
Mat q2 = new Mat(croppedMag, new Rect(0, cy, cx, cy));
Mat q3 = new Mat(croppedMag, new Rect(cx, cy, cx, cy));
Mat mask = new Mat(croppedMag.size(), CV_32F, new Scalar(1.0))) {
// 象限交换 (Shift)
q0.copyTo(tmp); q3.copyTo(q0); tmp.copyTo(q3);
q1.copyTo(tmp); q2.copyTo(q1); tmp.copyTo(q2);
// 5. Mask 屏蔽中心低频
int r = Math.min(cx, cy) / 4;
rectangle(mask,
new Point(cx - r, cy - r),
new Point(cx + r, cy + r),
new Scalar(0.0),
-1, 8, 0);
// 6. 对应元素相乘 (只保留高频部分)
multiply(croppedMag, mask, croppedMag);
// 7. 计算整体高频均值
return mean(croppedMag).get(0);
}
}
}
}
// ===============================
// 白墙和纯色背景图检测
// ===============================
private static boolean isWhiteWall(Mat image) {
try (Mat hsv = new Mat();
Mat mask = new Mat();
Mat lower = new Mat(1, 1, CV_8UC3, new Scalar(0, 0, 80, 0));
Mat upper = new Mat(1, 1, CV_8UC3, new Scalar(180, 50, 255, 0));
Mat gray = new Mat()) {
cvtColor(image, hsv, COLOR_BGR2HSV);
inRange(hsv, lower, upper, mask);
double ratio = (double) countNonZero(mask) / (mask.rows() * mask.cols());
cvtColor(image, gray, COLOR_BGR2GRAY);
double lap = laplacianScore(gray);
double edge = edgeDensity(gray);
if (ratio > 0.7 && lap < 30) {
return true;
}
if (lap < 15 && edge < 0.03) {
return true;
}
return false;
}
}
// ===============================
// ROI中心区域 (切片等价实现)
// ===============================
private static Mat extractRoi(Mat image) {
int h = image.rows();
int w = image.cols();
int y = h / 5;
int x = w / 5;
int roiH = (4 * h / 5) - y;
int roiW = (4 * w / 5) - x;
return new Mat(image, new Rect(x, y, roiW, roiH));
}
// ===============================
// 模糊检测单图主函数
// ===============================
public static DetectResult detectBlur(Mat image, String detectTypeKey, double threshold) {
if (image == null || image.empty()) {
throw new IllegalArgumentException("image read error");
}
// ===============================
// 白墙过滤
// ===============================
if (isWhiteWall(image)) {
return new DetectResult(detectTypeKey, "1", "4001", "白墙/纯色背景 score=0", 0.0, 0.0, 0.0);
}
try (Mat roiImage = extractRoi(image);
Mat gray = new Mat()) {
cvtColor(roiImage, gray, COLOR_BGR2GRAY);
try (Mat normGray = normalizeLighting(gray);
Mat smoothedGray = new Mat()) {
GaussianBlur(normGray, smoothedGray, new Size(3, 3), 0);
// ===============================
// 计算指标
// ===============================
double lap = laplacianScore(normGray);
double ten = tenengradScore(normGray);
double edge = edgeDensity(normGray);
double fft = fftHighFrequency(normGray);
// ===============================
// 归一化
// ===============================
double lap_n = Math.min(lap / 2000.0, 1.0);
double ten_n = Math.min(ten / 10000.0, 1.0);
double edge_n = Math.min(edge * 10.0, 1.0);
double fft_n = Math.min(fft / 10.0, 1.0);
// ===============================
// 综合评分
// ===============================
double score = (0.35 * lap_n + 0.30 * ten_n + 0.20 * edge_n + 0.15 * fft_n) * 100.0;
String descStr = String.format("score=%.2f", score);
// ===============================
// 判断
// ===============================
if (score < threshold) {
return new DetectResult(detectTypeKey, "1", "2000", "模糊 " + descStr, 1.0, score, 0.0);
} else {
return new DetectResult(detectTypeKey, "0", "2000", "正常 " + descStr, 1.0, score, 0.0);
}
}
}
}
public static DetectResult detectBlur(String imagePath) {
try (Mat img = imread(imagePath)) {
return detectBlur(img, "bpmh", 70.0);
}
}
// ===============================
// 双图检测
// ===============================
public static DetectResult doubleDetectBlur(String imgPath, String refPath, double ratioThreshold) {
boolean useRef = true;
if (refPath == null || refPath.isEmpty()) {
useRef = false;
}
try (Mat imgMat = imread(imgPath);
Mat refMat = useRef ? imread(refPath) : null) {
if (refMat == null || refMat.empty()) {
useRef = false;
}
// 单图模式兜底
if (!useRef) {
return detectBlur(imgMat, "bpmh", 60.0);
}
// 双图模式
DetectResult imgResult = detectBlur(imgMat, "bpmh", 60.0);
DetectResult refResult = detectBlur(refMat, "bpmh", 60.0);
double scoreImg = imgResult.score;
double scoreRef = refResult.score;
if (scoreRef < 1e-6) {
return new DetectResult("bpmh", "0", "2000", "参考图异常", 0.0, scoreImg, 0.0);
}
double ratio = scoreRef / scoreImg;
System.out.println(scoreImg + ", " + scoreRef);
if (ratio < ratioThreshold) {
return new DetectResult("bpmh", "1", "2000", String.format("模糊 ratio=%.2f", ratio), 1.0, scoreImg, ratio);
} else {
return new DetectResult("bpmh", "0", "2000", String.format("正常 ratio=%.2f", ratio), 1.0, scoreImg, ratio);
}
}
}
// ===============================
// 测试入口
// ===============================
public static void main(String[] args) {
String img = "D:\\work\\images\\CAPTURE_258_20260320093827912_bcf0b101.jpg"; // 基准图提前给定
String ref = "D:\\work\\images\\CAPTURE_258_20260319160231459_89b5826f.jpg"; // 摄像头后面传入图像
// 默认 ratio_threshold=0.85
DetectResult result = doubleDetectBlur(img, ref, 0.85);
System.out.println(result.toString());
// String path="D:\\work\\imgs\\CAPTURE_258_20260319160154580_4d8abac8.jpg";
// DetectResult detectResult = detectBlur(path);
// System.out.println(detectResult.toString());
}
}

@ -0,0 +1,297 @@
package com.sz.admin.monitor.utils;
import org.bytedeco.opencv.opencv_core.*;
import org.bytedeco.opencv.opencv_imgproc.CLAHE;
import static org.bytedeco.opencv.global.opencv_core.*;
import static org.bytedeco.opencv.global.opencv_imgcodecs.imread;
import static org.bytedeco.opencv.global.opencv_imgproc.*;
public class BlurDetectorV4 {
// ===============================
// 数据返回类 (从 V3 移植)
// ===============================
public static class DetectResult {
public String type;
public String value;
public String code;
public String desc;
public double conf;
public double score;
public double ratio;
public DetectResult(String type, String value, String code, String desc, double conf, double score, double ratio) {
this.type = type;
this.value = value;
this.code = code;
this.desc = desc;
this.conf = conf;
this.score = score;
this.ratio = ratio;
}
@Override
public String toString() {
return String.format("Result{type='%s', value='%s', code='%s', desc='%s', conf=%.1f, score=%.2f, ratio=%.2f}",
type, value, code, desc, conf, score, ratio);
}
}
// ===============================
// 光照归一化 (保留 V4 的 3.0 参数)
// ===============================
public static Mat normalizeLighting(Mat gray) {
CLAHE clahe = createCLAHE(1.5, new Size(8, 8));
Mat dst = new Mat();
clahe.apply(gray, dst);
clahe.close();
return dst;
}
// ===============================
// Laplacian 清晰度
// ===============================
public static double laplacianScore(Mat gray) {
Mat lap = new Mat();
Laplacian(gray, lap, CV_64F);
Mat mean = new Mat();
Mat stddev = new Mat();
meanStdDev(lap, mean, stddev);
double std = stddev.createIndexer().getDouble(0);
lap.close();
mean.close();
stddev.close();
return std * std;
}
// ===============================
// Tenengrad 梯度
// ===============================
public static double tenengradScore(Mat gray) {
Mat gx = new Mat();
Mat gy = new Mat();
Sobel(gray, gx, CV_64F, 1, 0, 3, 1.0, 0.0, BORDER_DEFAULT);
Sobel(gray, gy, CV_64F, 0, 1, 3, 1.0, 0.0, BORDER_DEFAULT);
Mat gx2 = new Mat();
Mat gy2 = new Mat();
Mat g = new Mat();
multiply(gx, gx, gx2);
multiply(gy, gy, gy2);
add(gx2, gy2, g);
double score = mean(g).get(0);
gx.close(); gy.close();
gx2.close(); gy2.close(); g.close();
return score;
}
// ===============================
// Edge Density边缘密度
// ===============================
public static double edgeDensity(Mat gray) {
Mat edges = new Mat();
Canny(gray, edges, 80, 150);
int nonZero = countNonZero(edges);
long totalPixels = edges.total();
edges.close();
return (double) nonZero / totalPixels;
}
// ===============================
// FFT 高频能量 (保留 V4 优秀的内存管理)
// ===============================
private static double fftHighFrequency(Mat gray) {
try (Mat f32 = new Mat();
Mat zeros = Mat.zeros(gray.size(), CV_32F).asMat();
MatVector planes = new MatVector(2);
Mat complexI = new Mat();
Mat mag = new Mat();
Mat ones = Mat.ones(gray.size(), CV_32F).asMat();
Mat tmp = new Mat()) {
gray.convertTo(f32, CV_32F);
planes.put(0, f32);
planes.put(1, zeros);
merge(planes, complexI);
dft(complexI, complexI);
split(complexI, planes);
magnitude(planes.get(0), planes.get(1), mag);
add(mag, ones, mag);
log(mag, mag);
try (Mat croppedMag = new Mat(mag, new Rect(0, 0, mag.cols() & -2, mag.rows() & -2))) {
int cx = croppedMag.cols() / 2;
int cy = croppedMag.rows() / 2;
try (Mat q0 = new Mat(croppedMag, new Rect(0, 0, cx, cy));
Mat q1 = new Mat(croppedMag, new Rect(cx, 0, cx, cy));
Mat q2 = new Mat(croppedMag, new Rect(0, cy, cx, cy));
Mat q3 = new Mat(croppedMag, new Rect(cx, cy, cx, cy));
Mat mask = new Mat(croppedMag.size(), CV_32F, new Scalar(1.0))) {
q0.copyTo(tmp); q3.copyTo(q0); tmp.copyTo(q3);
q1.copyTo(tmp); q2.copyTo(q1); tmp.copyTo(q2);
int r = Math.min(cx, cy) / 4;
rectangle(mask,
new Point(cx - r, cy - r),
new Point(cx + r, cy + r),
new Scalar(0.0),
-1, 8, 0);
multiply(croppedMag, mask, croppedMag);
return mean(croppedMag).get(0);
}
}
}
}
// ===============================
// ROI中心区域
// ===============================
public static Mat extractRoi(Mat image) {
int h = image.rows();
int w = image.cols();
int x = w / 5;
int y = h / 5;
int roiW = (4 * w / 5) - x;
int roiH = (4 * h / 5) - y;
return new Mat(image, new Rect(x, y, roiW, roiH));
}
// ===============================
// 模糊检测主函数 (改为返回 DetectResult)
// ===============================
public static DetectResult detectBlur(Object imageObj, String detectTypeKey, double threshold) {
Mat image = null;
boolean needsRelease = false;
if (imageObj instanceof String) {
image = imread((String) imageObj);
needsRelease = true;
} else if (imageObj instanceof Mat) {
image = (Mat) imageObj;
}
if (image == null || image.empty()) {
throw new IllegalArgumentException("Image read error");
}
Mat roiImage = extractRoi(image);
Mat gray = new Mat();
cvtColor(roiImage, gray, COLOR_BGR2GRAY);
Mat normalizedGray = normalizeLighting(gray);
double lap = laplacianScore(normalizedGray);
double ten = tenengradScore(normalizedGray);
double edge = edgeDensity(normalizedGray);
double fft = fftHighFrequency(normalizedGray);
double lapN = Math.min(lap / 2000.0, 1.0);
double tenN = Math.min(ten / 10000.0, 1.0);
double edgeN = Math.min(edge * 10.0, 1.0);
double fftN = Math.min(fft / 10.0, 1.0);
double score = (0.35 * lapN + 0.30 * tenN + 0.20 * edgeN + 0.15 * fftN) * 100;
String descStr = String.format("score=%.2f", score);
DetectResult result;
if (score < threshold) {
result = new DetectResult(detectTypeKey, "1", "2000", "模糊 " + descStr, 1.0, score, 0.0);
} else {
result = new DetectResult(detectTypeKey, "0", "2000", "正常 " + descStr, 1.0, score, 0.0);
}
roiImage.close();
gray.close();
normalizedGray.close();
if (needsRelease) image.close();
return result;
}
public static DetectResult detectBlur(Object imageObj) {
return detectBlur(imageObj, "bpmh", 70.0);
}
// ===============================
// 双图检测 (改为返回 DetectResult)
// ===============================
public static DetectResult doubleDetectBlur(Object imgObj, Object refObj, double ratioThreshold) {
boolean useRef = true;
Mat refMat = null;
boolean refNeedsRelease = false;
if (refObj == null || (refObj instanceof String && ((String) refObj).isEmpty())) {
useRef = false;
} else if (refObj instanceof String) {
refMat = imread((String) refObj);
if (refMat == null || refMat.empty()) useRef = false;
else refNeedsRelease = true;
} else if (refObj instanceof Mat) {
refMat = (Mat) refObj;
if (refMat.empty()) useRef = false;
}
// 单图模式兜底
if (!useRef) {
return detectBlur(imgObj);
}
// 双图模式
DetectResult imgResult = detectBlur(imgObj);
DetectResult refResult = detectBlur(refMat);
double scoreImg = imgResult.score;
double scoreRef = refResult.score;
if (scoreRef < 1e-6) {
if (refNeedsRelease) refMat.close();
return new DetectResult("bpmh", "0", "2000", "参考图异常", 0.0, scoreImg, 0.0);
}
double ratio = scoreRef / scoreImg;
DetectResult finalResult;
if (ratio < ratioThreshold) {
finalResult = new DetectResult("bpmh", "1", "2000", String.format("模糊 ratio=%.2f", ratio), 1.0, scoreImg, ratio);
} else {
finalResult = new DetectResult("bpmh", "0", "2000", String.format("正常 ratio=%.2f", ratio), 1.0, scoreImg, ratio);
}
if (refNeedsRelease) refMat.close();
return finalResult;
}
public static DetectResult doubleDetectBlur(Object imgObj, Object refObj) {
return doubleDetectBlur(imgObj, refObj, 0.85);
}
// ===============================
// 测试
// ===============================
public static void main(String[] args) {
String path = "D:\\work\\imgs\\CAPTURE_266_20260317123416804_ac0f924c.jpg";
try {
DetectResult result = detectBlur(path);
System.out.println(result.toString());
} catch (Exception e) {
e.printStackTrace();
}
}
}

@ -0,0 +1,136 @@
package com.sz.admin.monitor.utils;
import org.im4java.core.IMOperation;
import org.im4java.core.ImageCommand;
import java.io.File;
import java.util.UUID;
public class BlurrinessComparator {
// 强制指定你的 IM7 安装路径
private static final String IM_PATH = "D:\\work\\imageMagic\\ImageMagick-7.1.2-Q16-HDRI";
public static void main(String[] args) {
String imagePath1 = "D:\\work\\images\\CAPTURE_258_20260320093827912_bcf0b101.jpg"; // 基准图 (清晰图标准)
String imagePath2 = "D:\\work\\images\\CAPTURE_258_20260319160020647_ffbc4f66.jpg"; // 当前图 (待检测图)
try {
//Result{type='blur_detection', value='1', code='BLURRY', desc='检测到图片模糊',
// conf=1.0, score=580.00, ratio=0.47}
DetectResult result = compareBlurriness(imagePath1, imagePath2);
// 打印最终返回的标准结果对象
System.out.println("检测完成,返回结果: " + result.toString());
} catch (Exception e) {
System.err.println("处理图片时发生错误: " + e.getMessage());
e.printStackTrace();
}
}
/**
*
*/
public static class DetectResult {
public String type; // 检测类型
public String value; // 结果值 (1: 模糊, 0: 正常)
public String code; // 结果代码
public String desc; // 描述信息
public double conf; // 置信度 (此处默认给 1.0)
public double score; // 得分 (此处记录目标图压缩后的大小)
public double ratio; // 比例 (目标图大小 / 基准图大小)
public DetectResult(String type, String value, String code, String desc, double conf, double score, double ratio) {
this.type = type;
this.value = value;
this.code = code;
this.desc = desc;
this.conf = conf;
this.score = score;
this.ratio = ratio;
}
@Override
public String toString() {
return String.format("Result{type='%s', value='%s', code='%s', desc='%s', conf=%.1f, score=%.2f, ratio=%.2f}",
type, value, code, desc, conf, score, ratio);
}
}
/**
* DetectResult
*/
public static DetectResult compareBlurriness(String path1, String path2) {
System.out.println("正在处理ImageMagick 缩放压缩 -> 计算文件体积...");
// 注意:尺寸设为 64x48 非常小,可能会导致压缩后体积差异微弱。如果效果不明显建议调大(如 800x600)。
long size1 = getProcessedImageSize(path1, 64, 48, 80.0);
long size2 = getProcessedImageSize(path2, 64, 48, 80.0);
System.out.println("图片1大小: " + size1 + " 字节, 图片2大小: " + size2 + " 字节");
// x为图片的大小 y = 90.733x - 35.474;
// 90.733*1.234-35.474 = 76.490522
// 90.733*0.58-35.474 = 17.15114
// 90.733*0.695-35.474 = 27.585435
// size1/size2
// size1>size2 则出现了模糊,因为特征点变小了,体积也变小了
// 计算体积比例 (防止除以 0 的异常)
double ratio = (size1 == 0) ? 1.0 : (double) size2 / size1;
String value;
String code;
String desc;
// 判断逻辑:当前图体积小于基准图,说明丢失了细节,判定为模糊
if (size2 < size1) {
value = "1"; // 模糊 Value 为 1
code = "BLURRY";
desc = "检测到图片模糊";
} else {
value = "0"; // 正常 Value 为 0
code = "NORMAL";
desc = "图片清晰度正常";
}
// 构造并返回标准实体类
// type: 设为 "blur_detection"
// conf: 置信度设为 1.0
// score: 存入 size2 (目标图片的压缩字节数) 作为参考得分
return new DetectResult("blur_detection", value, code, desc, 1.0, size2, ratio);
}
/**
* ImageMagick
*/
private static long getProcessedImageSize(String imagePath, int width, int height, double quality) {
// 生成一个临时文件路径,用于存放 ImageMagick 处理后的图片
String tempImagePath = System.getProperty("java.io.tmpdir") + File.separator + "im_temp_" + UUID.randomUUID() + ".jpg";
File tempFile = new File(tempImagePath);
try {
// 构建 ImageMagick 压缩指令
IMOperation op = new IMOperation();
op.addImage(imagePath);
op.strip(); // 剥离 EXIF 等多余元数据信息
op.resize(width, height); // 缩放为标准大小
op.quality(quality); // 设置 JPEG 压缩质量
op.addImage(tempImagePath); // 输出到临时文件
// 执行命令
ImageCommand cmd = new ImageCommand("magick");
cmd.setSearchPath(IM_PATH);
cmd.run(op);
// 获取临时文件的体积 (字节)
if (!tempFile.exists()) {
throw new RuntimeException("ImageMagick 未能成功生成临时文件!");
}
return tempFile.length();
} catch (Exception e) {
throw new RuntimeException("ImageMagick 处理流水线执行失败", e);
} finally {
// 务必清理临时文件
if (tempFile.exists()) {
tempFile.delete();
}
}
}
}

@ -28,7 +28,7 @@ import static org.bytedeco.opencv.global.opencv_video.calcOpticalFlowFarneback;
/**
* ClassName: RobustImageMatcherUtil
* Package: com.sz.admin.monitor.utils
* Description:
* Description:
*/
@Slf4j
public class RobustImageMatcherUtil {
@ -321,7 +321,6 @@ public class RobustImageMatcherUtil {
private static Map<String, Object> formatResult(MatchResult result, Mat img1, Mat img2) {
Map<String, Object> map = new LinkedHashMap<>();
map.put("type", "tx_yzwpy");
if (!result.success || result.confidence < 0.2) {
log.warn("图像配准失败或置信度过低");
map.put("value", 1);
@ -388,10 +387,16 @@ public class RobustImageMatcherUtil {
Mat[] preprocessed = preprocess(smallImg1, smallImg2);
Mat gray1 = preprocessed[0];
Mat gray2 = preprocessed[1];
Map<String, Object> map = new LinkedHashMap<>();
map.put("type", "tx_yzwpy");
if (!isSameScene(gray1, gray2)) {
log.warn("图像差异过大,非同一场景: path1={}, path2={}", path1, path2);
return null;
map.put("value", 1);
map.put("code", "4000");
OffsetVO offsetVO = new OffsetVO();
offsetVO.setDescription("图像存在偏移");
map.put("description", JsonUtils.toJsonString(offsetVO));
return map;
}
MatchResult flowResult = calcOpticalFlow(gray1, gray2);
@ -416,8 +421,8 @@ public class RobustImageMatcherUtil {
// String img1Path = "D:\\work\\images\\CAPTURE_118_20260306140433490_7c323ce1.jpg";
// String img2Path = "D:\\work\\images\\CAPTURE_118_20260306140555121_0a31347e.jpg";
// 出现移位的图片 value 1
String img1Path="D:\\work\\images\\CAPTURE_118_20260306140328178_7f050439.jpg";
String img2Path="D:\\work\\images\\CAPTURE_118_20260306140433490_7c323ce1.jpg";
String img1Path = "D:\\work\\temp\\history_20260324_180000.jpg";
String img2Path = "D:\\work\\temp\\history_20260324_190000.jpg";
Map<String, Object> map = RobustImageMatcherUtil.calculateOffset(img1Path, img2Path);
System.out.println(map);
}

@ -2,24 +2,41 @@ package com.sz.admin.monitor.utils;
import java.io.File;
/**
* ClassName: UrlConvert
* Package: com.sz.admin.monitor.utils
* Description:
*/
public class UrlConvert {
private static final String RESOURCE_PREFIX = "/save/";
// 定义我们配置的两个静态资源根目录 (注意统一用正斜杠 / )
private static final String BASE_DIR_IMAGES = "D:/work/images/";
private static final String BASE_DIR_TEMP = "D:/work/temp/";
/**
*
* @param localPath D:\work\sz-admin\images\test.jpg
* @return /save/test.jpg
* @param localPath : D:\work\temp\task_123\test.jpg
* @return /save/task_123/test.jpg
*/
public static String convertToUrl(String localPath) {
if (localPath == null || localPath.isEmpty()) {
return null;
}
String fileName = new File(localPath).getName();
// 2. 拼接映射前缀
return RESOURCE_PREFIX + fileName;
// 1. 统一路径分隔符:将 Windows 的反斜杠 \ 全部替换为标准的正斜杠 /
String normalizedPath = localPath.replace("\\", "/");
String relativePath = "";
// 2. 剥离根目录,保留后面的子文件夹和文件名
if (normalizedPath.startsWith(BASE_DIR_IMAGES)) {
// 截取掉 D:/work/images/ 这一部分
relativePath = normalizedPath.substring(BASE_DIR_IMAGES.length());
} else if (normalizedPath.startsWith(BASE_DIR_TEMP)) {
// 截取掉 D:/work/temp/ 这一部分,保留 task_123/test.jpg
relativePath = normalizedPath.substring(BASE_DIR_TEMP.length());
} else {
// 兜底方案:如果传进来的路径不在这两个目录里,退回到只取文件名
relativePath = new File(localPath).getName();
}
// 3. 拼接映射前缀
return RESOURCE_PREFIX + relativePath;
}
}

@ -98,6 +98,7 @@ public class ZLMediaKitUtils {
public JSONObject sendPost(String api, Map<String, Object> param, RequestCallback callback) {
OkHttpClient okHttpClient = getClient();
String url = String.format(MediaConstant.HTTP_MEDIA_URL, ip, port, api);
log.info("url:{}", url);
JSONObject responseJSON = new JSONObject();
responseJSON.put("code", CommonResponseEnum.MEDIA_HTTP_FAIL.getCode());
responseJSON.put("msg", CommonResponseEnum.MEDIA_HTTP_FAIL.getMessage());

@ -75,3 +75,9 @@ management:
endpoint:
health:
show-details: "never"
file:
object:
storage:
targetDir: D:/work/images

@ -1,52 +1,52 @@
--liquibase formatted sql
--changeset sz:20250425_0924
-- 以下为演示环境脚本,-- 仅供演示使用,实际业务请删除
CREATE TABLE IF NOT EXISTS `teacher_statistics` (
`id` bigint NOT NULL AUTO_INCREMENT COMMENT 'ID',
`year` varchar(4) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '统计年限',
`month` varchar(2) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '统计月份',
`during_time` varchar(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '统计年月',
`teacher_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '教师id',
`teacher_common_type` int NOT NULL COMMENT '讲师区分类型',
`total_teaching` int NULL DEFAULT NULL COMMENT '授课总数',
`total_class_count` int NULL DEFAULT NULL COMMENT '服务班次数',
`total_hours` decimal(10, 2) NULL DEFAULT NULL COMMENT '课时总数',
`check_status` int NOT NULL DEFAULT 0 COMMENT '核对状态',
`check_time` datetime NULL DEFAULT NULL COMMENT '核对时间',
`create_time` datetime NULL DEFAULT NULL COMMENT '生成时间',
`update_time` datetime NULL DEFAULT NULL COMMENT '更新时间',
`last_sync_time` datetime NULL DEFAULT NULL COMMENT '最近一次同步时间',
`remark` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '备注',
`create_id` bigint NULL DEFAULT NULL COMMENT '创建人ID',
`update_id` bigint NULL DEFAULT NULL COMMENT '更新人ID',
`dept_scope` json NULL COMMENT '部门范围',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 28 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '教师统计总览表' ROW_FORMAT = DYNAMIC;
INSERT IGNORE INTO `teacher_statistics` (`id`, `year`, `month`, `during_time`, `teacher_id`, `teacher_common_type`, `total_teaching`, `total_class_count`, `total_hours`, `check_status`, `check_time`, `create_time`, `update_time`, `last_sync_time`, `remark`, `create_id`, `update_id`, `dept_scope`) VALUES (22, '2018', '12', '03', '1503', 1000001, 12, 22, 15.00, 1000001, '2024-07-08 10:39:56', '2024-07-08 10:40:16', NULL, '2024-07-08 10:39:57', 'test1 创建记录', 3, NULL, '[4]');
INSERT IGNORE INTO `teacher_statistics` (`id`, `year`, `month`, `during_time`, `teacher_id`, `teacher_common_type`, `total_teaching`, `total_class_count`, `total_hours`, `check_status`, `check_time`, `create_time`, `update_time`, `last_sync_time`, `remark`, `create_id`, `update_id`, `dept_scope`) VALUES (23, '2019', '12', '03', '111', 1000001, 1, 2, 3.00, 1000001, '2024-07-08 10:41:09', '2024-07-08 10:41:18', NULL, '2024-07-08 10:41:11', 'test1 创建记录', 3, NULL, '[4]');
INSERT IGNORE INTO `teacher_statistics` (`id`, `year`, `month`, `during_time`, `teacher_id`, `teacher_common_type`, `total_teaching`, `total_class_count`, `total_hours`, `check_status`, `check_time`, `create_time`, `update_time`, `last_sync_time`, `remark`, `create_id`, `update_id`, `dept_scope`) VALUES (24, '2020', '12', '2020-12', '023', 1000001, 1, 1, 1.00, 1000001, '2024-07-08 13:06:55', '2024-07-08 13:07:07', NULL, '2024-07-08 13:06:57', 'test1 创建记录', 3, NULL, '[4]');
INSERT IGNORE INTO `teacher_statistics` (`id`, `year`, `month`, `during_time`, `teacher_id`, `teacher_common_type`, `total_teaching`, `total_class_count`, `total_hours`, `check_status`, `check_time`, `create_time`, `update_time`, `last_sync_time`, `remark`, `create_id`, `update_id`, `dept_scope`) VALUES (25, '2021', '12', '2021-12', '123', 1000001, 1, 1, 1.00, 1000001, '2024-07-08 13:13:56', '2024-07-08 13:13:59', NULL, NULL, 'test2 创建记录', 4, NULL, '[15]');
INSERT IGNORE INTO `teacher_statistics` (`id`, `year`, `month`, `during_time`, `teacher_id`, `teacher_common_type`, `total_teaching`, `total_class_count`, `total_hours`, `check_status`, `check_time`, `create_time`, `update_time`, `last_sync_time`, `remark`, `create_id`, `update_id`, `dept_scope`) VALUES (26, '2022', '12', '2022-12', '13123', 1000001, 1, 1, 1.00, 1000001, '2024-07-08 13:15:36', '2024-07-08 13:15:37', '2024-07-08 13:15:46', NULL, 'test3 创建记录', 5, 5, '[15]');
INSERT IGNORE INTO `teacher_statistics` (`id`, `year`, `month`, `during_time`, `teacher_id`, `teacher_common_type`, `total_teaching`, `total_class_count`, `total_hours`, `check_status`, `check_time`, `create_time`, `update_time`, `last_sync_time`, `remark`, `create_id`, `update_id`, `dept_scope`) VALUES (27, '2099', '12', '12', '123123', 1000001, 1, 1, 1.00, 1000001, NULL, '2024-07-08 13:20:29', NULL, NULL, '管理员创建', 1, NULL, '[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]');
INSERT IGNORE INTO `generator_table` (`table_id`, `table_name`, `table_comment`, `class_name`, `camel_class_name`, `tpl_category`, `package_name`, `module_name`, `business_name`, `function_name`, `function_author`, `type`, `options`, `parent_menu_id`, `path`, `path_api`, `path_web`, `menu_init_type`, `btn_permission_type`, `has_import`, `has_export`, `generate_type`, `create_id`, `update_id`, `create_time`, `update_time`, `is_autofill`) VALUES (1, 'teacher_statistics', '教师统计总览表', 'TeacherStatistics', 'teacherStatistics', 'crud', 'com.sz.admin', 'teacherstatistics', 'teacherStatistics', '教师统计总览表', 'sz-admin', '0', NULL, '0', '/', 'E:\\dev\\Code\\Github\\sz-boot-parent\\sz-service\\sz-service-admin', '', '1', '1', '1', '1', 'all', 1, NULL, '2024-05-10 21:45:32', NULL, '1');
INSERT IGNORE INTO `generator_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `search_type`, `ts_type`, `java_type_package`, `java_field`, `up_camel_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `is_import`, `is_export`, `is_autofill`, `is_unique_valid`, `autofill_type`, `query_type`, `html_type`, `dict_type`, `is_logic_del`, `options`, `sort`, `create_id`, `update_id`, `create_time`, `update_time`, `dict_show_way`) VALUES (1, 1, 'id', 'id', 'int', 'Long', 'input', 'number', NULL, 'id', 'Id', '1', '1', '0', '0', '1', '1', '0', '0', '0', '0', '0', NULL, 'EQ', 'input-number', '', '0', NULL, 1, 1, NULL, '2024-05-10 21:45:32', NULL, '0');
INSERT IGNORE INTO `generator_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `search_type`, `ts_type`, `java_type_package`, `java_field`, `up_camel_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `is_import`, `is_export`, `is_autofill`, `is_unique_valid`, `autofill_type`, `query_type`, `html_type`, `dict_type`, `is_logic_del`, `options`, `sort`, `create_id`, `update_id`, `create_time`, `update_time`, `dict_show_way`) VALUES (2, 1, 'year', '统计年限', 'varchar(4)', 'String', 'input', 'string', NULL, 'year', 'Year', '0', '0', '1', '1', '1', '1', '1', '1', '1', '0', '0', NULL, 'EQ', 'input', '', '0', NULL, 2, 1, NULL, '2024-05-10 21:45:32', NULL, '0');
INSERT IGNORE INTO `generator_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `search_type`, `ts_type`, `java_type_package`, `java_field`, `up_camel_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `is_import`, `is_export`, `is_autofill`, `is_unique_valid`, `autofill_type`, `query_type`, `html_type`, `dict_type`, `is_logic_del`, `options`, `sort`, `create_id`, `update_id`, `create_time`, `update_time`, `dict_show_way`) VALUES (3, 1, 'month', '统计月份', 'varchar(2)', 'String', 'input', 'string', NULL, 'month', 'Month', '0', '0', '1', '1', '1', '1', '1', '1', '1', '0', '0', NULL, 'EQ', 'input', '', '0', NULL, 3, 1, NULL, '2024-05-10 21:45:32', NULL, '0');
INSERT IGNORE INTO `generator_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `search_type`, `ts_type`, `java_type_package`, `java_field`, `up_camel_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `is_import`, `is_export`, `is_autofill`, `is_unique_valid`, `autofill_type`, `query_type`, `html_type`, `dict_type`, `is_logic_del`, `options`, `sort`, `create_id`, `update_id`, `create_time`, `update_time`, `dict_show_way`) VALUES (4, 1, 'during_time', '统计年月', 'varchar(10)', 'String', 'date-picker', 'string', NULL, 'duringTime', 'DuringTime', '0', '0', '0', '1', '1', '1', '1', '1', '1', '0', '0', NULL, 'EQ', 'input', '', '0', NULL, 4, 1, NULL, '2024-05-10 21:45:32', NULL, '0');
INSERT IGNORE INTO `generator_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `search_type`, `ts_type`, `java_type_package`, `java_field`, `up_camel_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `is_import`, `is_export`, `is_autofill`, `is_unique_valid`, `autofill_type`, `query_type`, `html_type`, `dict_type`, `is_logic_del`, `options`, `sort`, `create_id`, `update_id`, `create_time`, `update_time`, `dict_show_way`) VALUES (5, 1, 'teacher_id', '教师id', 'varchar(32)', 'String', 'input', 'string', NULL, 'teacherId', 'TeacherId', '0', '0', '1', '1', '1', '1', '1', '1', '1', '0', '0', NULL, 'EQ', 'input', '', '0', NULL, 5, 1, NULL, '2024-05-10 21:45:32', NULL, '0');
INSERT IGNORE INTO `generator_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `search_type`, `ts_type`, `java_type_package`, `java_field`, `up_camel_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `is_import`, `is_export`, `is_autofill`, `is_unique_valid`, `autofill_type`, `query_type`, `html_type`, `dict_type`, `is_logic_del`, `options`, `sort`, `create_id`, `update_id`, `create_time`, `update_time`, `dict_show_way`) VALUES (6, 1, 'teacher_common_type', '讲师区分类型', 'int', 'Integer', 'select', 'number', NULL, 'teacherCommonType', 'TeacherCommonType', '0', '0', '1', '1', '1', '1', '1', '1', '1', '0', '0', NULL, 'EQ', 'select', '', '0', NULL, 6, 1, NULL, '2024-05-10 21:45:32', NULL, '0');
INSERT IGNORE INTO `generator_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `search_type`, `ts_type`, `java_type_package`, `java_field`, `up_camel_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `is_import`, `is_export`, `is_autofill`, `is_unique_valid`, `autofill_type`, `query_type`, `html_type`, `dict_type`, `is_logic_del`, `options`, `sort`, `create_id`, `update_id`, `create_time`, `update_time`, `dict_show_way`) VALUES (7, 1, 'total_teaching', '授课总数', 'int', 'Integer', 'input', 'number', NULL, 'totalTeaching', 'TotalTeaching', '0', '0', '0', '1', '1', '1', '1', '1', '1', '0', '0', NULL, 'EQ', 'input-number', '', '0', NULL, 7, 1, NULL, '2024-05-10 21:45:32', NULL, '0');
INSERT IGNORE INTO `generator_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `search_type`, `ts_type`, `java_type_package`, `java_field`, `up_camel_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `is_import`, `is_export`, `is_autofill`, `is_unique_valid`, `autofill_type`, `query_type`, `html_type`, `dict_type`, `is_logic_del`, `options`, `sort`, `create_id`, `update_id`, `create_time`, `update_time`, `dict_show_way`) VALUES (8, 1, 'total_class_count', '服务班次数', 'int', 'Integer', 'input', 'number', NULL, 'totalClassCount', 'TotalClassCount', '0', '0', '0', '1', '1', '1', '1', '1', '1', '0', '0', NULL, 'EQ', 'input-number', '', '0', NULL, 8, 1, NULL, '2024-05-10 21:45:32', NULL, '0');
INSERT IGNORE INTO `generator_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `search_type`, `ts_type`, `java_type_package`, `java_field`, `up_camel_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `is_import`, `is_export`, `is_autofill`, `is_unique_valid`, `autofill_type`, `query_type`, `html_type`, `dict_type`, `is_logic_del`, `options`, `sort`, `create_id`, `update_id`, `create_time`, `update_time`, `dict_show_way`) VALUES (9, 1, 'total_hours', '课时总数', 'decimal(10,2)', 'BigDecimal', 'input', 'number', 'java.math.BigDecimal', 'totalHours', 'TotalHours', '0', '0', '0', '1', '1', '1', '1', '1', '1', '0', '0', NULL, 'EQ', 'input-number', '', '0', NULL, 9, 1, NULL, '2024-05-10 21:45:32', NULL, '0');
INSERT IGNORE INTO `generator_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `search_type`, `ts_type`, `java_type_package`, `java_field`, `up_camel_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `is_import`, `is_export`, `is_autofill`, `is_unique_valid`, `autofill_type`, `query_type`, `html_type`, `dict_type`, `is_logic_del`, `options`, `sort`, `create_id`, `update_id`, `create_time`, `update_time`, `dict_show_way`) VALUES (10, 1, 'check_status', '核对状态', 'int', 'Integer', 'select', 'number', NULL, 'checkStatus', 'CheckStatus', '0', '0', '1', '1', '1', '1', '1', '1', '1', '0', '0', NULL, 'EQ', 'radio', '', '0', NULL, 10, 1, NULL, '2024-05-10 21:45:32', NULL, '0');
INSERT IGNORE INTO `generator_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `search_type`, `ts_type`, `java_type_package`, `java_field`, `up_camel_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `is_import`, `is_export`, `is_autofill`, `is_unique_valid`, `autofill_type`, `query_type`, `html_type`, `dict_type`, `is_logic_del`, `options`, `sort`, `create_id`, `update_id`, `create_time`, `update_time`, `dict_show_way`) VALUES (11, 1, 'check_time', '核对时间', 'datetime', 'LocalDateTime', 'date-picker', 'string', 'java.time.LocalDateTime', 'checkTime', 'CheckTime', '0', '0', '0', '1', '1', '1', '1', '1', '1', '0', '0', NULL, 'EQ', 'datetime', '', '0', NULL, 11, 1, NULL, '2024-05-10 21:45:32', NULL, '0');
INSERT IGNORE INTO `generator_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `search_type`, `ts_type`, `java_type_package`, `java_field`, `up_camel_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `is_import`, `is_export`, `is_autofill`, `is_unique_valid`, `autofill_type`, `query_type`, `html_type`, `dict_type`, `is_logic_del`, `options`, `sort`, `create_id`, `update_id`, `create_time`, `update_time`, `dict_show_way`) VALUES (12, 1, 'create_time', '生成时间', 'datetime', 'LocalDateTime', 'date-picker', 'string', 'java.time.LocalDateTime', 'createTime', 'CreateTime', '0', '0', '0', '0', '0', '0', '0', '0', '0', '1', '0', 'FieldFill.INSERT', 'EQ', 'datetime', '', '0', NULL, 12, 1, NULL, '2024-05-10 21:45:32', NULL, '0');
INSERT IGNORE INTO `generator_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `search_type`, `ts_type`, `java_type_package`, `java_field`, `up_camel_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `is_import`, `is_export`, `is_autofill`, `is_unique_valid`, `autofill_type`, `query_type`, `html_type`, `dict_type`, `is_logic_del`, `options`, `sort`, `create_id`, `update_id`, `create_time`, `update_time`, `dict_show_way`) VALUES (13, 1, 'update_time', '更新时间', 'datetime', 'LocalDateTime', 'date-picker', 'string', 'java.time.LocalDateTime', 'updateTime', 'UpdateTime', '0', '0', '0', '0', '0', '0', '0', '0', '0', '1', '0', 'FieldFill.UPDATE', 'EQ', 'datetime', '', '0', NULL, 13, 1, NULL, '2024-05-10 21:45:32', NULL, '0');
INSERT IGNORE INTO `generator_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `search_type`, `ts_type`, `java_type_package`, `java_field`, `up_camel_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `is_import`, `is_export`, `is_autofill`, `is_unique_valid`, `autofill_type`, `query_type`, `html_type`, `dict_type`, `is_logic_del`, `options`, `sort`, `create_id`, `update_id`, `create_time`, `update_time`, `dict_show_way`) VALUES (14, 1, 'last_sync_time', '最近一次同步时间', 'datetime', 'LocalDateTime', 'date-picker', 'string', 'java.time.LocalDateTime', 'lastSyncTime', 'LastSyncTime', '0', '0', '0', '1', '1', '1', '1', '1', '1', '0', '0', NULL, 'EQ', 'datetime', '', '0', NULL, 14, 1, NULL, '2024-05-10 21:45:32', NULL, '0');
INSERT IGNORE INTO `generator_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `search_type`, `ts_type`, `java_type_package`, `java_field`, `up_camel_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `is_import`, `is_export`, `is_autofill`, `is_unique_valid`, `autofill_type`, `query_type`, `html_type`, `dict_type`, `is_logic_del`, `options`, `sort`, `create_id`, `update_id`, `create_time`, `update_time`, `dict_show_way`) VALUES (15, 1, 'remark', '备注', 'varchar(255)', 'String', 'input', 'string', NULL, 'remark', 'Remark', '0', '0', '0', '1', '1', '1', '0', '1', '1', '0', '0', NULL, 'EQ', 'input', '', '0', NULL, 15, 1, NULL, '2024-05-10 21:45:32', NULL, '0');
-- --liquibase formatted sql
--
-- --changeset 升职哦sz:20250425_0924
-- -- 以下为演示环境脚本,-- 仅供演示使用,实际业务请删除
-- CREATE TABLE IF NOT EXISTS `teacher_statistics` (
-- `id` bigint NOT NULL AUTO_INCREMENT COMMENT 'ID',
-- `year` varchar(4) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '统计年限',
-- `month` varchar(2) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '统计月份',
-- `during_time` varchar(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '统计年月',
-- `teacher_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '教师id',
-- `teacher_common_type` int NOT NULL COMMENT '讲师区分类型',
-- `total_teaching` int NULL DEFAULT NULL COMMENT '授课总数',
-- `total_class_count` int NULL DEFAULT NULL COMMENT '服务班次数',
-- `total_hours` decimal(10, 2) NULL DEFAULT NULL COMMENT '课时总数',
-- `check_status` int NOT NULL DEFAULT 0 COMMENT '核对状态',
-- `check_time` datetime NULL DEFAULT NULL COMMENT '核对时间',
-- `create_time` datetime NULL DEFAULT NULL COMMENT '生成时间',
-- `update_time` datetime NULL DEFAULT NULL COMMENT '更新时间',
-- `last_sync_time` datetime NULL DEFAULT NULL COMMENT '最近一次同步时间',
-- `remark` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '备注',
-- `create_id` bigint NULL DEFAULT NULL COMMENT '创建人ID',
-- `update_id` bigint NULL DEFAULT NULL COMMENT '更新人ID',
-- `dept_scope` json NULL COMMENT '部门范围',
-- PRIMARY KEY (`id`) USING BTREE
-- ) ENGINE = InnoDB AUTO_INCREMENT = 28 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '教师统计总览表' ROW_FORMAT = DYNAMIC;
--
-- INSERT IGNORE INTO `teacher_statistics` (`id`, `year`, `month`, `during_time`, `teacher_id`, `teacher_common_type`, `total_teaching`, `total_class_count`, `total_hours`, `check_status`, `check_time`, `create_time`, `update_time`, `last_sync_time`, `remark`, `create_id`, `update_id`, `dept_scope`) VALUES (22, '2018', '12', '03', '1503', 1000001, 12, 22, 15.00, 1000001, '2024-07-08 10:39:56', '2024-07-08 10:40:16', NULL, '2024-07-08 10:39:57', 'test1 创建记录', 3, NULL, '[4]');
-- INSERT IGNORE INTO `teacher_statistics` (`id`, `year`, `month`, `during_time`, `teacher_id`, `teacher_common_type`, `total_teaching`, `total_class_count`, `total_hours`, `check_status`, `check_time`, `create_time`, `update_time`, `last_sync_time`, `remark`, `create_id`, `update_id`, `dept_scope`) VALUES (23, '2019', '12', '03', '111', 1000001, 1, 2, 3.00, 1000001, '2024-07-08 10:41:09', '2024-07-08 10:41:18', NULL, '2024-07-08 10:41:11', 'test1 创建记录', 3, NULL, '[4]');
-- INSERT IGNORE INTO `teacher_statistics` (`id`, `year`, `month`, `during_time`, `teacher_id`, `teacher_common_type`, `total_teaching`, `total_class_count`, `total_hours`, `check_status`, `check_time`, `create_time`, `update_time`, `last_sync_time`, `remark`, `create_id`, `update_id`, `dept_scope`) VALUES (24, '2020', '12', '2020-12', '023', 1000001, 1, 1, 1.00, 1000001, '2024-07-08 13:06:55', '2024-07-08 13:07:07', NULL, '2024-07-08 13:06:57', 'test1 创建记录', 3, NULL, '[4]');
-- INSERT IGNORE INTO `teacher_statistics` (`id`, `year`, `month`, `during_time`, `teacher_id`, `teacher_common_type`, `total_teaching`, `total_class_count`, `total_hours`, `check_status`, `check_time`, `create_time`, `update_time`, `last_sync_time`, `remark`, `create_id`, `update_id`, `dept_scope`) VALUES (25, '2021', '12', '2021-12', '123', 1000001, 1, 1, 1.00, 1000001, '2024-07-08 13:13:56', '2024-07-08 13:13:59', NULL, NULL, 'test2 创建记录', 4, NULL, '[15]');
-- INSERT IGNORE INTO `teacher_statistics` (`id`, `year`, `month`, `during_time`, `teacher_id`, `teacher_common_type`, `total_teaching`, `total_class_count`, `total_hours`, `check_status`, `check_time`, `create_time`, `update_time`, `last_sync_time`, `remark`, `create_id`, `update_id`, `dept_scope`) VALUES (26, '2022', '12', '2022-12', '13123', 1000001, 1, 1, 1.00, 1000001, '2024-07-08 13:15:36', '2024-07-08 13:15:37', '2024-07-08 13:15:46', NULL, 'test3 创建记录', 5, 5, '[15]');
-- INSERT IGNORE INTO `teacher_statistics` (`id`, `year`, `month`, `during_time`, `teacher_id`, `teacher_common_type`, `total_teaching`, `total_class_count`, `total_hours`, `check_status`, `check_time`, `create_time`, `update_time`, `last_sync_time`, `remark`, `create_id`, `update_id`, `dept_scope`) VALUES (27, '2099', '12', '12', '123123', 1000001, 1, 1, 1.00, 1000001, NULL, '2024-07-08 13:20:29', NULL, NULL, '管理员创建', 1, NULL, '[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]');
--
-- INSERT IGNORE INTO `generator_table` (`table_id`, `table_name`, `table_comment`, `class_name`, `camel_class_name`, `tpl_category`, `package_name`, `module_name`, `business_name`, `function_name`, `function_author`, `type`, `options`, `parent_menu_id`, `path`, `path_api`, `path_web`, `menu_init_type`, `btn_permission_type`, `has_import`, `has_export`, `generate_type`, `create_id`, `update_id`, `create_time`, `update_time`, `is_autofill`) VALUES (1, 'teacher_statistics', '教师统计总览表', 'TeacherStatistics', 'teacherStatistics', 'crud', 'com.sz.admin', 'teacherstatistics', 'teacherStatistics', '教师统计总览表', 'sz-admin', '0', NULL, '0', '/', 'E:\\dev\\Code\\Github\\sz-boot-parent\\sz-service\\sz-service-admin', '', '1', '1', '1', '1', 'all', 1, NULL, '2024-05-10 21:45:32', NULL, '1');
--
-- INSERT IGNORE INTO `generator_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `search_type`, `ts_type`, `java_type_package`, `java_field`, `up_camel_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `is_import`, `is_export`, `is_autofill`, `is_unique_valid`, `autofill_type`, `query_type`, `html_type`, `dict_type`, `is_logic_del`, `options`, `sort`, `create_id`, `update_id`, `create_time`, `update_time`, `dict_show_way`) VALUES (1, 1, 'id', 'id', 'int', 'Long', 'input', 'number', NULL, 'id', 'Id', '1', '1', '0', '0', '1', '1', '0', '0', '0', '0', '0', NULL, 'EQ', 'input-number', '', '0', NULL, 1, 1, NULL, '2024-05-10 21:45:32', NULL, '0');
-- INSERT IGNORE INTO `generator_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `search_type`, `ts_type`, `java_type_package`, `java_field`, `up_camel_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `is_import`, `is_export`, `is_autofill`, `is_unique_valid`, `autofill_type`, `query_type`, `html_type`, `dict_type`, `is_logic_del`, `options`, `sort`, `create_id`, `update_id`, `create_time`, `update_time`, `dict_show_way`) VALUES (2, 1, 'year', '统计年限', 'varchar(4)', 'String', 'input', 'string', NULL, 'year', 'Year', '0', '0', '1', '1', '1', '1', '1', '1', '1', '0', '0', NULL, 'EQ', 'input', '', '0', NULL, 2, 1, NULL, '2024-05-10 21:45:32', NULL, '0');
-- INSERT IGNORE INTO `generator_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `search_type`, `ts_type`, `java_type_package`, `java_field`, `up_camel_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `is_import`, `is_export`, `is_autofill`, `is_unique_valid`, `autofill_type`, `query_type`, `html_type`, `dict_type`, `is_logic_del`, `options`, `sort`, `create_id`, `update_id`, `create_time`, `update_time`, `dict_show_way`) VALUES (3, 1, 'month', '统计月份', 'varchar(2)', 'String', 'input', 'string', NULL, 'month', 'Month', '0', '0', '1', '1', '1', '1', '1', '1', '1', '0', '0', NULL, 'EQ', 'input', '', '0', NULL, 3, 1, NULL, '2024-05-10 21:45:32', NULL, '0');
-- INSERT IGNORE INTO `generator_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `search_type`, `ts_type`, `java_type_package`, `java_field`, `up_camel_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `is_import`, `is_export`, `is_autofill`, `is_unique_valid`, `autofill_type`, `query_type`, `html_type`, `dict_type`, `is_logic_del`, `options`, `sort`, `create_id`, `update_id`, `create_time`, `update_time`, `dict_show_way`) VALUES (4, 1, 'during_time', '统计年月', 'varchar(10)', 'String', 'date-picker', 'string', NULL, 'duringTime', 'DuringTime', '0', '0', '0', '1', '1', '1', '1', '1', '1', '0', '0', NULL, 'EQ', 'input', '', '0', NULL, 4, 1, NULL, '2024-05-10 21:45:32', NULL, '0');
-- INSERT IGNORE INTO `generator_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `search_type`, `ts_type`, `java_type_package`, `java_field`, `up_camel_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `is_import`, `is_export`, `is_autofill`, `is_unique_valid`, `autofill_type`, `query_type`, `html_type`, `dict_type`, `is_logic_del`, `options`, `sort`, `create_id`, `update_id`, `create_time`, `update_time`, `dict_show_way`) VALUES (5, 1, 'teacher_id', '教师id', 'varchar(32)', 'String', 'input', 'string', NULL, 'teacherId', 'TeacherId', '0', '0', '1', '1', '1', '1', '1', '1', '1', '0', '0', NULL, 'EQ', 'input', '', '0', NULL, 5, 1, NULL, '2024-05-10 21:45:32', NULL, '0');
-- INSERT IGNORE INTO `generator_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `search_type`, `ts_type`, `java_type_package`, `java_field`, `up_camel_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `is_import`, `is_export`, `is_autofill`, `is_unique_valid`, `autofill_type`, `query_type`, `html_type`, `dict_type`, `is_logic_del`, `options`, `sort`, `create_id`, `update_id`, `create_time`, `update_time`, `dict_show_way`) VALUES (6, 1, 'teacher_common_type', '讲师区分类型', 'int', 'Integer', 'select', 'number', NULL, 'teacherCommonType', 'TeacherCommonType', '0', '0', '1', '1', '1', '1', '1', '1', '1', '0', '0', NULL, 'EQ', 'select', '', '0', NULL, 6, 1, NULL, '2024-05-10 21:45:32', NULL, '0');
-- INSERT IGNORE INTO `generator_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `search_type`, `ts_type`, `java_type_package`, `java_field`, `up_camel_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `is_import`, `is_export`, `is_autofill`, `is_unique_valid`, `autofill_type`, `query_type`, `html_type`, `dict_type`, `is_logic_del`, `options`, `sort`, `create_id`, `update_id`, `create_time`, `update_time`, `dict_show_way`) VALUES (7, 1, 'total_teaching', '授课总数', 'int', 'Integer', 'input', 'number', NULL, 'totalTeaching', 'TotalTeaching', '0', '0', '0', '1', '1', '1', '1', '1', '1', '0', '0', NULL, 'EQ', 'input-number', '', '0', NULL, 7, 1, NULL, '2024-05-10 21:45:32', NULL, '0');
-- INSERT IGNORE INTO `generator_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `search_type`, `ts_type`, `java_type_package`, `java_field`, `up_camel_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `is_import`, `is_export`, `is_autofill`, `is_unique_valid`, `autofill_type`, `query_type`, `html_type`, `dict_type`, `is_logic_del`, `options`, `sort`, `create_id`, `update_id`, `create_time`, `update_time`, `dict_show_way`) VALUES (8, 1, 'total_class_count', '服务班次数', 'int', 'Integer', 'input', 'number', NULL, 'totalClassCount', 'TotalClassCount', '0', '0', '0', '1', '1', '1', '1', '1', '1', '0', '0', NULL, 'EQ', 'input-number', '', '0', NULL, 8, 1, NULL, '2024-05-10 21:45:32', NULL, '0');
-- INSERT IGNORE INTO `generator_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `search_type`, `ts_type`, `java_type_package`, `java_field`, `up_camel_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `is_import`, `is_export`, `is_autofill`, `is_unique_valid`, `autofill_type`, `query_type`, `html_type`, `dict_type`, `is_logic_del`, `options`, `sort`, `create_id`, `update_id`, `create_time`, `update_time`, `dict_show_way`) VALUES (9, 1, 'total_hours', '课时总数', 'decimal(10,2)', 'BigDecimal', 'input', 'number', 'java.math.BigDecimal', 'totalHours', 'TotalHours', '0', '0', '0', '1', '1', '1', '1', '1', '1', '0', '0', NULL, 'EQ', 'input-number', '', '0', NULL, 9, 1, NULL, '2024-05-10 21:45:32', NULL, '0');
-- INSERT IGNORE INTO `generator_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `search_type`, `ts_type`, `java_type_package`, `java_field`, `up_camel_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `is_import`, `is_export`, `is_autofill`, `is_unique_valid`, `autofill_type`, `query_type`, `html_type`, `dict_type`, `is_logic_del`, `options`, `sort`, `create_id`, `update_id`, `create_time`, `update_time`, `dict_show_way`) VALUES (10, 1, 'check_status', '核对状态', 'int', 'Integer', 'select', 'number', NULL, 'checkStatus', 'CheckStatus', '0', '0', '1', '1', '1', '1', '1', '1', '1', '0', '0', NULL, 'EQ', 'radio', '', '0', NULL, 10, 1, NULL, '2024-05-10 21:45:32', NULL, '0');
-- INSERT IGNORE INTO `generator_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `search_type`, `ts_type`, `java_type_package`, `java_field`, `up_camel_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `is_import`, `is_export`, `is_autofill`, `is_unique_valid`, `autofill_type`, `query_type`, `html_type`, `dict_type`, `is_logic_del`, `options`, `sort`, `create_id`, `update_id`, `create_time`, `update_time`, `dict_show_way`) VALUES (11, 1, 'check_time', '核对时间', 'datetime', 'LocalDateTime', 'date-picker', 'string', 'java.time.LocalDateTime', 'checkTime', 'CheckTime', '0', '0', '0', '1', '1', '1', '1', '1', '1', '0', '0', NULL, 'EQ', 'datetime', '', '0', NULL, 11, 1, NULL, '2024-05-10 21:45:32', NULL, '0');
-- INSERT IGNORE INTO `generator_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `search_type`, `ts_type`, `java_type_package`, `java_field`, `up_camel_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `is_import`, `is_export`, `is_autofill`, `is_unique_valid`, `autofill_type`, `query_type`, `html_type`, `dict_type`, `is_logic_del`, `options`, `sort`, `create_id`, `update_id`, `create_time`, `update_time`, `dict_show_way`) VALUES (12, 1, 'create_time', '生成时间', 'datetime', 'LocalDateTime', 'date-picker', 'string', 'java.time.LocalDateTime', 'createTime', 'CreateTime', '0', '0', '0', '0', '0', '0', '0', '0', '0', '1', '0', 'FieldFill.INSERT', 'EQ', 'datetime', '', '0', NULL, 12, 1, NULL, '2024-05-10 21:45:32', NULL, '0');
-- INSERT IGNORE INTO `generator_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `search_type`, `ts_type`, `java_type_package`, `java_field`, `up_camel_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `is_import`, `is_export`, `is_autofill`, `is_unique_valid`, `autofill_type`, `query_type`, `html_type`, `dict_type`, `is_logic_del`, `options`, `sort`, `create_id`, `update_id`, `create_time`, `update_time`, `dict_show_way`) VALUES (13, 1, 'update_time', '更新时间', 'datetime', 'LocalDateTime', 'date-picker', 'string', 'java.time.LocalDateTime', 'updateTime', 'UpdateTime', '0', '0', '0', '0', '0', '0', '0', '0', '0', '1', '0', 'FieldFill.UPDATE', 'EQ', 'datetime', '', '0', NULL, 13, 1, NULL, '2024-05-10 21:45:32', NULL, '0');
-- INSERT IGNORE INTO `generator_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `search_type`, `ts_type`, `java_type_package`, `java_field`, `up_camel_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `is_import`, `is_export`, `is_autofill`, `is_unique_valid`, `autofill_type`, `query_type`, `html_type`, `dict_type`, `is_logic_del`, `options`, `sort`, `create_id`, `update_id`, `create_time`, `update_time`, `dict_show_way`) VALUES (14, 1, 'last_sync_time', '最近一次同步时间', 'datetime', 'LocalDateTime', 'date-picker', 'string', 'java.time.LocalDateTime', 'lastSyncTime', 'LastSyncTime', '0', '0', '0', '1', '1', '1', '1', '1', '1', '0', '0', NULL, 'EQ', 'datetime', '', '0', NULL, 14, 1, NULL, '2024-05-10 21:45:32', NULL, '0');
-- INSERT IGNORE INTO `generator_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `search_type`, `ts_type`, `java_type_package`, `java_field`, `up_camel_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `is_import`, `is_export`, `is_autofill`, `is_unique_valid`, `autofill_type`, `query_type`, `html_type`, `dict_type`, `is_logic_del`, `options`, `sort`, `create_id`, `update_id`, `create_time`, `update_time`, `dict_show_way`) VALUES (15, 1, 'remark', '备注', 'varchar(255)', 'String', 'input', 'string', NULL, 'remark', 'Remark', '0', '0', '0', '1', '1', '1', '0', '1', '1', '0', '0', NULL, 'EQ', 'input', '', '0', NULL, 15, 1, NULL, '2024-05-10 21:45:32', NULL, '0');
--
--

@ -1,31 +1,31 @@
--liquibase formatted sql
--changeset sz:20250526_1636
-- 以下为演示环境脚本,-- 仅供演示使用,实际业务请删除
UPDATE `sys_menu` SET `use_data_scope` = 'T' WHERE `id` = '85b54322630f43a39296488a5e76ba16';
DELETE FROM `generator_table` WHERE `table_id` = 1;
DELETE FROM `generator_table_column` WHERE `table_id` = 1;
ALTER TABLE `teacher_statistics`
MODIFY COLUMN `create_time` datetime DEFAULT NULL COMMENT '生成时间' AFTER `create_id`,
MODIFY COLUMN `update_time` datetime DEFAULT NULL COMMENT '更新时间' AFTER `update_id`;
INSERT INTO `generator_table` (`table_id`, `table_name`, `table_comment`, `class_name`, `camel_class_name`, `tpl_category`, `package_name`, `module_name`, `business_name`, `function_name`, `function_author`, `type`, `options`, `parent_menu_id`, `path`, `path_api`, `path_web`, `menu_init_type`, `btn_permission_type`, `has_import`, `has_export`, `generate_type`, `create_id`, `update_id`, `create_time`, `update_time`, `is_autofill`) VALUES (1, 'teacher_statistics', '教师统计总览表', 'TeacherStatistics', 'teacherStatistics', 'crud', 'com.sz.admin', 'teacher', 'teacherStatistics', '教师统计总览表', 'sz-admin', '0', '', '0', '/', 'E:\\code\\Github\\sz\\sz-boot-parent\\sz-service\\sz-service-admin', '', '1', '1', '1', '1', 'all', 1, 1, '2025-05-27 09:37:08', '2025-05-27 13:23:24', '1');
INSERT INTO `generator_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `search_type`, `ts_type`, `java_type_package`, `java_field`, `up_camel_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `is_import`, `is_export`, `is_autofill`, `is_unique_valid`, `autofill_type`, `query_type`, `html_type`, `dict_type`, `is_logic_del`, `options`, `sort`, `create_id`, `update_id`, `create_time`, `update_time`, `dict_show_way`) VALUES (16, 1, 'id', 'ID', 'bigint', 'Long', 'input', 'number', '', 'id', 'Id', '1', '1', '0', '0', '1', '1', '0', '0', '0', '0', '0', '', 'EQ', 'input-number', '', '0', '', 1, 1, 1, '2025-05-27 09:37:08', '2025-05-27 13:23:24', '0');
INSERT INTO `generator_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `search_type`, `ts_type`, `java_type_package`, `java_field`, `up_camel_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `is_import`, `is_export`, `is_autofill`, `is_unique_valid`, `autofill_type`, `query_type`, `html_type`, `dict_type`, `is_logic_del`, `options`, `sort`, `create_id`, `update_id`, `create_time`, `update_time`, `dict_show_way`) VALUES (17, 1, 'year', '统计年限', 'varchar(4)', 'String', 'input', 'string', '', 'year', 'Year', '0', '0', '1', '1', '1', '1', '1', '1', '1', '0', '0', '', 'EQ', 'input', '', '0', '', 2, 1, 1, '2025-05-27 09:37:08', '2025-05-27 13:23:24', '0');
INSERT INTO `generator_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `search_type`, `ts_type`, `java_type_package`, `java_field`, `up_camel_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `is_import`, `is_export`, `is_autofill`, `is_unique_valid`, `autofill_type`, `query_type`, `html_type`, `dict_type`, `is_logic_del`, `options`, `sort`, `create_id`, `update_id`, `create_time`, `update_time`, `dict_show_way`) VALUES (18, 1, 'month', '统计月份', 'varchar(2)', 'String', 'input', 'string', '', 'month', 'Month', '0', '0', '1', '1', '1', '1', '1', '1', '1', '0', '0', '', 'EQ', 'input', '', '0', '', 3, 1, 1, '2025-05-27 09:37:08', '2025-05-27 13:23:24', '0');
INSERT INTO `generator_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `search_type`, `ts_type`, `java_type_package`, `java_field`, `up_camel_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `is_import`, `is_export`, `is_autofill`, `is_unique_valid`, `autofill_type`, `query_type`, `html_type`, `dict_type`, `is_logic_del`, `options`, `sort`, `create_id`, `update_id`, `create_time`, `update_time`, `dict_show_way`) VALUES (19, 1, 'during_time', '统计年月', 'varchar(10)', 'String', 'date-picker', 'string', '', 'duringTime', 'DuringTime', '0', '0', '0', '1', '1', '1', '1', '1', '1', '0', '0', '', 'EQ', 'input', '', '0', '', 4, 1, 1, '2025-05-27 09:37:08', '2025-05-27 13:23:24', '0');
INSERT INTO `generator_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `search_type`, `ts_type`, `java_type_package`, `java_field`, `up_camel_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `is_import`, `is_export`, `is_autofill`, `is_unique_valid`, `autofill_type`, `query_type`, `html_type`, `dict_type`, `is_logic_del`, `options`, `sort`, `create_id`, `update_id`, `create_time`, `update_time`, `dict_show_way`) VALUES (20, 1, 'teacher_id', '教师id', 'varchar(32)', 'String', 'input', 'string', '', 'teacherId', 'TeacherId', '0', '0', '1', '1', '1', '1', '1', '1', '1', '0', '0', '', 'EQ', 'input', '', '0', '', 5, 1, 1, '2025-05-27 09:37:08', '2025-05-27 13:23:24', '0');
INSERT INTO `generator_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `search_type`, `ts_type`, `java_type_package`, `java_field`, `up_camel_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `is_import`, `is_export`, `is_autofill`, `is_unique_valid`, `autofill_type`, `query_type`, `html_type`, `dict_type`, `is_logic_del`, `options`, `sort`, `create_id`, `update_id`, `create_time`, `update_time`, `dict_show_way`) VALUES (21, 1, 'teacher_common_type', '讲师区分类型', 'int', 'Integer', 'select', 'number', '', 'teacherCommonType', 'TeacherCommonType', '0', '0', '1', '1', '1', '1', '1', '1', '1', '0', '0', '', 'EQ', 'select', '', '0', '', 6, 1, 1, '2025-05-27 09:37:08', '2025-05-27 13:23:24', '0');
INSERT INTO `generator_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `search_type`, `ts_type`, `java_type_package`, `java_field`, `up_camel_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `is_import`, `is_export`, `is_autofill`, `is_unique_valid`, `autofill_type`, `query_type`, `html_type`, `dict_type`, `is_logic_del`, `options`, `sort`, `create_id`, `update_id`, `create_time`, `update_time`, `dict_show_way`) VALUES (22, 1, 'total_teaching', '授课总数', 'int', 'Integer', 'input', 'number', '', 'totalTeaching', 'TotalTeaching', '0', '0', '0', '1', '1', '1', '1', '1', '1', '0', '0', '', 'EQ', 'input-number', '', '0', '', 7, 1, 1, '2025-05-27 09:37:08', '2025-05-27 13:23:24', '0');
INSERT INTO `generator_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `search_type`, `ts_type`, `java_type_package`, `java_field`, `up_camel_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `is_import`, `is_export`, `is_autofill`, `is_unique_valid`, `autofill_type`, `query_type`, `html_type`, `dict_type`, `is_logic_del`, `options`, `sort`, `create_id`, `update_id`, `create_time`, `update_time`, `dict_show_way`) VALUES (23, 1, 'total_class_count', '服务班次数', 'int', 'Integer', 'input', 'number', '', 'totalClassCount', 'TotalClassCount', '0', '0', '0', '1', '1', '1', '1', '1', '1', '0', '0', '', 'EQ', 'input-number', '', '0', '', 8, 1, 1, '2025-05-27 09:37:08', '2025-05-27 13:23:24', '0');
INSERT INTO `generator_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `search_type`, `ts_type`, `java_type_package`, `java_field`, `up_camel_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `is_import`, `is_export`, `is_autofill`, `is_unique_valid`, `autofill_type`, `query_type`, `html_type`, `dict_type`, `is_logic_del`, `options`, `sort`, `create_id`, `update_id`, `create_time`, `update_time`, `dict_show_way`) VALUES (24, 1, 'total_hours', '课时总数', 'decimal(10,2)', 'BigDecimal', 'input', 'number', 'java.math.BigDecimal', 'totalHours', 'TotalHours', '0', '0', '0', '1', '1', '1', '1', '1', '1', '0', '0', '', 'EQ', 'input-number', '', '0', '', 9, 1, 1, '2025-05-27 09:37:08', '2025-05-27 13:23:24', '0');
INSERT INTO `generator_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `search_type`, `ts_type`, `java_type_package`, `java_field`, `up_camel_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `is_import`, `is_export`, `is_autofill`, `is_unique_valid`, `autofill_type`, `query_type`, `html_type`, `dict_type`, `is_logic_del`, `options`, `sort`, `create_id`, `update_id`, `create_time`, `update_time`, `dict_show_way`) VALUES (25, 1, 'check_status', '核对状态', 'int', 'Integer', 'select', 'number', '', 'checkStatus', 'CheckStatus', '0', '0', '1', '1', '1', '1', '1', '1', '1', '0', '0', '', 'EQ', 'radio', '', '0', '', 10, 1, 1, '2025-05-27 09:37:08', '2025-05-27 13:23:24', '0');
INSERT INTO `generator_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `search_type`, `ts_type`, `java_type_package`, `java_field`, `up_camel_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `is_import`, `is_export`, `is_autofill`, `is_unique_valid`, `autofill_type`, `query_type`, `html_type`, `dict_type`, `is_logic_del`, `options`, `sort`, `create_id`, `update_id`, `create_time`, `update_time`, `dict_show_way`) VALUES (26, 1, 'check_time', '核对时间', 'datetime', 'LocalDateTime', 'date-picker', 'string', 'java.time.LocalDateTime', 'checkTime', 'CheckTime', '0', '0', '0', '1', '1', '1', '1', '1', '1', '0', '0', '', 'BETWEEN', 'datetime', '', '0', '', 11, 1, 1, '2025-05-27 09:37:08', '2025-05-27 13:23:24', '0');
INSERT INTO `generator_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `search_type`, `ts_type`, `java_type_package`, `java_field`, `up_camel_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `is_import`, `is_export`, `is_autofill`, `is_unique_valid`, `autofill_type`, `query_type`, `html_type`, `dict_type`, `is_logic_del`, `options`, `sort`, `create_id`, `update_id`, `create_time`, `update_time`, `dict_show_way`) VALUES (27, 1, 'last_sync_time', '最近一次同步时间', 'datetime', 'LocalDateTime', 'date-picker', 'string', 'java.time.LocalDateTime', 'lastSyncTime', 'LastSyncTime', '0', '0', '0', '1', '1', '1', '1', '1', '1', '0', '0', '', 'BETWEEN', 'datetime', '', '0', '', 12, 1, 1, '2025-05-27 09:37:08', '2025-05-27 13:23:24', '0');
INSERT INTO `generator_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `search_type`, `ts_type`, `java_type_package`, `java_field`, `up_camel_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `is_import`, `is_export`, `is_autofill`, `is_unique_valid`, `autofill_type`, `query_type`, `html_type`, `dict_type`, `is_logic_del`, `options`, `sort`, `create_id`, `update_id`, `create_time`, `update_time`, `dict_show_way`) VALUES (28, 1, 'remark', '备注', 'varchar(255)', 'String', 'input', 'string', '', 'remark', 'Remark', '0', '0', '0', '1', '1', '1', '0', '1', '1', '0', '0', '', 'EQ', 'input', '', '0', '', 13, 1, 1, '2025-05-27 09:37:08', '2025-05-27 13:23:24', '0');
INSERT INTO `generator_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `search_type`, `ts_type`, `java_type_package`, `java_field`, `up_camel_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `is_import`, `is_export`, `is_autofill`, `is_unique_valid`, `autofill_type`, `query_type`, `html_type`, `dict_type`, `is_logic_del`, `options`, `sort`, `create_id`, `update_id`, `create_time`, `update_time`, `dict_show_way`) VALUES (29, 1, 'create_id', '创建人ID', 'bigint', 'Long', 'input', 'number', '', 'createId', 'CreateId', '0', '0', '0', '0', '0', '1', '0', '0', '1', '1', '0', 'FieldFill.INSERT', 'EQ', 'input-number', 'dynamic_user_options', '0', '', 14, 1, 1, '2025-05-27 09:37:08', '2025-05-27 13:23:24', '0');
INSERT INTO `generator_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `search_type`, `ts_type`, `java_type_package`, `java_field`, `up_camel_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `is_import`, `is_export`, `is_autofill`, `is_unique_valid`, `autofill_type`, `query_type`, `html_type`, `dict_type`, `is_logic_del`, `options`, `sort`, `create_id`, `update_id`, `create_time`, `update_time`, `dict_show_way`) VALUES (30, 1, 'create_time', '生成时间', 'datetime', 'LocalDateTime', 'date-picker', 'string', 'java.time.LocalDateTime', 'createTime', 'CreateTime', '0', '0', '0', '0', '0', '1', '0', '0', '1', '1', '0', 'FieldFill.INSERT', 'BETWEEN', 'datetime', '', '0', '', 15, 1, 1, '2025-05-27 09:37:08', '2025-05-27 13:23:24', '0');
INSERT INTO `generator_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `search_type`, `ts_type`, `java_type_package`, `java_field`, `up_camel_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `is_import`, `is_export`, `is_autofill`, `is_unique_valid`, `autofill_type`, `query_type`, `html_type`, `dict_type`, `is_logic_del`, `options`, `sort`, `create_id`, `update_id`, `create_time`, `update_time`, `dict_show_way`) VALUES (31, 1, 'update_id', '更新人ID', 'bigint', 'Long', 'input', 'number', '', 'updateId', 'UpdateId', '0', '0', '0', '0', '0', '1', '0', '0', '1', '1', '0', 'FieldFill.UPDATE', 'EQ', 'input-number', 'dynamic_user_options', '0', '', 16, 1, 1, '2025-05-27 09:37:08', '2025-05-27 13:23:24', '0');
INSERT INTO `generator_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `search_type`, `ts_type`, `java_type_package`, `java_field`, `up_camel_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `is_import`, `is_export`, `is_autofill`, `is_unique_valid`, `autofill_type`, `query_type`, `html_type`, `dict_type`, `is_logic_del`, `options`, `sort`, `create_id`, `update_id`, `create_time`, `update_time`, `dict_show_way`) VALUES (32, 1, 'update_time', '更新时间', 'datetime', 'LocalDateTime', 'date-picker', 'string', 'java.time.LocalDateTime', 'updateTime', 'UpdateTime', '0', '0', '0', '0', '0', '1', '0', '0', '1', '1', '0', 'FieldFill.UPDATE', 'BETWEEN', 'datetime', '', '0', '', 17, 1, 1, '2025-05-27 09:37:08', '2025-05-27 13:23:24', '0');
INSERT INTO `generator_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `search_type`, `ts_type`, `java_type_package`, `java_field`, `up_camel_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `is_import`, `is_export`, `is_autofill`, `is_unique_valid`, `autofill_type`, `query_type`, `html_type`, `dict_type`, `is_logic_del`, `options`, `sort`, `create_id`, `update_id`, `create_time`, `update_time`, `dict_show_way`) VALUES (33, 1, 'dept_scope', '部门范围', 'json', 'String', 'input', 'string', '', 'deptScope', 'DeptScope', '0', '0', '0', '0', '0', '0', '0', '0', '1', '0', '0', '', 'EQ', '', '', '0', '', 18, 1, 1, '2025-05-27 09:37:08', '2025-05-27 13:23:24', '0');
-- --liquibase formatted sql
--
-- --changeset 升职哦sz:20250526_1636
-- -- 以下为演示环境脚本,-- 仅供演示使用,实际业务请删除
-- UPDATE `sys_menu` SET `use_data_scope` = 'T' WHERE `id` = '85b54322630f43a39296488a5e76ba16';
-- DELETE FROM `generator_table` WHERE `table_id` = 1;
-- DELETE FROM `generator_table_column` WHERE `table_id` = 1;
-- ALTER TABLE `teacher_statistics`
-- MODIFY COLUMN `create_time` datetime DEFAULT NULL COMMENT '生成时间' AFTER `create_id`,
-- MODIFY COLUMN `update_time` datetime DEFAULT NULL COMMENT '更新时间' AFTER `update_id`;
--
-- INSERT INTO `generator_table` (`table_id`, `table_name`, `table_comment`, `class_name`, `camel_class_name`, `tpl_category`, `package_name`, `module_name`, `business_name`, `function_name`, `function_author`, `type`, `options`, `parent_menu_id`, `path`, `path_api`, `path_web`, `menu_init_type`, `btn_permission_type`, `has_import`, `has_export`, `generate_type`, `create_id`, `update_id`, `create_time`, `update_time`, `is_autofill`) VALUES (1, 'teacher_statistics', '教师统计总览表', 'TeacherStatistics', 'teacherStatistics', 'crud', 'com.sz.admin', 'teacher', 'teacherStatistics', '教师统计总览表', 'sz-admin', '0', '', '0', '/', 'E:\\code\\Github\\sz\\sz-boot-parent\\sz-service\\sz-service-admin', '', '1', '1', '1', '1', 'all', 1, 1, '2025-05-27 09:37:08', '2025-05-27 13:23:24', '1');
--
-- INSERT INTO `generator_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `search_type`, `ts_type`, `java_type_package`, `java_field`, `up_camel_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `is_import`, `is_export`, `is_autofill`, `is_unique_valid`, `autofill_type`, `query_type`, `html_type`, `dict_type`, `is_logic_del`, `options`, `sort`, `create_id`, `update_id`, `create_time`, `update_time`, `dict_show_way`) VALUES (16, 1, 'id', 'ID', 'bigint', 'Long', 'input', 'number', '', 'id', 'Id', '1', '1', '0', '0', '1', '1', '0', '0', '0', '0', '0', '', 'EQ', 'input-number', '', '0', '', 1, 1, 1, '2025-05-27 09:37:08', '2025-05-27 13:23:24', '0');
-- INSERT INTO `generator_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `search_type`, `ts_type`, `java_type_package`, `java_field`, `up_camel_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `is_import`, `is_export`, `is_autofill`, `is_unique_valid`, `autofill_type`, `query_type`, `html_type`, `dict_type`, `is_logic_del`, `options`, `sort`, `create_id`, `update_id`, `create_time`, `update_time`, `dict_show_way`) VALUES (17, 1, 'year', '统计年限', 'varchar(4)', 'String', 'input', 'string', '', 'year', 'Year', '0', '0', '1', '1', '1', '1', '1', '1', '1', '0', '0', '', 'EQ', 'input', '', '0', '', 2, 1, 1, '2025-05-27 09:37:08', '2025-05-27 13:23:24', '0');
-- INSERT INTO `generator_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `search_type`, `ts_type`, `java_type_package`, `java_field`, `up_camel_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `is_import`, `is_export`, `is_autofill`, `is_unique_valid`, `autofill_type`, `query_type`, `html_type`, `dict_type`, `is_logic_del`, `options`, `sort`, `create_id`, `update_id`, `create_time`, `update_time`, `dict_show_way`) VALUES (18, 1, 'month', '统计月份', 'varchar(2)', 'String', 'input', 'string', '', 'month', 'Month', '0', '0', '1', '1', '1', '1', '1', '1', '1', '0', '0', '', 'EQ', 'input', '', '0', '', 3, 1, 1, '2025-05-27 09:37:08', '2025-05-27 13:23:24', '0');
-- INSERT INTO `generator_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `search_type`, `ts_type`, `java_type_package`, `java_field`, `up_camel_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `is_import`, `is_export`, `is_autofill`, `is_unique_valid`, `autofill_type`, `query_type`, `html_type`, `dict_type`, `is_logic_del`, `options`, `sort`, `create_id`, `update_id`, `create_time`, `update_time`, `dict_show_way`) VALUES (19, 1, 'during_time', '统计年月', 'varchar(10)', 'String', 'date-picker', 'string', '', 'duringTime', 'DuringTime', '0', '0', '0', '1', '1', '1', '1', '1', '1', '0', '0', '', 'EQ', 'input', '', '0', '', 4, 1, 1, '2025-05-27 09:37:08', '2025-05-27 13:23:24', '0');
-- INSERT INTO `generator_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `search_type`, `ts_type`, `java_type_package`, `java_field`, `up_camel_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `is_import`, `is_export`, `is_autofill`, `is_unique_valid`, `autofill_type`, `query_type`, `html_type`, `dict_type`, `is_logic_del`, `options`, `sort`, `create_id`, `update_id`, `create_time`, `update_time`, `dict_show_way`) VALUES (20, 1, 'teacher_id', '教师id', 'varchar(32)', 'String', 'input', 'string', '', 'teacherId', 'TeacherId', '0', '0', '1', '1', '1', '1', '1', '1', '1', '0', '0', '', 'EQ', 'input', '', '0', '', 5, 1, 1, '2025-05-27 09:37:08', '2025-05-27 13:23:24', '0');
-- INSERT INTO `generator_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `search_type`, `ts_type`, `java_type_package`, `java_field`, `up_camel_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `is_import`, `is_export`, `is_autofill`, `is_unique_valid`, `autofill_type`, `query_type`, `html_type`, `dict_type`, `is_logic_del`, `options`, `sort`, `create_id`, `update_id`, `create_time`, `update_time`, `dict_show_way`) VALUES (21, 1, 'teacher_common_type', '讲师区分类型', 'int', 'Integer', 'select', 'number', '', 'teacherCommonType', 'TeacherCommonType', '0', '0', '1', '1', '1', '1', '1', '1', '1', '0', '0', '', 'EQ', 'select', '', '0', '', 6, 1, 1, '2025-05-27 09:37:08', '2025-05-27 13:23:24', '0');
-- INSERT INTO `generator_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `search_type`, `ts_type`, `java_type_package`, `java_field`, `up_camel_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `is_import`, `is_export`, `is_autofill`, `is_unique_valid`, `autofill_type`, `query_type`, `html_type`, `dict_type`, `is_logic_del`, `options`, `sort`, `create_id`, `update_id`, `create_time`, `update_time`, `dict_show_way`) VALUES (22, 1, 'total_teaching', '授课总数', 'int', 'Integer', 'input', 'number', '', 'totalTeaching', 'TotalTeaching', '0', '0', '0', '1', '1', '1', '1', '1', '1', '0', '0', '', 'EQ', 'input-number', '', '0', '', 7, 1, 1, '2025-05-27 09:37:08', '2025-05-27 13:23:24', '0');
-- INSERT INTO `generator_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `search_type`, `ts_type`, `java_type_package`, `java_field`, `up_camel_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `is_import`, `is_export`, `is_autofill`, `is_unique_valid`, `autofill_type`, `query_type`, `html_type`, `dict_type`, `is_logic_del`, `options`, `sort`, `create_id`, `update_id`, `create_time`, `update_time`, `dict_show_way`) VALUES (23, 1, 'total_class_count', '服务班次数', 'int', 'Integer', 'input', 'number', '', 'totalClassCount', 'TotalClassCount', '0', '0', '0', '1', '1', '1', '1', '1', '1', '0', '0', '', 'EQ', 'input-number', '', '0', '', 8, 1, 1, '2025-05-27 09:37:08', '2025-05-27 13:23:24', '0');
-- INSERT INTO `generator_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `search_type`, `ts_type`, `java_type_package`, `java_field`, `up_camel_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `is_import`, `is_export`, `is_autofill`, `is_unique_valid`, `autofill_type`, `query_type`, `html_type`, `dict_type`, `is_logic_del`, `options`, `sort`, `create_id`, `update_id`, `create_time`, `update_time`, `dict_show_way`) VALUES (24, 1, 'total_hours', '课时总数', 'decimal(10,2)', 'BigDecimal', 'input', 'number', 'java.math.BigDecimal', 'totalHours', 'TotalHours', '0', '0', '0', '1', '1', '1', '1', '1', '1', '0', '0', '', 'EQ', 'input-number', '', '0', '', 9, 1, 1, '2025-05-27 09:37:08', '2025-05-27 13:23:24', '0');
-- INSERT INTO `generator_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `search_type`, `ts_type`, `java_type_package`, `java_field`, `up_camel_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `is_import`, `is_export`, `is_autofill`, `is_unique_valid`, `autofill_type`, `query_type`, `html_type`, `dict_type`, `is_logic_del`, `options`, `sort`, `create_id`, `update_id`, `create_time`, `update_time`, `dict_show_way`) VALUES (25, 1, 'check_status', '核对状态', 'int', 'Integer', 'select', 'number', '', 'checkStatus', 'CheckStatus', '0', '0', '1', '1', '1', '1', '1', '1', '1', '0', '0', '', 'EQ', 'radio', '', '0', '', 10, 1, 1, '2025-05-27 09:37:08', '2025-05-27 13:23:24', '0');
-- INSERT INTO `generator_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `search_type`, `ts_type`, `java_type_package`, `java_field`, `up_camel_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `is_import`, `is_export`, `is_autofill`, `is_unique_valid`, `autofill_type`, `query_type`, `html_type`, `dict_type`, `is_logic_del`, `options`, `sort`, `create_id`, `update_id`, `create_time`, `update_time`, `dict_show_way`) VALUES (26, 1, 'check_time', '核对时间', 'datetime', 'LocalDateTime', 'date-picker', 'string', 'java.time.LocalDateTime', 'checkTime', 'CheckTime', '0', '0', '0', '1', '1', '1', '1', '1', '1', '0', '0', '', 'BETWEEN', 'datetime', '', '0', '', 11, 1, 1, '2025-05-27 09:37:08', '2025-05-27 13:23:24', '0');
-- INSERT INTO `generator_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `search_type`, `ts_type`, `java_type_package`, `java_field`, `up_camel_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `is_import`, `is_export`, `is_autofill`, `is_unique_valid`, `autofill_type`, `query_type`, `html_type`, `dict_type`, `is_logic_del`, `options`, `sort`, `create_id`, `update_id`, `create_time`, `update_time`, `dict_show_way`) VALUES (27, 1, 'last_sync_time', '最近一次同步时间', 'datetime', 'LocalDateTime', 'date-picker', 'string', 'java.time.LocalDateTime', 'lastSyncTime', 'LastSyncTime', '0', '0', '0', '1', '1', '1', '1', '1', '1', '0', '0', '', 'BETWEEN', 'datetime', '', '0', '', 12, 1, 1, '2025-05-27 09:37:08', '2025-05-27 13:23:24', '0');
-- INSERT INTO `generator_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `search_type`, `ts_type`, `java_type_package`, `java_field`, `up_camel_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `is_import`, `is_export`, `is_autofill`, `is_unique_valid`, `autofill_type`, `query_type`, `html_type`, `dict_type`, `is_logic_del`, `options`, `sort`, `create_id`, `update_id`, `create_time`, `update_time`, `dict_show_way`) VALUES (28, 1, 'remark', '备注', 'varchar(255)', 'String', 'input', 'string', '', 'remark', 'Remark', '0', '0', '0', '1', '1', '1', '0', '1', '1', '0', '0', '', 'EQ', 'input', '', '0', '', 13, 1, 1, '2025-05-27 09:37:08', '2025-05-27 13:23:24', '0');
-- INSERT INTO `generator_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `search_type`, `ts_type`, `java_type_package`, `java_field`, `up_camel_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `is_import`, `is_export`, `is_autofill`, `is_unique_valid`, `autofill_type`, `query_type`, `html_type`, `dict_type`, `is_logic_del`, `options`, `sort`, `create_id`, `update_id`, `create_time`, `update_time`, `dict_show_way`) VALUES (29, 1, 'create_id', '创建人ID', 'bigint', 'Long', 'input', 'number', '', 'createId', 'CreateId', '0', '0', '0', '0', '0', '1', '0', '0', '1', '1', '0', 'FieldFill.INSERT', 'EQ', 'input-number', 'dynamic_user_options', '0', '', 14, 1, 1, '2025-05-27 09:37:08', '2025-05-27 13:23:24', '0');
-- INSERT INTO `generator_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `search_type`, `ts_type`, `java_type_package`, `java_field`, `up_camel_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `is_import`, `is_export`, `is_autofill`, `is_unique_valid`, `autofill_type`, `query_type`, `html_type`, `dict_type`, `is_logic_del`, `options`, `sort`, `create_id`, `update_id`, `create_time`, `update_time`, `dict_show_way`) VALUES (30, 1, 'create_time', '生成时间', 'datetime', 'LocalDateTime', 'date-picker', 'string', 'java.time.LocalDateTime', 'createTime', 'CreateTime', '0', '0', '0', '0', '0', '1', '0', '0', '1', '1', '0', 'FieldFill.INSERT', 'BETWEEN', 'datetime', '', '0', '', 15, 1, 1, '2025-05-27 09:37:08', '2025-05-27 13:23:24', '0');
-- INSERT INTO `generator_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `search_type`, `ts_type`, `java_type_package`, `java_field`, `up_camel_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `is_import`, `is_export`, `is_autofill`, `is_unique_valid`, `autofill_type`, `query_type`, `html_type`, `dict_type`, `is_logic_del`, `options`, `sort`, `create_id`, `update_id`, `create_time`, `update_time`, `dict_show_way`) VALUES (31, 1, 'update_id', '更新人ID', 'bigint', 'Long', 'input', 'number', '', 'updateId', 'UpdateId', '0', '0', '0', '0', '0', '1', '0', '0', '1', '1', '0', 'FieldFill.UPDATE', 'EQ', 'input-number', 'dynamic_user_options', '0', '', 16, 1, 1, '2025-05-27 09:37:08', '2025-05-27 13:23:24', '0');
-- INSERT INTO `generator_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `search_type`, `ts_type`, `java_type_package`, `java_field`, `up_camel_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `is_import`, `is_export`, `is_autofill`, `is_unique_valid`, `autofill_type`, `query_type`, `html_type`, `dict_type`, `is_logic_del`, `options`, `sort`, `create_id`, `update_id`, `create_time`, `update_time`, `dict_show_way`) VALUES (32, 1, 'update_time', '更新时间', 'datetime', 'LocalDateTime', 'date-picker', 'string', 'java.time.LocalDateTime', 'updateTime', 'UpdateTime', '0', '0', '0', '0', '0', '1', '0', '0', '1', '1', '0', 'FieldFill.UPDATE', 'BETWEEN', 'datetime', '', '0', '', 17, 1, 1, '2025-05-27 09:37:08', '2025-05-27 13:23:24', '0');
-- INSERT INTO `generator_table_column` (`column_id`, `table_id`, `column_name`, `column_comment`, `column_type`, `java_type`, `search_type`, `ts_type`, `java_type_package`, `java_field`, `up_camel_field`, `is_pk`, `is_increment`, `is_required`, `is_insert`, `is_edit`, `is_list`, `is_query`, `is_import`, `is_export`, `is_autofill`, `is_unique_valid`, `autofill_type`, `query_type`, `html_type`, `dict_type`, `is_logic_del`, `options`, `sort`, `create_id`, `update_id`, `create_time`, `update_time`, `dict_show_way`) VALUES (33, 1, 'dept_scope', '部门范围', 'json', 'String', 'input', 'string', '', 'deptScope', 'DeptScope', '0', '0', '0', '0', '0', '0', '0', '0', '1', '0', '0', '', 'EQ', '', '', '0', '', 18, 1, 1, '2025-05-27 09:37:08', '2025-05-27 13:23:24', '0');

@ -1,10 +1,10 @@
--liquibase formatted sql
--changeset sz:20251013_1836
-- 以下为演示环境脚本,-- 仅供演示使用,实际业务请删除
ALTER TABLE `teacher_statistics` ADD COLUMN `url` json DEFAULT NULL COMMENT '文件地址(JSON)';
--changeset sz:20251021_2100
UPDATE `teacher_statistics` SET `url` = '[{\"url\": \"https://minioapi.szadmin.cn/test/teacher/20251021/bg1.png\", \"etag\": \"73be62dc9778dc13478c59f0c236feca\", \"size\": 105636, \"dirTag\": \"teacher\", \"fileId\": 158, \"filename\": \"bg1.png\", \"metaData\": {\"original-filename\": \"bg1.png\"}, \"objectName\": \"teacher/20251021/bg1.png\", \"contextType\": \"image/png\"}, {\"url\": \"https://minioapi.szadmin.cn/test/teacher/20251021/bg7.png\", \"etag\": \"6b6857c36b4fded86645d0ed2662869b\", \"size\": 66861, \"dirTag\": \"teacher\", \"fileId\": 156, \"filename\": \"bg7.png\", \"metaData\": {\"original-filename\": \"bg7.png\"}, \"objectName\": \"teacher/20251021/bg7.png\", \"contextType\": \"image/png\"}, {\"url\": \"https://minioapi.szadmin.cn/test/teacher/20251021/bg10.png\", \"etag\": \"9a546cb494af380c9e2cf5efac2ae362\", \"size\": 87531, \"dirTag\": \"teacher\", \"fileId\": 157, \"filename\": \"bg10.png\", \"metaData\": {\"original-filename\": \"bg10.png\"}, \"objectName\": \"teacher/20251021/bg10.png\", \"contextType\": \"image/png\"}]' WHERE `id` = 26;
UPDATE `teacher_statistics` SET `url` = '[{\"url\": \"https://minioapi.szadmin.cn/test/teacher/20251021/bg4.png\", \"etag\": \"c4a227a6f24d5b818bf46a49d28cf282\", \"size\": 90015, \"dirTag\": \"teacher\", \"fileId\": 153, \"filename\": \"bg4.png\", \"metaData\": {\"original-filename\": \"bg4.png\"}, \"objectName\": \"teacher/20251021/bg4.png\", \"contextType\": \"image/png\"}, {\"url\": \"https://minioapi.szadmin.cn/test/teacher/20251021/bg5.png\", \"etag\": \"a6e547dcfe5a50a060d5f895857f0c9b\", \"size\": 70640, \"dirTag\": \"teacher\", \"fileId\": 152, \"filename\": \"bg5.png\", \"metaData\": {\"original-filename\": \"bg5.png\"}, \"objectName\": \"teacher/20251021/bg5.png\", \"contextType\": \"image/png\"}, {\"url\": \"https://minioapi.szadmin.cn/test/teacher/20251021/微信图片_20240420160033.jpg\", \"etag\": \"322e08e6b47cd85dec6a7b8dc9e88476\", \"size\": 20276, \"dirTag\": \"teacher\", \"fileId\": 151, \"filename\": \"微信图片_20240420160033.jpg\", \"metaData\": {\"original-filename\": \"微信图片_20240420160033.jpg\"}, \"objectName\": \"teacher/20251021/微信图片_20240420160033.jpg\", \"contextType\": \"image/jpeg\"}, {\"url\": \"https://minioapi.szadmin.cn/test/teacher/20251021/教师统计.xlsx\", \"etag\": \"47c4e1a9be3987a477d2c9672f761968\", \"size\": 5481, \"dirTag\": \"teacher\", \"fileId\": 154, \"filename\": \"教师统计.xlsx\", \"metaData\": {\"original-filename\": \"教师统计.xlsx\"}, \"objectName\": \"teacher/20251021/教师统计.xlsx\", \"contextType\": \"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet\"}, {\"url\": \"https://minioapi.szadmin.cn/test/teacher/20251021/题库导入模板.xlsx\", \"etag\": \"54e2201ec376091aeb3f25581feba1c1\", \"size\": 13862, \"dirTag\": \"teacher\", \"fileId\": 155, \"filename\": \"题库导入模板.xlsx\", \"metaData\": {\"original-filename\": \"题库导入模板.xlsx\"}, \"objectName\": \"teacher/20251021/题库导入模板.xlsx\", \"contextType\": \"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet\"}]' WHERE `id` = 27;
-- --liquibase formatted sql
--
-- --changeset 升职哦sz:20251013_1836
-- -- 以下为演示环境脚本,-- 仅供演示使用,实际业务请删除
--
-- ALTER TABLE `teacher_statistics` ADD COLUMN `url` json DEFAULT NULL COMMENT '文件地址(JSON)';
--
-- --changeset 升职哦sz:20251021_2100
-- UPDATE `teacher_statistics` SET `url` = '[{\"url\": \"https://minioapi.szadmin.cn/test/teacher/20251021/bg1.png\", \"etag\": \"73be62dc9778dc13478c59f0c236feca\", \"size\": 105636, \"dirTag\": \"teacher\", \"fileId\": 158, \"filename\": \"bg1.png\", \"metaData\": {\"original-filename\": \"bg1.png\"}, \"objectName\": \"teacher/20251021/bg1.png\", \"contextType\": \"image/png\"}, {\"url\": \"https://minioapi.szadmin.cn/test/teacher/20251021/bg7.png\", \"etag\": \"6b6857c36b4fded86645d0ed2662869b\", \"size\": 66861, \"dirTag\": \"teacher\", \"fileId\": 156, \"filename\": \"bg7.png\", \"metaData\": {\"original-filename\": \"bg7.png\"}, \"objectName\": \"teacher/20251021/bg7.png\", \"contextType\": \"image/png\"}, {\"url\": \"https://minioapi.szadmin.cn/test/teacher/20251021/bg10.png\", \"etag\": \"9a546cb494af380c9e2cf5efac2ae362\", \"size\": 87531, \"dirTag\": \"teacher\", \"fileId\": 157, \"filename\": \"bg10.png\", \"metaData\": {\"original-filename\": \"bg10.png\"}, \"objectName\": \"teacher/20251021/bg10.png\", \"contextType\": \"image/png\"}]' WHERE `id` = 26;
-- UPDATE `teacher_statistics` SET `url` = '[{\"url\": \"https://minioapi.szadmin.cn/test/teacher/20251021/bg4.png\", \"etag\": \"c4a227a6f24d5b818bf46a49d28cf282\", \"size\": 90015, \"dirTag\": \"teacher\", \"fileId\": 153, \"filename\": \"bg4.png\", \"metaData\": {\"original-filename\": \"bg4.png\"}, \"objectName\": \"teacher/20251021/bg4.png\", \"contextType\": \"image/png\"}, {\"url\": \"https://minioapi.szadmin.cn/test/teacher/20251021/bg5.png\", \"etag\": \"a6e547dcfe5a50a060d5f895857f0c9b\", \"size\": 70640, \"dirTag\": \"teacher\", \"fileId\": 152, \"filename\": \"bg5.png\", \"metaData\": {\"original-filename\": \"bg5.png\"}, \"objectName\": \"teacher/20251021/bg5.png\", \"contextType\": \"image/png\"}, {\"url\": \"https://minioapi.szadmin.cn/test/teacher/20251021/微信图片_20240420160033.jpg\", \"etag\": \"322e08e6b47cd85dec6a7b8dc9e88476\", \"size\": 20276, \"dirTag\": \"teacher\", \"fileId\": 151, \"filename\": \"微信图片_20240420160033.jpg\", \"metaData\": {\"original-filename\": \"微信图片_20240420160033.jpg\"}, \"objectName\": \"teacher/20251021/微信图片_20240420160033.jpg\", \"contextType\": \"image/jpeg\"}, {\"url\": \"https://minioapi.szadmin.cn/test/teacher/20251021/教师统计.xlsx\", \"etag\": \"47c4e1a9be3987a477d2c9672f761968\", \"size\": 5481, \"dirTag\": \"teacher\", \"fileId\": 154, \"filename\": \"教师统计.xlsx\", \"metaData\": {\"original-filename\": \"教师统计.xlsx\"}, \"objectName\": \"teacher/20251021/教师统计.xlsx\", \"contextType\": \"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet\"}, {\"url\": \"https://minioapi.szadmin.cn/test/teacher/20251021/题库导入模板.xlsx\", \"etag\": \"54e2201ec376091aeb3f25581feba1c1\", \"size\": 13862, \"dirTag\": \"teacher\", \"fileId\": 155, \"filename\": \"题库导入模板.xlsx\", \"metaData\": {\"original-filename\": \"题库导入模板.xlsx\"}, \"objectName\": \"teacher/20251021/题库导入模板.xlsx\", \"contextType\": \"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet\"}]' WHERE `id` = 27;

@ -1,66 +1,66 @@
--liquibase formatted sql
--changeset sz:20251105_1934
DELETE FROM `sys_role` WHERE id = 3 and permissions = 'teacher_statics_menu';
-- 创建新的演示角色
INSERT IGNORE INTO `sys_role` (`id`, `role_name`, `remark`, `del_flag`, `create_time`, `update_time`, `create_id`, `update_id`, `is_lock`, `permissions`) VALUES (3, '教师统计-全部', '演示:数据权限-全部', 'F', '2024-05-10 21:53:15', '2025-11-05 13:39:50', NULL, 1, 'T', 'teacher_statics_menu_1006001');
INSERT IGNORE INTO `sys_role` (`id`, `role_name`, `remark`, `del_flag`, `create_time`, `update_time`, `create_id`, `update_id`, `is_lock`, `permissions`) VALUES (4, '教师统计-部门及以下', '演示:数据权限-部门及以下', 'F', '2025-11-05 11:24:40', '2025-11-05 13:39:45', 1, 1, 'T', 'teacher_statics_menu_1006002');
INSERT IGNORE INTO `sys_role` (`id`, `role_name`, `remark`, `del_flag`, `create_time`, `update_time`, `create_id`, `update_id`, `is_lock`, `permissions`) VALUES (5, '教师统计-仅本部', '演示:数据权限-仅本部', 'F', '2025-11-05 11:25:21', '2025-11-05 13:40:02', 1, 1, 'T', 'teacher_statics_menu_1006003');
INSERT IGNORE INTO `sys_role` (`id`, `role_name`, `remark`, `del_flag`, `create_time`, `update_time`, `create_id`, `update_id`, `is_lock`, `permissions`) VALUES (6, '教师统计-仅本人', '演示:数据权限-仅本人', 'F', '2025-11-05 13:39:19', '2025-11-05 13:40:08', 1, 1, 'T', 'teacher_statics_menu_1006004');
INSERT IGNORE INTO `sys_role` (`id`, `role_name`, `remark`, `del_flag`, `create_time`, `update_time`, `create_id`, `update_id`, `is_lock`, `permissions`) VALUES (7, '教师统计-自定义', '演示:数据权限-自定义', 'F', '2025-11-05 13:46:50', '2025-11-05 13:46:50', 1, 1, 'T', 'teacher_statics_menu_1006005');
-- 为新的角色分配菜单权
INSERT IGNORE INTO `sys_role_menu` (`menu_id`, `role_id`, `permission_type`, `data_scope_cd`) VALUES ('ab1ac16c617d41979472ebe433c1f8e4', 3, 'menu', NULL);
INSERT IGNORE INTO `sys_role_menu` (`menu_id`, `role_id`, `permission_type`, `data_scope_cd`) VALUES ('85b54322630f43a39296488a5e76ba16', 3, 'menu', NULL);
INSERT IGNORE INTO `sys_role_menu` (`menu_id`, `role_id`, `permission_type`, `data_scope_cd`) VALUES ('cb3500315dba4c2d83e4d92edf36dff7', 3, 'menu', NULL);
INSERT IGNORE INTO `sys_role_menu` (`menu_id`, `role_id`, `permission_type`, `data_scope_cd`) VALUES ('7391f12ad51049c2b86d231d39708c71', 3, 'menu', NULL);
INSERT IGNORE INTO `sys_role_menu` (`menu_id`, `role_id`, `permission_type`, `data_scope_cd`) VALUES ('73d312f4fa8949ddba3d9807c0c56f00', 3, 'menu', NULL);
INSERT IGNORE INTO `sys_role_menu` (`menu_id`, `role_id`, `permission_type`, `data_scope_cd`) VALUES ('91ccb13b5c174583803a4c492a5dfdb6', 3, 'menu', NULL);
INSERT IGNORE INTO `sys_role_menu` (`menu_id`, `role_id`, `permission_type`, `data_scope_cd`) VALUES ('8061d8e79be744bf91b7b438f8e8e887', 3, 'menu', NULL);
INSERT IGNORE INTO `sys_role_menu` (`menu_id`, `role_id`, `permission_type`, `data_scope_cd`) VALUES ('85b54322630f43a39296488a5e76ba16', 3, 'scope', '1006001');
INSERT IGNORE INTO `sys_role_menu` (`menu_id`, `role_id`, `permission_type`, `data_scope_cd`) VALUES ('ab1ac16c617d41979472ebe433c1f8e4', 4, 'menu', NULL);
INSERT IGNORE INTO `sys_role_menu` (`menu_id`, `role_id`, `permission_type`, `data_scope_cd`) VALUES ('85b54322630f43a39296488a5e76ba16', 4, 'menu', NULL);
INSERT IGNORE INTO `sys_role_menu` (`menu_id`, `role_id`, `permission_type`, `data_scope_cd`) VALUES ('cb3500315dba4c2d83e4d92edf36dff7', 4, 'menu', NULL);
INSERT IGNORE INTO `sys_role_menu` (`menu_id`, `role_id`, `permission_type`, `data_scope_cd`) VALUES ('7391f12ad51049c2b86d231d39708c71', 4, 'menu', NULL);
INSERT IGNORE INTO `sys_role_menu` (`menu_id`, `role_id`, `permission_type`, `data_scope_cd`) VALUES ('73d312f4fa8949ddba3d9807c0c56f00', 4, 'menu', NULL);
INSERT IGNORE INTO `sys_role_menu` (`menu_id`, `role_id`, `permission_type`, `data_scope_cd`) VALUES ('91ccb13b5c174583803a4c492a5dfdb6', 4, 'menu', NULL);
INSERT IGNORE INTO `sys_role_menu` (`menu_id`, `role_id`, `permission_type`, `data_scope_cd`) VALUES ('8061d8e79be744bf91b7b438f8e8e887', 4, 'menu', NULL);
INSERT IGNORE INTO `sys_role_menu` (`menu_id`, `role_id`, `permission_type`, `data_scope_cd`) VALUES ('85b54322630f43a39296488a5e76ba16', 4, 'scope', '1006002');
INSERT IGNORE INTO `sys_role_menu` (`menu_id`, `role_id`, `permission_type`, `data_scope_cd`) VALUES ('ab1ac16c617d41979472ebe433c1f8e4', 6, 'menu', NULL);
INSERT IGNORE INTO `sys_role_menu` (`menu_id`, `role_id`, `permission_type`, `data_scope_cd`) VALUES ('85b54322630f43a39296488a5e76ba16', 6, 'menu', NULL);
INSERT IGNORE INTO `sys_role_menu` (`menu_id`, `role_id`, `permission_type`, `data_scope_cd`) VALUES ('cb3500315dba4c2d83e4d92edf36dff7', 6, 'menu', NULL);
INSERT IGNORE INTO `sys_role_menu` (`menu_id`, `role_id`, `permission_type`, `data_scope_cd`) VALUES ('7391f12ad51049c2b86d231d39708c71', 6, 'menu', NULL);
INSERT IGNORE INTO `sys_role_menu` (`menu_id`, `role_id`, `permission_type`, `data_scope_cd`) VALUES ('73d312f4fa8949ddba3d9807c0c56f00', 6, 'menu', NULL);
INSERT IGNORE INTO `sys_role_menu` (`menu_id`, `role_id`, `permission_type`, `data_scope_cd`) VALUES ('91ccb13b5c174583803a4c492a5dfdb6', 6, 'menu', NULL);
INSERT IGNORE INTO `sys_role_menu` (`menu_id`, `role_id`, `permission_type`, `data_scope_cd`) VALUES ('8061d8e79be744bf91b7b438f8e8e887', 6, 'menu', NULL);
INSERT IGNORE INTO `sys_role_menu` (`menu_id`, `role_id`, `permission_type`, `data_scope_cd`) VALUES ('85b54322630f43a39296488a5e76ba16', 6, 'scope', '1006004');
INSERT IGNORE INTO `sys_role_menu` (`menu_id`, `role_id`, `permission_type`, `data_scope_cd`) VALUES ('ab1ac16c617d41979472ebe433c1f8e4', 5, 'menu', NULL);
INSERT IGNORE INTO `sys_role_menu` (`menu_id`, `role_id`, `permission_type`, `data_scope_cd`) VALUES ('85b54322630f43a39296488a5e76ba16', 5, 'menu', NULL);
INSERT IGNORE INTO `sys_role_menu` (`menu_id`, `role_id`, `permission_type`, `data_scope_cd`) VALUES ('cb3500315dba4c2d83e4d92edf36dff7', 5, 'menu', NULL);
INSERT IGNORE INTO `sys_role_menu` (`menu_id`, `role_id`, `permission_type`, `data_scope_cd`) VALUES ('7391f12ad51049c2b86d231d39708c71', 5, 'menu', NULL);
INSERT IGNORE INTO `sys_role_menu` (`menu_id`, `role_id`, `permission_type`, `data_scope_cd`) VALUES ('73d312f4fa8949ddba3d9807c0c56f00', 5, 'menu', NULL);
INSERT IGNORE INTO `sys_role_menu` (`menu_id`, `role_id`, `permission_type`, `data_scope_cd`) VALUES ('91ccb13b5c174583803a4c492a5dfdb6', 5, 'menu', NULL);
INSERT IGNORE INTO `sys_role_menu` (`menu_id`, `role_id`, `permission_type`, `data_scope_cd`) VALUES ('8061d8e79be744bf91b7b438f8e8e887', 5, 'menu', NULL);
INSERT IGNORE INTO `sys_role_menu` (`menu_id`, `role_id`, `permission_type`, `data_scope_cd`) VALUES ('85b54322630f43a39296488a5e76ba16', 5, 'scope', '1006003');
INSERT IGNORE INTO `sys_role_menu` (`menu_id`, `role_id`, `permission_type`, `data_scope_cd`) VALUES ('ab1ac16c617d41979472ebe433c1f8e4', 7, 'menu', NULL);
INSERT IGNORE INTO `sys_role_menu` (`menu_id`, `role_id`, `permission_type`, `data_scope_cd`) VALUES ('85b54322630f43a39296488a5e76ba16', 7, 'menu', NULL);
INSERT IGNORE INTO `sys_role_menu` (`menu_id`, `role_id`, `permission_type`, `data_scope_cd`) VALUES ('cb3500315dba4c2d83e4d92edf36dff7', 7, 'menu', NULL);
INSERT IGNORE INTO `sys_role_menu` (`menu_id`, `role_id`, `permission_type`, `data_scope_cd`) VALUES ('7391f12ad51049c2b86d231d39708c71', 7, 'menu', NULL);
INSERT IGNORE INTO `sys_role_menu` (`menu_id`, `role_id`, `permission_type`, `data_scope_cd`) VALUES ('73d312f4fa8949ddba3d9807c0c56f00', 7, 'menu', NULL);
INSERT IGNORE INTO `sys_role_menu` (`menu_id`, `role_id`, `permission_type`, `data_scope_cd`) VALUES ('91ccb13b5c174583803a4c492a5dfdb6', 7, 'menu', NULL);
INSERT IGNORE INTO `sys_role_menu` (`menu_id`, `role_id`, `permission_type`, `data_scope_cd`) VALUES ('8061d8e79be744bf91b7b438f8e8e887', 7, 'menu', NULL);
INSERT IGNORE INTO `sys_role_menu` (`menu_id`, `role_id`, `permission_type`, `data_scope_cd`) VALUES ('85b54322630f43a39296488a5e76ba16', 7, 'scope', '1006005');
INSERT IGNORE INTO `sys_role_menu` (`menu_id`, `role_id`, `permission_type`, `data_scope_cd`) VALUES ('d90946bc9ed54e598e3c4471dbd1f496', 2, 'menu', NULL);
INSERT IGNORE INTO `sys_role_menu` (`menu_id`, `role_id`, `permission_type`, `data_scope_cd`) VALUES ('7a4544831af34e69aa73148bf84b9924', 2, 'menu', NULL);
-- 为自定义角色分配数据权限
INSERT IGNORE INTO `sys_data_role_relation` (`role_id`, `relation_type_cd`, `relation_id`, `menu_id`) VALUES (7, '1007001', 3, '85b54322630f43a39296488a5e76ba16');
INSERT IGNORE INTO `sys_data_role_relation` (`role_id`, `relation_type_cd`, `relation_id`, `menu_id`) VALUES (7, '1007001', 5, '85b54322630f43a39296488a5e76ba16');
INSERT IGNORE INTO `sys_data_role_relation` (`role_id`, `relation_type_cd`, `relation_id`, `menu_id`) VALUES (7, '1007002', 15, '85b54322630f43a39296488a5e76ba16');
--changeset sz:20251106_2018
DELETE `sys_user_role` FROM `sys_user_role` JOIN `sys_user` on `sys_user_role`.`user_id` = `sys_user`.`id` where `sys_user`.`username` in ('user', 'test1', 'test2', 'test3', 'test4');
INSERT INTO `sys_user_role` (`role_id`, `user_id`) VALUES (3, 2);
INSERT INTO `sys_user_role` (`role_id`, `user_id`) VALUES (4, 3);
INSERT INTO `sys_user_role` (`role_id`, `user_id`) VALUES (5, 4);
INSERT INTO `sys_user_role` (`role_id`, `user_id`) VALUES (6, 5);
INSERT INTO `sys_user_role` (`role_id`, `user_id`) VALUES (7, 6);
-- --liquibase formatted sql
--
-- --changeset 升职哦sz:20251105_1934
-- DELETE FROM `sys_role` WHERE id = 3 and permissions = 'teacher_statics_menu';
-- -- 创建新的演示角色
-- INSERT IGNORE INTO `sys_role` (`id`, `role_name`, `remark`, `del_flag`, `create_time`, `update_time`, `create_id`, `update_id`, `is_lock`, `permissions`) VALUES (3, '教师统计-全部', '演示:数据权限-全部', 'F', '2024-05-10 21:53:15', '2025-11-05 13:39:50', NULL, 1, 'T', 'teacher_statics_menu_1006001');
-- INSERT IGNORE INTO `sys_role` (`id`, `role_name`, `remark`, `del_flag`, `create_time`, `update_time`, `create_id`, `update_id`, `is_lock`, `permissions`) VALUES (4, '教师统计-部门及以下', '演示:数据权限-部门及以下', 'F', '2025-11-05 11:24:40', '2025-11-05 13:39:45', 1, 1, 'T', 'teacher_statics_menu_1006002');
-- INSERT IGNORE INTO `sys_role` (`id`, `role_name`, `remark`, `del_flag`, `create_time`, `update_time`, `create_id`, `update_id`, `is_lock`, `permissions`) VALUES (5, '教师统计-仅本部', '演示:数据权限-仅本部', 'F', '2025-11-05 11:25:21', '2025-11-05 13:40:02', 1, 1, 'T', 'teacher_statics_menu_1006003');
-- INSERT IGNORE INTO `sys_role` (`id`, `role_name`, `remark`, `del_flag`, `create_time`, `update_time`, `create_id`, `update_id`, `is_lock`, `permissions`) VALUES (6, '教师统计-仅本人', '演示:数据权限-仅本人', 'F', '2025-11-05 13:39:19', '2025-11-05 13:40:08', 1, 1, 'T', 'teacher_statics_menu_1006004');
-- INSERT IGNORE INTO `sys_role` (`id`, `role_name`, `remark`, `del_flag`, `create_time`, `update_time`, `create_id`, `update_id`, `is_lock`, `permissions`) VALUES (7, '教师统计-自定义', '演示:数据权限-自定义', 'F', '2025-11-05 13:46:50', '2025-11-05 13:46:50', 1, 1, 'T', 'teacher_statics_menu_1006005');
-- -- 为新的角色分配菜单权
-- INSERT IGNORE INTO `sys_role_menu` (`menu_id`, `role_id`, `permission_type`, `data_scope_cd`) VALUES ('ab1ac16c617d41979472ebe433c1f8e4', 3, 'menu', NULL);
-- INSERT IGNORE INTO `sys_role_menu` (`menu_id`, `role_id`, `permission_type`, `data_scope_cd`) VALUES ('85b54322630f43a39296488a5e76ba16', 3, 'menu', NULL);
-- INSERT IGNORE INTO `sys_role_menu` (`menu_id`, `role_id`, `permission_type`, `data_scope_cd`) VALUES ('cb3500315dba4c2d83e4d92edf36dff7', 3, 'menu', NULL);
-- INSERT IGNORE INTO `sys_role_menu` (`menu_id`, `role_id`, `permission_type`, `data_scope_cd`) VALUES ('7391f12ad51049c2b86d231d39708c71', 3, 'menu', NULL);
-- INSERT IGNORE INTO `sys_role_menu` (`menu_id`, `role_id`, `permission_type`, `data_scope_cd`) VALUES ('73d312f4fa8949ddba3d9807c0c56f00', 3, 'menu', NULL);
-- INSERT IGNORE INTO `sys_role_menu` (`menu_id`, `role_id`, `permission_type`, `data_scope_cd`) VALUES ('91ccb13b5c174583803a4c492a5dfdb6', 3, 'menu', NULL);
-- INSERT IGNORE INTO `sys_role_menu` (`menu_id`, `role_id`, `permission_type`, `data_scope_cd`) VALUES ('8061d8e79be744bf91b7b438f8e8e887', 3, 'menu', NULL);
-- INSERT IGNORE INTO `sys_role_menu` (`menu_id`, `role_id`, `permission_type`, `data_scope_cd`) VALUES ('85b54322630f43a39296488a5e76ba16', 3, 'scope', '1006001');
-- INSERT IGNORE INTO `sys_role_menu` (`menu_id`, `role_id`, `permission_type`, `data_scope_cd`) VALUES ('ab1ac16c617d41979472ebe433c1f8e4', 4, 'menu', NULL);
-- INSERT IGNORE INTO `sys_role_menu` (`menu_id`, `role_id`, `permission_type`, `data_scope_cd`) VALUES ('85b54322630f43a39296488a5e76ba16', 4, 'menu', NULL);
-- INSERT IGNORE INTO `sys_role_menu` (`menu_id`, `role_id`, `permission_type`, `data_scope_cd`) VALUES ('cb3500315dba4c2d83e4d92edf36dff7', 4, 'menu', NULL);
-- INSERT IGNORE INTO `sys_role_menu` (`menu_id`, `role_id`, `permission_type`, `data_scope_cd`) VALUES ('7391f12ad51049c2b86d231d39708c71', 4, 'menu', NULL);
-- INSERT IGNORE INTO `sys_role_menu` (`menu_id`, `role_id`, `permission_type`, `data_scope_cd`) VALUES ('73d312f4fa8949ddba3d9807c0c56f00', 4, 'menu', NULL);
-- INSERT IGNORE INTO `sys_role_menu` (`menu_id`, `role_id`, `permission_type`, `data_scope_cd`) VALUES ('91ccb13b5c174583803a4c492a5dfdb6', 4, 'menu', NULL);
-- INSERT IGNORE INTO `sys_role_menu` (`menu_id`, `role_id`, `permission_type`, `data_scope_cd`) VALUES ('8061d8e79be744bf91b7b438f8e8e887', 4, 'menu', NULL);
-- INSERT IGNORE INTO `sys_role_menu` (`menu_id`, `role_id`, `permission_type`, `data_scope_cd`) VALUES ('85b54322630f43a39296488a5e76ba16', 4, 'scope', '1006002');
-- INSERT IGNORE INTO `sys_role_menu` (`menu_id`, `role_id`, `permission_type`, `data_scope_cd`) VALUES ('ab1ac16c617d41979472ebe433c1f8e4', 6, 'menu', NULL);
-- INSERT IGNORE INTO `sys_role_menu` (`menu_id`, `role_id`, `permission_type`, `data_scope_cd`) VALUES ('85b54322630f43a39296488a5e76ba16', 6, 'menu', NULL);
-- INSERT IGNORE INTO `sys_role_menu` (`menu_id`, `role_id`, `permission_type`, `data_scope_cd`) VALUES ('cb3500315dba4c2d83e4d92edf36dff7', 6, 'menu', NULL);
-- INSERT IGNORE INTO `sys_role_menu` (`menu_id`, `role_id`, `permission_type`, `data_scope_cd`) VALUES ('7391f12ad51049c2b86d231d39708c71', 6, 'menu', NULL);
-- INSERT IGNORE INTO `sys_role_menu` (`menu_id`, `role_id`, `permission_type`, `data_scope_cd`) VALUES ('73d312f4fa8949ddba3d9807c0c56f00', 6, 'menu', NULL);
-- INSERT IGNORE INTO `sys_role_menu` (`menu_id`, `role_id`, `permission_type`, `data_scope_cd`) VALUES ('91ccb13b5c174583803a4c492a5dfdb6', 6, 'menu', NULL);
-- INSERT IGNORE INTO `sys_role_menu` (`menu_id`, `role_id`, `permission_type`, `data_scope_cd`) VALUES ('8061d8e79be744bf91b7b438f8e8e887', 6, 'menu', NULL);
-- INSERT IGNORE INTO `sys_role_menu` (`menu_id`, `role_id`, `permission_type`, `data_scope_cd`) VALUES ('85b54322630f43a39296488a5e76ba16', 6, 'scope', '1006004');
-- INSERT IGNORE INTO `sys_role_menu` (`menu_id`, `role_id`, `permission_type`, `data_scope_cd`) VALUES ('ab1ac16c617d41979472ebe433c1f8e4', 5, 'menu', NULL);
-- INSERT IGNORE INTO `sys_role_menu` (`menu_id`, `role_id`, `permission_type`, `data_scope_cd`) VALUES ('85b54322630f43a39296488a5e76ba16', 5, 'menu', NULL);
-- INSERT IGNORE INTO `sys_role_menu` (`menu_id`, `role_id`, `permission_type`, `data_scope_cd`) VALUES ('cb3500315dba4c2d83e4d92edf36dff7', 5, 'menu', NULL);
-- INSERT IGNORE INTO `sys_role_menu` (`menu_id`, `role_id`, `permission_type`, `data_scope_cd`) VALUES ('7391f12ad51049c2b86d231d39708c71', 5, 'menu', NULL);
-- INSERT IGNORE INTO `sys_role_menu` (`menu_id`, `role_id`, `permission_type`, `data_scope_cd`) VALUES ('73d312f4fa8949ddba3d9807c0c56f00', 5, 'menu', NULL);
-- INSERT IGNORE INTO `sys_role_menu` (`menu_id`, `role_id`, `permission_type`, `data_scope_cd`) VALUES ('91ccb13b5c174583803a4c492a5dfdb6', 5, 'menu', NULL);
-- INSERT IGNORE INTO `sys_role_menu` (`menu_id`, `role_id`, `permission_type`, `data_scope_cd`) VALUES ('8061d8e79be744bf91b7b438f8e8e887', 5, 'menu', NULL);
-- INSERT IGNORE INTO `sys_role_menu` (`menu_id`, `role_id`, `permission_type`, `data_scope_cd`) VALUES ('85b54322630f43a39296488a5e76ba16', 5, 'scope', '1006003');
-- INSERT IGNORE INTO `sys_role_menu` (`menu_id`, `role_id`, `permission_type`, `data_scope_cd`) VALUES ('ab1ac16c617d41979472ebe433c1f8e4', 7, 'menu', NULL);
-- INSERT IGNORE INTO `sys_role_menu` (`menu_id`, `role_id`, `permission_type`, `data_scope_cd`) VALUES ('85b54322630f43a39296488a5e76ba16', 7, 'menu', NULL);
-- INSERT IGNORE INTO `sys_role_menu` (`menu_id`, `role_id`, `permission_type`, `data_scope_cd`) VALUES ('cb3500315dba4c2d83e4d92edf36dff7', 7, 'menu', NULL);
-- INSERT IGNORE INTO `sys_role_menu` (`menu_id`, `role_id`, `permission_type`, `data_scope_cd`) VALUES ('7391f12ad51049c2b86d231d39708c71', 7, 'menu', NULL);
-- INSERT IGNORE INTO `sys_role_menu` (`menu_id`, `role_id`, `permission_type`, `data_scope_cd`) VALUES ('73d312f4fa8949ddba3d9807c0c56f00', 7, 'menu', NULL);
-- INSERT IGNORE INTO `sys_role_menu` (`menu_id`, `role_id`, `permission_type`, `data_scope_cd`) VALUES ('91ccb13b5c174583803a4c492a5dfdb6', 7, 'menu', NULL);
-- INSERT IGNORE INTO `sys_role_menu` (`menu_id`, `role_id`, `permission_type`, `data_scope_cd`) VALUES ('8061d8e79be744bf91b7b438f8e8e887', 7, 'menu', NULL);
-- INSERT IGNORE INTO `sys_role_menu` (`menu_id`, `role_id`, `permission_type`, `data_scope_cd`) VALUES ('85b54322630f43a39296488a5e76ba16', 7, 'scope', '1006005');
-- INSERT IGNORE INTO `sys_role_menu` (`menu_id`, `role_id`, `permission_type`, `data_scope_cd`) VALUES ('d90946bc9ed54e598e3c4471dbd1f496', 2, 'menu', NULL);
-- INSERT IGNORE INTO `sys_role_menu` (`menu_id`, `role_id`, `permission_type`, `data_scope_cd`) VALUES ('7a4544831af34e69aa73148bf84b9924', 2, 'menu', NULL);
--
-- -- 为自定义角色分配数据权限
-- INSERT IGNORE INTO `sys_data_role_relation` (`role_id`, `relation_type_cd`, `relation_id`, `menu_id`) VALUES (7, '1007001', 3, '85b54322630f43a39296488a5e76ba16');
-- INSERT IGNORE INTO `sys_data_role_relation` (`role_id`, `relation_type_cd`, `relation_id`, `menu_id`) VALUES (7, '1007001', 5, '85b54322630f43a39296488a5e76ba16');
-- INSERT IGNORE INTO `sys_data_role_relation` (`role_id`, `relation_type_cd`, `relation_id`, `menu_id`) VALUES (7, '1007002', 15, '85b54322630f43a39296488a5e76ba16');
--
-- --changeset 升职哦sz:20251106_2018
-- DELETE `sys_user_role` FROM `sys_user_role` JOIN `sys_user` on `sys_user_role`.`user_id` = `sys_user`.`id` where `sys_user`.`username` in ('user', 'test1', 'test2', 'test3', 'test4');
-- INSERT INTO `sys_user_role` (`role_id`, `user_id`) VALUES (3, 2);
-- INSERT INTO `sys_user_role` (`role_id`, `user_id`) VALUES (4, 3);
-- INSERT INTO `sys_user_role` (`role_id`, `user_id`) VALUES (5, 4);
-- INSERT INTO `sys_user_role` (`role_id`, `user_id`) VALUES (6, 5);
-- INSERT INTO `sys_user_role` (`role_id`, `user_id`) VALUES (7, 6);

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

Loading…
Cancel
Save