This commit is contained in:
高雄 2025-07-24 08:41:52 +08:00
commit 748067961f
17 changed files with 261 additions and 11 deletions

View File

@ -31,7 +31,7 @@ public class HttpLogAspect {
/**
* 自定义切点
*/
@Pointcut("execution(* com.dite.*.controller.*.*(..)) ")
@Pointcut("execution(* com.dite.znpt.web..*(..)) ")
public void log() {
}

View File

@ -0,0 +1,78 @@
package com.dite.znpt.config;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.RuntimeUtil;
import com.dite.znpt.constant.Message;
import com.dite.znpt.exception.ServiceException;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
@Data
@Configuration
@ConfigurationProperties(prefix = "util")
public class ExtUtilConfig {
@ApiModelProperty("图片预处理工具路径")
private String imagePreTreatmentPath;
@ApiModelProperty("报告生成工具路径")
private String reportGeneratorPath;
@ApiModelProperty("报告生成工具模板路径")
private String reportGeneratorTemplatePath;
/**
* 参数 缩写 默认值 说明
* --input-dir 必需 输入图片目录路径
* --input-file 必需 输入的单图默认输出到输入值同一目录
* --output-dir 输入目录+"+调整" 输出目录路径
* --gamma 180 阴影检测阈值 (0-255)
* --threshold 253 高光检测阈值 (0-255)
* --config-file naming_config.json 命名规则配置文件路径
* --no-auto-bright 禁用 RAW文件禁用自动亮度调整
* --quiet 禁用 减少控制台输出
* --encoder vitl 深度模型编码器类型 (vits/vitb/vitl/vitg)
* --input-size 518 模型输入图像尺寸
* @param inputFile
* @param outputDir
* @return
*/
public String imagePreTreatment(String inputFile, String outputDir) {
boolean directory = FileUtil.isDirectory(inputFile);
try {
Process exec = RuntimeUtil.exec(imagePreTreatmentPath,
directory ? "--input-dir" : "--input-file", inputFile,
"--output-dir", outputDir
);
exec.waitFor();
return RuntimeUtil.getResult(exec);
} catch (InterruptedException e) {
throw new ServiceException(Message.UTIL_EXEC_ERROR + e.getMessage());
}
}
/**
* 功能描述报告生成器
* --turbine_id 指定要生成报告的机组ID
* --output_dir 指定生成报告的输出目录
* --template_dir 指定Word模板文件所在的目录
* @param turbineId 机组id
* @param outputDir 输出dir
* @return {@link String }
* @author cuizhibin
* @date 2025/07/17 14:08
**/
public String reportGenerator(String turbineId, String outputDir) {
try {
Process exec = RuntimeUtil.exec(reportGeneratorPath,
"--turbine_id", turbineId,
"--output_dir", outputDir,
"--template_dir", reportGeneratorTemplatePath
);
exec.waitFor();
return RuntimeUtil.getResult(exec);
} catch (InterruptedException e) {
throw new ServiceException(Message.UTIL_EXEC_ERROR + e.getMessage());
}
}
}

View File

@ -70,4 +70,6 @@ public class Message implements Serializable {
public static final String SUGGESTION_LEVEL_TYPE_FORBID_REPEAT = "存在缺陷级别为[{}]缺陷类型为[{}]的维修建议";
public static final String CHECK_SCHEME_ID_IS_NOT_EXIST = "检查方案id不存在";
public static final String INSPECTION_REPORT_ID_IS_NOT_EXIST = "检查报告id不存在";
public static final String UTIL_EXEC_ERROR = "工具执行出错:";
public static final String REPORT_GENERATOR_ERROR = "报告生成出错";
}

View File

@ -91,4 +91,8 @@ public class InspectionReportEntity extends AuditableEntity implements Serializa
@ApiModelProperty("报告审核时间")
@TableField("report_audit_time")
private LocalDateTime reportAuditTime;
@ApiModelProperty("报告状态")
@TableField("report_status")
private String reportStatus;
}

View File

@ -19,6 +19,9 @@ public class DefectListResp implements Serializable {
@ApiModelProperty("缺陷id")
private String defectId;
@ApiModelProperty("图片id")
private String imageId;
@ApiModelProperty("缺陷名称")
private String defectName;

View File

@ -26,4 +26,7 @@ public class ImageSimpleReq implements Serializable {
@ApiModelProperty(name = "图像路径", required = true)
private String imagePath;
@ApiModelProperty("影像类型")
private String imageType;
}

View File

@ -36,5 +36,8 @@ public class InspectionReportListReq implements Serializable {
@ApiModelProperty("委托单位")
private String client;
@ApiModelProperty("报告状态")
private String reportStatus;
}

View File

@ -87,4 +87,8 @@ public class InspectionReportReq implements Serializable {
@NotNull(message = "报告审核时间不能为空")
@ApiModelProperty("报告审核时间")
private LocalDate reportAuditTime;
@NotBlank(message = "报告状态不能为空")
@ApiModelProperty("报告状态")
private String reportStatus;
}

View File

@ -0,0 +1,51 @@
package com.dite.znpt.enums;
import cn.hutool.json.JSONObject;
import lombok.Getter;
import java.util.ArrayList;
import java.util.List;
/**
* @author Bear.G
* @date 2025/6/26/周四 10:49
* @description
*/
@Getter
public enum InspectionReportStatusEnum {
PENDING("PENDING","待审核"),
PUBLISH("PUBLISH","已发布");
private final String code;
private final String desc;
InspectionReportStatusEnum(String code, String desc){
this.code = code;
this.desc = desc;
}
public static InspectionReportStatusEnum getByCode(String code){
for (InspectionReportStatusEnum e : InspectionReportStatusEnum.values() ) {
if(e.code.equals(code)){
return e;
}
}
return null;
}
public static String getDescByCode(String code){
InspectionReportStatusEnum e = getByCode(code);
return null == e ? null : e.desc;
}
public static List<JSONObject> listAll(){
List<JSONObject> list = new ArrayList<>(InspectionReportStatusEnum.values().length);
for (InspectionReportStatusEnum e : InspectionReportStatusEnum.values() ) {
JSONObject jsonObject = new JSONObject();
jsonObject.set(e.code, e.desc);
list.add(jsonObject);
}
return list;
}
}

View File

@ -20,4 +20,22 @@ public interface InspectionReportService extends IService<InspectionReportEntity
InspectionReportResp detail(String reportId);
void save(InspectionReportReq req);
void update(String reportId, InspectionReportReq req);
/**
* 功能描述报告生成器
*
* @param turbineId 机组id
* @author cuizhibin
* @date 2025/07/17 10:49
**/
void reportGenerator(String turbineId);
/**
* 功能描述发布
*
* @param reportId 报告id
* @author cuizhibin
* @date 2025/07/17 21:25
**/
void publish(String reportId);
}

View File

@ -108,9 +108,12 @@ public class DefectServiceImpl extends ServiceImpl<DefectMapper, DefectEntity> i
@Transactional(rollbackFor = Exception.class)
@Override
public void save(String imageId, DefectReq req) {
if(null == imageService.getById(imageId)){
ImageEntity image = imageService.getById(imageId);
if(null == image){
throw new ServiceException(Message.IMAGE_ID_IS_NOT_EXIST);
}
image.setImageType(ImageTypeEnum.DEFECT.getCode());
imageService.updateById(image);
DefectEntity defectEntity = Converts.INSTANCE.toDefectEntity(req);
defectEntity.setImageId(imageId);
defectEntity.setLabelInfo(JSONUtil.toJsonStr(req.getMarkInfo()));
@ -128,6 +131,7 @@ public class DefectServiceImpl extends ServiceImpl<DefectMapper, DefectEntity> i
@Override
public List<DefectEntity> saveOutWorkDefect(List<OutWorkDefectReq> list) {
List<ImageSimpleReq> imageSimpleReqList = Converts.INSTANCE.toImageSimpleReq(list);
imageSimpleReqList.forEach(req -> req.setImageType(ImageTypeEnum.DEFECT.getCode()));
List<ImageEntity> imageEntityList = imageService.batchSaveByImageSimpleReq(imageSimpleReqList);
Map<String, ImageEntity> imageMap = imageEntityList.stream().collect(Collectors.toMap(k->k.getPartId().concat(StrUtil.COLON).concat(k.getImagePath()), Function.identity()));
List<DefectEntity> defectEntityList = new ArrayList<>();
@ -192,6 +196,8 @@ public class DefectServiceImpl extends ServiceImpl<DefectMapper, DefectEntity> i
if (Objects.isNull(image)) {
throw new ServiceException(Message.IMAGE_ID_IS_NOT_EXIST);
}
image.setImageType(ImageTypeEnum.DEFECT.getCode());
imageService.updateById(image);
FilePathEnum pathEnum = image.getImagePath().contains("temp") ? FilePathEnum.IMAGE_TEMP : FilePathEnum.IMAGE;
String inputPath = pathEnum.getFileAbsolutePath(image.getImagePath());
// 写入attach同层级文件夹下

View File

@ -1,22 +1,26 @@
package com.dite.znpt.service.impl;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.dite.znpt.config.ExtUtilConfig;
import com.dite.znpt.constant.Message;
import com.dite.znpt.converts.Converts;
import com.dite.znpt.domain.entity.*;
import com.dite.znpt.domain.vo.*;
import com.dite.znpt.enums.CheckMethodEnum;
import com.dite.znpt.enums.ProjectStatusEnum;
import com.dite.znpt.enums.*;
import com.dite.znpt.exception.ServiceException;
import com.dite.znpt.mapper.InspectionReportMapper;
import com.dite.znpt.service.*;
import com.dite.znpt.util.PageUtil;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
@ -27,6 +31,7 @@ import java.util.stream.Collectors;
* @description
*/
@Service
@RequiredArgsConstructor
public class InspectionReportServiceImpl extends ServiceImpl<InspectionReportMapper, InspectionReportEntity> implements InspectionReportService {
@Resource
@ -44,6 +49,8 @@ public class InspectionReportServiceImpl extends ServiceImpl<InspectionReportMap
@Resource
private UserService userService;
private final ExtUtilConfig extUtilConfig;
private final AttachInfoService attachInfoService;
@Override
public List<InspectionReportListResp> page(InspectionReportListReq req) {
@ -135,4 +142,60 @@ public class InspectionReportServiceImpl extends ServiceImpl<InspectionReportMap
}
return Converts.INSTANCE.toInspectionReportEntity(req);
}
/**
* 功能描述报告生成器
*
* @param turbineId 机组id
* @author cuizhibin
* @date 2025/07/17 10:49
**/
@Override
@Transactional(rollbackFor = Exception.class)
public void reportGenerator(String turbineId) {
TurbineEntity turbine = turbineService.getById(turbineId);
if (Objects.isNull(turbine)) {
throw new ServiceException(Message.TURBINE_ID_IS_NOT_EXIST);
}
String outputDir = FilePathEnum.ATTACH.getFileAbsolutePathPrefix().concat(AttachBusinessTypeEnum.REPORT.getCode()).concat(FileUtil.FILE_SEPARATOR)
.concat(turbineId).concat(FileUtil.FILE_SEPARATOR);
String output = extUtilConfig.reportGenerator(turbineId, outputDir);
log.debug(output);
List<String> list = FileUtil.listFileNames(outputDir);
if (CollUtil.isEmpty(list)) {
throw new ServiceException(Message.REPORT_GENERATOR_ERROR);
}
AttachInfoEntity attachInfo = new AttachInfoEntity();
attachInfo.setBusinessId(turbineId);
attachInfo.setAttachPath(FilePathEnum.ATTACH.getFileDownPath(outputDir + list.get(0)));
attachInfo.setBusinessType(AttachBusinessTypeEnum.REPORT.getCode());
attachInfoService.save(attachInfo);
ProjectEntity project = projectService.getById(turbine.getProjectId());
InspectionReportEntity inspectionReport = new InspectionReportEntity();
inspectionReport.setTitle(project.getProjectName() + turbine.getTurbineName());
inspectionReport.setProjectId(project.getProjectId());
inspectionReport.setTurbineId(turbineId);
inspectionReport.setReportWriteTime(LocalDateTime.now());
inspectionReport.setReportStatus(InspectionReportStatusEnum.PENDING.getCode());
baseMapper.insert(inspectionReport);
}
/**
* 功能描述发布
*
* @param reportId 报告id
* @author cuizhibin
* @date 2025/07/17 21:25
**/
@Override
public void publish(String reportId) {
InspectionReportEntity report = getById(reportId);
if (Objects.isNull(report)) {
throw new ServiceException(Message.REPORT_GENERATOR_ERROR);
}
report.setReportStatus(InspectionReportStatusEnum.PUBLISH.getCode());
report.setReportAuditor(StpUtil.getLoginIdAsString());
report.setReportAuditTime(LocalDateTime.now());
baseMapper.updateById(report);
}
}

View File

@ -5,7 +5,7 @@
<select id="queryBySelective" resultType="com.dite.znpt.domain.vo.DefectListResp">
SELECT
d.defect_id, d.defect_name, d.defect_code, p.part_name, d.defect_position, d.defect_type, d.defect_level, d.description, d.repair_idea
d.defect_id, d.defect_name, d.defect_code, p.part_name, d.defect_position, d.defect_type, d.defect_level, d.description, d.repair_idea, d.image_id
FROM defect d
LEFT JOIN image i ON d.image_id = i.image_id
LEFT JOIN image_collect ic ON ic.collect_id = i.collect_id

View File

@ -28,6 +28,9 @@
<if test = "req.client != null and req.client != ''">
AND p.client LIKE concat('%', #{req.client}, '%')
</if>
<if test="req.reportStatus != null and req.reportStatus != ''">
and ir.report_status like concat ('%', #{req.reportStatus}, '%')
</if>
</where>
</select>

View File

@ -61,7 +61,7 @@ public class DeployController {
// 1. 签名校验
if (!validSignature(body, signature)) {
throw new RuntimeException("签名错误");
return ResponseEntity.status(403).body("签名验证失败");
}
// 2. 启动部署流程
@ -75,9 +75,8 @@ public class DeployController {
try {
Mac mac = Mac.getInstance("HmacSHA256");
mac.init(new SecretKeySpec(webhookSecret.getBytes(StandardCharsets.UTF_8), "HmacSHA256"));
byte[] hash = mac.doFinal(body);
String computed = "sha256=" + bytesToHex(hash);
return computed.equalsIgnoreCase(sigHeader);
String computed = bytesToHex(mac.doFinal(body));
return computed.equalsIgnoreCase(sigHeader); // 不区分大小写
} catch (Exception e) {
return false;
}
@ -108,7 +107,7 @@ public class DeployController {
@ApiOperation(value = "查询自动部署日志", httpMethod = "GET")
@GetMapping("/deployment-log")
public ResponseEntity<String> getDeploymentLog(
@RequestParam(defaultValue = "20") int lines) {
@RequestParam(defaultValue = "100") int lines) {
try {
Path logFile = Path.of(buildDir, "deploy.log");
if (!Files.exists(logFile)) {

View File

@ -163,5 +163,11 @@ public class CommonController {
return Result.ok(CheckMethodEnum.listAll());
}
@ApiOperation(value = "查询报告状态", httpMethod = "GET")
@GetMapping("/list/report-status")
public Result<?> listReportStatus(){
return Result.ok(InspectionReportStatusEnum.listAll());
}
}

View File

@ -67,4 +67,11 @@ public class InspectionReportController {
inspectionReportService.removeById(reportId);
return Result.ok();
}
@ApiOperation(value = "发布项目机组报告", httpMethod = "POST")
@PutMapping("/publish/{reportId}")
public Result<Object> publish(@PathVariable String reportId) {
inspectionReportService.publish(reportId);
return Result.ok();
}
}