From f37b47065191b20ba038be70505f1134a377292f Mon Sep 17 00:00:00 2001 From: bounce5733 Date: Mon, 20 Oct 2025 15:43:21 +0800 Subject: [PATCH 1/6] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E6=89=80=E6=9C=89?= =?UTF-8?q?=E7=9A=84=E5=8F=98=E6=9B=B4=E8=AE=B0=E5=BD=95=E9=83=BD=E6=A0=B9?= =?UTF-8?q?=E6=8D=AEdocId=E8=8E=B7=E5=8F=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../torna/service/DocDiffRecordService.java | 23 ++++++++++--------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/server/server-service/src/main/java/cn/torna/service/DocDiffRecordService.java b/server/server-service/src/main/java/cn/torna/service/DocDiffRecordService.java index 25af52b4..280123d3 100644 --- a/server/server-service/src/main/java/cn/torna/service/DocDiffRecordService.java +++ b/server/server-service/src/main/java/cn/torna/service/DocDiffRecordService.java @@ -62,17 +62,18 @@ public class DocDiffRecordService extends BaseLambdaService listDocDiff(Long docId) { - DocInfo docInfo = docInfoService.getById(docId); - String version = docInfo.getVersion(); - List diffRecordList; - // 如果有版本号,只能看截止到当前版本的记录 - if (StringUtils.hasText(version) && !"-".equals(version)) { - diffRecordList = listByField(DocDiffRecord::getDocId, docId); - } else { - // 可以查看所有变更记录 - String docKey = docInfoService.getDocKey(docId); - diffRecordList = listByField(DocDiffRecord::getDocKey, docKey); - } +// DocInfo docInfo = docInfoService.getById(docId); +// String version = docInfo.getVersion(); +// List diffRecordList; +// // 如果有版本号,只能看截止到当前版本的记录 +// if (StringUtils.hasText(version) && !"-".equals(version)) { +// diffRecordList = listByField(DocDiffRecord::getDocId, docId); +// } else { +// // 可以查看所有变更记录 +// String docKey = docInfoService.getDocKey(docId); +// diffRecordList = listByField(DocDiffRecord::getDocKey, docKey); +// } + List diffRecordList = listByField(DocDiffRecord::getDocId, docId); if (CollectionUtils.isEmpty(diffRecordList)) { return Collections.emptyList(); } -- Gitee From 05a9acfe24c5e196d74040071d5dfe7292d80e3d Mon Sep 17 00:00:00 2001 From: bounce5733 Date: Mon, 20 Oct 2025 16:38:52 +0800 Subject: [PATCH 2/6] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E6=98=AF=E5=90=A6?= =?UTF-8?q?=E4=BF=9D=E5=AD=98=E6=89=80=E6=9C=89=E5=BF=AB=E7=85=A7=E9=85=8D?= =?UTF-8?q?=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/resources/META-INF/torna.properties | 2 ++ .../java/cn/torna/service/DocSnapshotService.java | 14 ++++++++++---- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/server/boot/src/main/resources/META-INF/torna.properties b/server/boot/src/main/resources/META-INF/torna.properties index b3f2cef1..f0bf68ff 100644 --- a/server/boot/src/main/resources/META-INF/torna.properties +++ b/server/boot/src/main/resources/META-INF/torna.properties @@ -73,6 +73,8 @@ torna.view-config.response-hidden-columns=required,maxLength # \u521D\u59CB\u6392\u5E8F\u503C torna.view-config.init-order=10000 torna.view-config.compose-show-debug=true +# \u662F\u5426\u4FDD\u5B58\u6240\u6709\u5FEB\u7167 +torna.snapshot.save.all=false # \u65E5\u5FD7\u7B49\u7EA7 diff --git a/server/server-service/src/main/java/cn/torna/service/DocSnapshotService.java b/server/server-service/src/main/java/cn/torna/service/DocSnapshotService.java index d2d93ef0..c861f54b 100644 --- a/server/server-service/src/main/java/cn/torna/service/DocSnapshotService.java +++ b/server/server-service/src/main/java/cn/torna/service/DocSnapshotService.java @@ -16,6 +16,7 @@ import com.gitee.fastmybatis.core.support.BaseLambdaService; import com.google.common.collect.Lists; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import org.springframework.util.StringUtils; @@ -32,6 +33,9 @@ import java.util.stream.Collectors; @Slf4j public class DocSnapshotService extends BaseLambdaService { + @Value("${torna.snapshot.save.all:false}") + private boolean saveAllSnapshot; + @Autowired private DocInfoService docInfoService; @@ -73,10 +77,12 @@ public class DocSnapshotService extends BaseLambdaService Date: Mon, 27 Oct 2025 16:06:22 +0800 Subject: [PATCH 3/6] =?UTF-8?q?=E5=8F=82=E6=95=B0=E6=AF=94=E5=AF=B9?= =?UTF-8?q?=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/cn/torna/api/open/DocApi.java | 82 ++++++-- .../java/cn/torna/dao/entity/DocInfoTmp.java | 42 ++++ .../cn/torna/dao/entity/DocParamDiff.java | 44 +++++ .../java/cn/torna/dao/entity/DocParamTmp.java | 45 +++++ .../cn/torna/dao/mapper/DocInfoTmpMapper.java | 11 ++ .../torna/dao/mapper/DocParamDiffMapper.java | 12 ++ .../torna/dao/mapper/DocParamTmpMapper.java | 11 ++ .../java/cn/torna/service/DocInfoService.java | 180 ++++++++++++++++++ .../cn/torna/service/DocInfoTmpService.java | 67 +++++++ .../cn/torna/service/DocParamTmpService.java | 49 +++++ .../cn/torna/service/dto/DocParamTmpDTO.java | 60 ++++++ .../web/controller/doc/DocController.java | 12 ++ 12 files changed, 596 insertions(+), 19 deletions(-) create mode 100755 server/server-dao/src/main/java/cn/torna/dao/entity/DocInfoTmp.java create mode 100644 server/server-dao/src/main/java/cn/torna/dao/entity/DocParamDiff.java create mode 100755 server/server-dao/src/main/java/cn/torna/dao/entity/DocParamTmp.java create mode 100755 server/server-dao/src/main/java/cn/torna/dao/mapper/DocInfoTmpMapper.java create mode 100755 server/server-dao/src/main/java/cn/torna/dao/mapper/DocParamDiffMapper.java create mode 100755 server/server-dao/src/main/java/cn/torna/dao/mapper/DocParamTmpMapper.java create mode 100644 server/server-service/src/main/java/cn/torna/service/DocInfoTmpService.java create mode 100644 server/server-service/src/main/java/cn/torna/service/DocParamTmpService.java create mode 100644 server/server-service/src/main/java/cn/torna/service/dto/DocParamTmpDTO.java diff --git a/server/server-api/src/main/java/cn/torna/api/open/DocApi.java b/server/server-api/src/main/java/cn/torna/api/open/DocApi.java index 1ae8aa28..a114d303 100644 --- a/server/server-api/src/main/java/cn/torna/api/open/DocApi.java +++ b/server/server-api/src/main/java/cn/torna/api/open/DocApi.java @@ -37,14 +37,7 @@ import cn.torna.dao.entity.DocParam; import cn.torna.dao.entity.Module; import cn.torna.dao.entity.Project; import cn.torna.manager.tx.TornaTransactionManager; -import cn.torna.service.DocDiffRecordService; -import cn.torna.service.DocInfoService; -import cn.torna.service.DocViewService; -import cn.torna.service.MockConfigService; -import cn.torna.service.ModuleConfigService; -import cn.torna.service.ModuleEnvironmentService; -import cn.torna.service.ProjectService; -import cn.torna.service.UserMessageService; +import cn.torna.service.*; import cn.torna.service.dto.DocFolderCreateDTO; import cn.torna.service.dto.DocInfoDTO; import cn.torna.service.dto.DocMeta; @@ -115,6 +108,9 @@ public class DocApi { @Autowired private DocInfoService docInfoService; + @Autowired + private DocInfoTmpService docInfoTmpService; + @Autowired private ModuleConfigService moduleConfigService; @@ -156,19 +152,25 @@ public class DocApi { if (Boolean.parseBoolean(isPrint) || isPrintContent(module.getId())) { log.info("【PUSH】推送内容:{}", JSON.toJSONString(param)); } - // 允许有相同的目录 - String allowSameFolder = EnvironmentKeys.TORNA_PUSH_ALLOW_SAME_FOLDER.getValue(); - if (Boolean.parseBoolean(allowSameFolder)) { - this.mergeSameFolder(param); + // 获取该模块是否开启监控 + boolean isMonitor = true; + if (isMonitor) { + ThreadPoolUtil.execute(() -> doPushTmp(param, context)); } else { - this.checkSameFolder(param); - } - String author = param.getAuthor(); - if (StringUtils.hasText(author)) { - ApiUser user = (ApiUser) context.getApiUser(); - user.setNickname(author); + // 允许有相同的目录 + String allowSameFolder = EnvironmentKeys.TORNA_PUSH_ALLOW_SAME_FOLDER.getValue(); + if (Boolean.parseBoolean(allowSameFolder)) { + this.mergeSameFolder(param); + } else { + this.checkSameFolder(param); + } + String author = param.getAuthor(); + if (StringUtils.hasText(author)) { + ApiUser user = (ApiUser) context.getApiUser(); + user.setNickname(author); + } + ThreadPoolUtil.execute(() -> doPush(param, context)); } - ThreadPoolUtil.execute(() -> doPush(param, context)); } private void checkSameFolder(DocPushParam param) { @@ -218,6 +220,31 @@ public class DocApi { param.setApis(new ArrayList<>(folderItems.keySet())); } + /** + * 保存api到临时表用于比对差异 + * + * @param param + * @param context + */ + private void doPushTmp(DocPushParam param, RequestContext context) { + Module module = context.getModule(); + ThreadLocal docPushItemParamThreadLocal = new ThreadLocal<>(); + synchronized (lock) { + tornaTransactionManager.execute(() -> { + // 处理文档 + for (DocPushItemParam detailPushParam : param.getApis()) { + docPushItemParamThreadLocal.set(detailPushParam); + this.saveDocItemTmp(detailPushParam, module.getId()); + } + return true; + }, e -> { + DocPushItemParam docPushItemParam = docPushItemParamThreadLocal.get(); + String paramInfo = JSON.toJSONString(docPushItemParam); + log.error("【PUSH_TMP】保存临时文档失败,模块名称:{},推送人:{},ip:{},token:{}, 文档信息:{}", module.getName(), param.getAuthor(), context.getIp(), context.getToken(), paramInfo, e); + }); + } + } + private void doPush(DocPushParam param, RequestContext context) { Module module = context.getModule(); long moduleId = module.getId(); @@ -353,6 +380,23 @@ public class DocApi { } } + public void saveDocItemTmp(DocPushItemParam param, long moduleId) { + if (Booleans.isTrue(param.getIsFolder())) { + List items = param.getItems(); + if (items != null) { + for (DocPushItemParam item : items) { + this.saveDocItemTmp(item, moduleId); + } + } + } else { + DocInfoDTO docInfoDTO = buildDocInfoDTO(param); + docInfoDTO.setType(DocTypeEnum.HTTP.getType()); + formatUrl(docInfoDTO); + docInfoDTO.setModuleId(moduleId); + docInfoTmpService.saveDocInfoTmp(docInfoDTO); + } + } + public void pushDocItem(DocPushItemParam param, RequestContext context, Long parentId, PushContext pushContext) { User user = context.getApiUser(); long moduleId = context.getModuleId(); diff --git a/server/server-dao/src/main/java/cn/torna/dao/entity/DocInfoTmp.java b/server/server-dao/src/main/java/cn/torna/dao/entity/DocInfoTmp.java new file mode 100755 index 00000000..161fdbee --- /dev/null +++ b/server/server-dao/src/main/java/cn/torna/dao/entity/DocInfoTmp.java @@ -0,0 +1,42 @@ +package cn.torna.dao.entity; + +import com.gitee.fastmybatis.annotation.Pk; +import com.gitee.fastmybatis.annotation.PkStrategy; +import com.gitee.fastmybatis.annotation.Table; +import lombok.Data; + +import java.time.LocalDateTime; + + +/** + * 表名:doc_info_tmp + * 备注:推送文档临时信息 + * + * @author jyh + */ +@Table(name = "doc_info_tmp", pk = @Pk(name = "id", strategy = PkStrategy.INCREMENT)) +@Data +public class DocInfoTmp { + + /** 数据库字段:id */ + private Long id; + + /** 唯一id,接口规则:md5(module_id:parent_id:url:http_method)。分类规则:md5(module_id:parent_id:name), 数据库字段:doc_key */ + private String docKey; + + /** 访问URL, 数据库字段:url */ + private String url; + + /** http方法, 数据库字段:http_method */ + private String httpMethod; + + /** contentType, 数据库字段:content_type */ + private String contentType; + + /** 模块id,module.id, 数据库字段:module_id */ + private Long moduleId; + + /** 数据库字段:gmt_create */ + private LocalDateTime gmtCreate; + +} diff --git a/server/server-dao/src/main/java/cn/torna/dao/entity/DocParamDiff.java b/server/server-dao/src/main/java/cn/torna/dao/entity/DocParamDiff.java new file mode 100644 index 00000000..6412573c --- /dev/null +++ b/server/server-dao/src/main/java/cn/torna/dao/entity/DocParamDiff.java @@ -0,0 +1,44 @@ +package cn.torna.dao.entity; + +import com.gitee.fastmybatis.annotation.Pk; +import com.gitee.fastmybatis.annotation.PkStrategy; +import com.gitee.fastmybatis.annotation.Table; +import lombok.Data; + +import java.time.LocalDateTime; + +/** + * 文档参数差异 + * + * @Author jyh + * @Date 2025/10/27 14:07 + * @Version 1.0 + **/ +@Table(name = "doc_param_diff", pk = @Pk(name = "id", strategy = PkStrategy.INCREMENT)) +@Data +public class DocParamDiff { + + /** 数据库字段:id */ + private Long id; + + /** 根据diff_type决定doc_param.id 或 doc_param_tmp.id */ + private Long paramId; + + /** doc_info.id, 数据库字段:doc_id */ + private Long docId; + + /** 0:path, 1:header, 2:请求参数,3:返回参数,4:错误码, 数据库字段:style */ + private Byte style; + + /** 差异类型: 1: 临时参数缺少字段,-1: 临时参数多出字段, 2: 名称一致,类型不一致 */ + private Byte diffType; + + /** 差异字段名称 */ + private String diffParamName; + + /** 差异字段类型 */ + private String diffParamType; + + /** 数据库字段:gmt_create */ + private LocalDateTime gmtCreate; +} diff --git a/server/server-dao/src/main/java/cn/torna/dao/entity/DocParamTmp.java b/server/server-dao/src/main/java/cn/torna/dao/entity/DocParamTmp.java new file mode 100755 index 00000000..cfd08ddd --- /dev/null +++ b/server/server-dao/src/main/java/cn/torna/dao/entity/DocParamTmp.java @@ -0,0 +1,45 @@ +package cn.torna.dao.entity; + +import com.gitee.fastmybatis.annotation.Pk; +import com.gitee.fastmybatis.annotation.PkStrategy; +import com.gitee.fastmybatis.annotation.Table; +import lombok.Data; + +import java.time.LocalDateTime; + + +/** + * 表名:doc_param_tmp + * 备注:文档参数临时表 + * + * @author jyh + */ +@Table(name = "doc_param_tmp", pk = @Pk(name = "id", strategy = PkStrategy.INCREMENT)) +@Data +public class DocParamTmp { + + /** 数据库字段:id */ + private Long id; + + /** 字段名称, 数据库字段:name */ + private String name; + + /** 字段类型, 数据库字段:type */ + private String type; + + /** doc_info.id, 数据库字段:doc_id */ + private Long docId; + + /** 数据库字段:parent_id */ + private Long parentId; + + /** 0:path, 1:header, 2:请求参数,3:返回参数,4:错误码, 数据库字段:style */ + private Byte style; + + /** 排序索引, 数据库字段:order_index */ + private Integer orderIndex; + + /** 数据库字段:gmt_create */ + private LocalDateTime gmtCreate; + +} \ No newline at end of file diff --git a/server/server-dao/src/main/java/cn/torna/dao/mapper/DocInfoTmpMapper.java b/server/server-dao/src/main/java/cn/torna/dao/mapper/DocInfoTmpMapper.java new file mode 100755 index 00000000..d0e658b4 --- /dev/null +++ b/server/server-dao/src/main/java/cn/torna/dao/mapper/DocInfoTmpMapper.java @@ -0,0 +1,11 @@ +package cn.torna.dao.mapper; + +import cn.torna.dao.entity.DocInfoTmp; +import com.gitee.fastmybatis.core.mapper.BaseMapper; + +/** + * @author jyh + */ +public interface DocInfoTmpMapper extends BaseMapper { + +} diff --git a/server/server-dao/src/main/java/cn/torna/dao/mapper/DocParamDiffMapper.java b/server/server-dao/src/main/java/cn/torna/dao/mapper/DocParamDiffMapper.java new file mode 100755 index 00000000..6c137b33 --- /dev/null +++ b/server/server-dao/src/main/java/cn/torna/dao/mapper/DocParamDiffMapper.java @@ -0,0 +1,12 @@ +package cn.torna.dao.mapper; + +import cn.torna.dao.entity.DocParamDiff; +import cn.torna.dao.entity.DocParamTmp; +import com.gitee.fastmybatis.core.mapper.BaseMapper; + +/** + * @author jyh + */ +public interface DocParamDiffMapper extends BaseMapper { + +} diff --git a/server/server-dao/src/main/java/cn/torna/dao/mapper/DocParamTmpMapper.java b/server/server-dao/src/main/java/cn/torna/dao/mapper/DocParamTmpMapper.java new file mode 100755 index 00000000..e95223f4 --- /dev/null +++ b/server/server-dao/src/main/java/cn/torna/dao/mapper/DocParamTmpMapper.java @@ -0,0 +1,11 @@ +package cn.torna.dao.mapper; + +import cn.torna.dao.entity.DocParamTmp; +import com.gitee.fastmybatis.core.mapper.BaseMapper; + +/** + * @author jyh + */ +public interface DocParamTmpMapper extends BaseMapper { + +} diff --git a/server/server-service/src/main/java/cn/torna/service/DocInfoService.java b/server/server-service/src/main/java/cn/torna/service/DocInfoService.java index 0a8040db..eb4da6a4 100755 --- a/server/server-service/src/main/java/cn/torna/service/DocInfoService.java +++ b/server/server-service/src/main/java/cn/torna/service/DocInfoService.java @@ -17,7 +17,10 @@ import cn.torna.common.util.IdGen; import cn.torna.common.util.Markdown2HtmlUtil; import cn.torna.common.util.TreeUtil; import cn.torna.dao.entity.DocInfo; +import cn.torna.dao.entity.DocInfoTmp; import cn.torna.dao.entity.DocParam; +import cn.torna.dao.entity.DocParamDiff; +import cn.torna.dao.entity.DocParamTmp; import cn.torna.dao.entity.EnumInfo; import cn.torna.dao.entity.Module; import cn.torna.dao.entity.ModuleEnvironment; @@ -25,6 +28,8 @@ import cn.torna.dao.entity.ModuleEnvironmentParam; import cn.torna.dao.entity.UserDingtalkInfo; import cn.torna.dao.entity.UserWeComInfo; import cn.torna.dao.mapper.DocInfoMapper; +import cn.torna.dao.mapper.DocInfoTmpMapper; +import cn.torna.dao.mapper.DocParamDiffMapper; import cn.torna.dao.mapper.UserDingtalkInfoMapper; import cn.torna.dao.mapper.UserWeComInfoMapper; import cn.torna.manager.doc.DataType; @@ -34,6 +39,7 @@ import cn.torna.service.dto.DocItemCreateDTO; import cn.torna.service.dto.DocListFormDTO; import cn.torna.service.dto.DocMeta; import cn.torna.service.dto.DocParamDTO; +import cn.torna.service.dto.DocParamTmpDTO; import cn.torna.service.dto.DocRefDTO; import cn.torna.service.dto.DubboInfoDTO; import cn.torna.service.dto.EnumInfoDTO; @@ -68,6 +74,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Objects; +import java.util.Set; import java.util.stream.Collectors; /** @@ -82,6 +89,9 @@ public class DocInfoService extends BaseLambdaService { @Autowired private DocParamService docParamService; + @Autowired + private DocParamTmpService docParamTmpService; + @Autowired private ModuleConfigService moduleConfigService; @@ -124,6 +134,12 @@ public class DocInfoService extends BaseLambdaService { @Autowired private MockConfigService mockConfigService; + @Autowired + private DocInfoTmpMapper docInfoTmpMapper; + + @Autowired + private DocParamDiffMapper docParamDiffMapper; + /** * 查询模块下的所有文档 @@ -992,4 +1008,168 @@ public class DocInfoService extends BaseLambdaService { return listByField(DocInfo::getParentId, parentId); } + /** + * 比对文档 + * + * @param moduleId + */ + public void compareDoc(Long moduleId) { + log.info("获取模块【{}】所有文档列表,并转换成doc_key为键值的map形式", moduleId); + List docInfoList = this.listDocDetail(moduleId); + Map docInfoMap = docInfoList.stream().collect(Collectors.toMap(item -> item.getDocKey(), + item -> item, (existing, replacement) -> existing)); + log.info("获取模块【{}】所有采集文档列表,并转换成doc_key为键值的map形式", moduleId); + List docInfoTmpList = docInfoTmpMapper.listByField(DocInfoTmp::getModuleId, moduleId); + Map docInfoTmpMap = docInfoTmpList.stream().collect(Collectors.toMap(item -> item.getDocKey(), + item -> item, (existing, replacement) -> existing)); + docInfoMap.forEach((docKey, docInfoDTO) -> { + if (docInfoTmpMap.get(docKey) != null) { + DocInfoTmp docInfoTmp = docInfoTmpMap.get(docKey); + log.info("开始比对文档【id:{},name:{},url:{},httpMethod:{}】", docInfoDTO.getId(), docInfoDTO.getName(), + docInfoDTO.getUrl(), docInfoDTO.getHttpMethod()); + + List params = docParamService.listByField(DocParam::getDocId, docInfoDTO.getId()); + params.sort(Comparator.comparing(DocParam::getOrderIndex)); + Map> paramsMap = params.stream() + .collect(Collectors.groupingBy(DocParam::getStyle)); + + List tmpParams = docParamTmpService.listByField(DocParamTmp::getDocId, docInfoTmp.getId()); + tmpParams.sort(Comparator.comparing(DocParamTmp::getOrderIndex)); + Map> tmpParamsMap = tmpParams.stream() + .collect(Collectors.groupingBy(DocParamTmp::getStyle)); + + paramsMap.forEach((paramType, docParams) -> { + if (tmpParamsMap.get(paramType) != null) { + log.info("开始比对参数类型【{}】", paramType); + List docParamDiffList = compareParam(docParams, tmpParamsMap.get(paramType)); + updateDocParamDiffByType(docParamDiffList, docInfoDTO.getId(), paramType); + } else { + log.info("采集文档【id:{},name:{},url:{},httpMethod:{}】参数类型【{}】不存在!", docInfoDTO.getId(), docInfoDTO.getName(), + docInfoDTO.getUrl(), docInfoDTO.getHttpMethod(), paramType); + } + }); + + } else { + log.info("采集文档【id:{},name:{},url:{},httpMethod:{}】不存在!", docInfoDTO.getId(), docInfoDTO.getName(), + docInfoDTO.getUrl(), docInfoDTO.getHttpMethod()); + } + }); + } + + /** + * 保存比对结果列表 + * + * @param docParamDiffList + * @param docId + * @param paramType + */ + private void updateDocParamDiffByType(List docParamDiffList, long docId, Byte paramType) { + Query query = Query.create().eq("doc_id", docId).eq("style", paramType); + docParamDiffMapper.deleteByQuery(query); + docParamDiffList.forEach(docParamDiff -> { + docParamDiff.setDocId(docId); + docParamDiff.setStyle(paramType); + docParamDiffMapper.save(docParamDiff); + }); + } + + /** + * 比对文档参数与采集文档参数差异 + * + * @param docParams + * @param tmpDocParams + * @return 比对结果列表 + */ + private List compareParam(List docParams, List tmpDocParams) { + List docParamDTOS = new ArrayList<>(); + for (DocParam item : docParams) { + DocParamTmpDTO docParamTmpDTO = new DocParamTmpDTO(); + CopyUtil.copyProperties(item, docParamTmpDTO); + docParamDTOS.add(docParamTmpDTO); + } + Map paramIdMap = new HashMap<>(); + Map paramTypeMap = new HashMap<>(); + this.convertTree(docParamDTOS, 0L, null, paramIdMap, paramTypeMap); + Set paramNameSet = paramIdMap.keySet(); + + List tmpDocParamDTOS = new ArrayList<>(); + for (DocParamTmp item : tmpDocParams) { + DocParamTmpDTO docParamTmpDTO = new DocParamTmpDTO(); + CopyUtil.copyProperties(item, docParamTmpDTO); + tmpDocParamDTOS.add(docParamTmpDTO); + } + Map tmpParamIdMap = new HashMap<>(); + Map tmpParamTypeMap = new HashMap<>(); + this.convertTree(tmpDocParamDTOS, 0L, null, tmpParamIdMap, tmpParamTypeMap); + Set tmpParamNameSet = tmpParamIdMap.keySet(); + + log.info("<-----------开始比对名称差异----------->"); + Map nameDiffMap = new HashMap<>(); // key: 参数全路径名(包含父路径,'-'号分隔), value: DocParamDiff + paramNameSet.forEach(paramName -> { + if (tmpParamNameSet.contains(paramName)) { // 包含字段 + if (!paramTypeMap.get(paramName).equals(tmpParamTypeMap.get(paramName))) { // 类型不一致 + DocParamDiff docParamDiff = new DocParamDiff(); + docParamDiff.setParamId(paramIdMap.get(paramName)); + docParamDiff.setDiffType((byte) 2); + docParamDiff.setDiffParamType(tmpParamTypeMap.get(paramName)); + nameDiffMap.put(paramName, docParamDiff); + } + } else { // 临时参数缺少字段 + DocParamDiff docParamDiff = new DocParamDiff(); + docParamDiff.setParamId(paramIdMap.get(paramName)); + docParamDiff.setDiffType((byte) 1); + nameDiffMap.put(paramName, docParamDiff); + } + }); + + tmpParamNameSet.forEach(tmpParamName -> { + if (!paramNameSet.contains(tmpParamName)) { // 临时参数多出字段 + DocParamDiff docParamDiff = new DocParamDiff(); + docParamDiff.setParamId(tmpParamIdMap.get(tmpParamName)); + docParamDiff.setDiffType((byte) -1); + docParamDiff.setDiffParamType(tmpParamTypeMap.get(tmpParamName)); + nameDiffMap.put(tmpParamName, docParamDiff); + } + }); + + // 组装比对结果 + List docParamDiffList = new ArrayList<>(); + nameDiffMap.forEach((paramName, docParamDiff) -> { + docParamDiff.setDiffParamName(paramName); + docParamDiffList.add(docParamDiff); + }); + return docParamDiffList; + } + + /** + * list转换成tree + * + * @param list + * @param parentId 当前父节点id + * @param parentName 拼接父节点名称 + * @param idMap 记录全路径名称->id映射 + * @param typeMap 记录全路径名称->类型映射 + * @return + */ + private List convertTree(List list, long parentId, String parentName, + Map idMap, Map typeMap) { + if (list == null) { + return Collections.emptyList(); + } + List temp = new ArrayList<>(); + for (int i = 0; i < list.size(); i++) { + DocParamTmpDTO item = list.get(i); + if (Objects.equals(item.getParentId(), parentId)) { + String fullPath = (parentId == 0L ? item.getName() : parentName + "-" + item.getName()); + List children = convertTree(list, item.getId(), fullPath, idMap, typeMap); + if (children.size() == 0) { + idMap.put(fullPath, item.getId()); + typeMap.put(fullPath, item.getType()); + } + item.setChildren(children); + temp.add(item); + } + } + return temp; + } } diff --git a/server/server-service/src/main/java/cn/torna/service/DocInfoTmpService.java b/server/server-service/src/main/java/cn/torna/service/DocInfoTmpService.java new file mode 100644 index 00000000..d82dce5f --- /dev/null +++ b/server/server-service/src/main/java/cn/torna/service/DocInfoTmpService.java @@ -0,0 +1,67 @@ +package cn.torna.service; + +import cn.torna.common.enums.ParamStyleEnum; +import cn.torna.common.util.CopyUtil; +import cn.torna.dao.entity.DocInfoTmp; +import cn.torna.dao.mapper.DocInfoTmpMapper; +import cn.torna.service.dto.DocInfoDTO; +import com.gitee.fastmybatis.core.support.BaseLambdaService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +/** + * @Author jyh + * @Date 2025/10/22 14:15 + * @Version 1.0 + **/ +@Service +@Slf4j +public class DocInfoTmpService extends BaseLambdaService { + + @Autowired + private DocParamTmpService docParamTmpService; + + /** + * 保存临时文档信息 + */ + @Transactional(rollbackFor = Exception.class) + public synchronized void saveDocInfoTmp(DocInfoDTO docInfoDTO) { + // 根据doc_key删除原先信息 + String docKey = docInfoDTO.buildDocKey(); + docInfoDTO.setDocKey(docKey); + DocInfoTmp docInfoTmp = this.getByField(DocInfoTmp::getDocKey, docKey); + if (docInfoTmp != null) { + this.deleteByColumn(DocInfoTmp::getDocKey, docKey); + docParamTmpService.deleteParamByDocId(docInfoTmp.getId()); + } + // 新增基本信息 + long docId = insertDocInfoTmp(docInfoDTO); + // 新增参数 + this.saveParams(docId, docInfoDTO); + } + + private void saveParams(long docId, DocInfoDTO docInfoDTO) { + docParamTmpService.saveParams(docId, docInfoDTO.getPathParams(), ParamStyleEnum.PATH); + docParamTmpService.saveParams(docId, docInfoDTO.getHeaderParams(), ParamStyleEnum.HEADER); + docParamTmpService.saveParams(docId, docInfoDTO.getQueryParams(), ParamStyleEnum.QUERY); + docParamTmpService.saveParams(docId, docInfoDTO.getRequestParams(), ParamStyleEnum.REQUEST); + docParamTmpService.saveParams(docId, docInfoDTO.getResponseParams(), ParamStyleEnum.RESPONSE); + docParamTmpService.saveParams(docId, docInfoDTO.getErrorCodeParams(), ParamStyleEnum.ERROR_CODE); + } + + private long insertDocInfoTmp(DocInfoDTO docInfoDTO) { + DocInfoTmp docInfoTmp = CopyUtil.copyBean(docInfoDTO, DocInfoTmp::new); + this.getMapper().saveIgnoreNull(docInfoTmp); + // 修复使用非MYSQL数据库插入数据id不返回问题 + if (docInfoTmp.getId() == null) { + DocInfoTmp one = getByField(DocInfoTmp::getDocKey, docInfoTmp.getDocKey()); + if (one != null) { + docInfoTmp.setId(one.getId()); + } + } + return docInfoTmp.getId(); + } + +} diff --git a/server/server-service/src/main/java/cn/torna/service/DocParamTmpService.java b/server/server-service/src/main/java/cn/torna/service/DocParamTmpService.java new file mode 100644 index 00000000..155376db --- /dev/null +++ b/server/server-service/src/main/java/cn/torna/service/DocParamTmpService.java @@ -0,0 +1,49 @@ +package cn.torna.service; + +import cn.torna.common.enums.ParamStyleEnum; +import cn.torna.dao.entity.DocParamTmp; +import cn.torna.dao.mapper.DocParamTmpMapper; +import cn.torna.service.dto.DocParamDTO; +import com.gitee.fastmybatis.core.support.BaseLambdaService; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + * @Author jyh + * @Date 2025/10/22 16:59 + * @Version 1.0 + **/ +@Service +public class DocParamTmpService extends BaseLambdaService { + + public void saveParams(long docId, List docParamDTOS, ParamStyleEnum paramStyleEnum) { + for (DocParamDTO docParamDTO : docParamDTOS) { + this.doSave(docParamDTO, 0L, docId, paramStyleEnum); + } + } + + public void deleteParamByDocId(long docId) { + this.deleteByColumn(DocParamTmp::getDocId, docId); + } + + private void doSave(DocParamDTO docParamDTO, long parentId, long docId, ParamStyleEnum paramStyleEnum) { + DocParamTmp docParamTmp = new DocParamTmp(); + docParamDTO.setParentId(parentId); + docParamTmp.setName(docParamDTO.getName()); + docParamTmp.setType(docParamDTO.getType()); + docParamTmp.setDocId(docId); + docParamTmp.setParentId(parentId); + docParamTmp.setStyle(paramStyleEnum.getStyle()); + docParamTmp.setOrderIndex(docParamDTO.getOrderIndex()); + this.save(docParamTmp); + + List children = docParamDTO.getChildren(); + if (children != null) { + Long pid = docParamTmp.getId(); + for (DocParamDTO child : children) { + this.doSave(child, pid, docId, paramStyleEnum); + } + } + } +} diff --git a/server/server-service/src/main/java/cn/torna/service/dto/DocParamTmpDTO.java b/server/server-service/src/main/java/cn/torna/service/dto/DocParamTmpDTO.java new file mode 100644 index 00000000..442a30a2 --- /dev/null +++ b/server/server-service/src/main/java/cn/torna/service/dto/DocParamTmpDTO.java @@ -0,0 +1,60 @@ +package cn.torna.service.dto; + +import cn.torna.common.annotation.Diff; +import cn.torna.common.bean.TreeAware; +import cn.torna.common.enums.PositionType; +import cn.torna.common.support.IdCodec; +import com.alibaba.fastjson.annotation.JSONField; +import lombok.Data; + +import java.time.LocalDateTime; +import java.util.List; + +/** + * @Author jiangyh + * @Date 2025/10/24 14:53 + * @Version 1.0 + **/ +@Data +public class DocParamTmpDTO implements TreeAware { + + @JSONField(serializeUsing = IdCodec.class, deserializeUsing = IdCodec.class) + private Long id; + + /** + * 字段名称, 数据库字段:name + */ + @Diff(positionType = PositionType.PARAM_NAME) + private String name; + + /** + * 字段类型, 数据库字段:type + */ + @Diff(positionType = PositionType.PARAM_TYPE) + private String type; + + /** + * doc_info.id, 数据库字段:doc_id + */ + @JSONField(serializeUsing = IdCodec.class, deserializeUsing = IdCodec.class) + private Long docId; + + /** + * 父节点, 数据库字段:parent_id + */ + @JSONField(serializeUsing = IdCodec.class, deserializeUsing = IdCodec.class) + private Long parentId; + + /** + * 0:header, 1:请求参数,2:返回参数,3:错误码, 数据库字段:style + */ + private Byte style; + + /** + * 数据库字段:gmt_create + */ + private LocalDateTime gmtCreate; + + private List children; + +} diff --git a/server/server-web/src/main/java/cn/torna/web/controller/doc/DocController.java b/server/server-web/src/main/java/cn/torna/web/controller/doc/DocController.java index 18496c10..1d3f57f1 100644 --- a/server/server-web/src/main/java/cn/torna/web/controller/doc/DocController.java +++ b/server/server-web/src/main/java/cn/torna/web/controller/doc/DocController.java @@ -68,6 +68,18 @@ public class DocController { @Autowired private ModuleEnvironmentService moduleEnvironmentService; + /** + * 比对文档 + * + * @param moduleId + * @return 比对结果 + */ + @GetMapping("compare") + public Result compareDoc(@HashId Long moduleId) { + docInfoService.compareDoc(moduleId); + return Result.ok(); + } + /** * 获取项目文档目录,可用于文档菜单 * -- Gitee From a65901e5766c2969da0f54b4b1cda41356c0bc4e Mon Sep 17 00:00:00 2001 From: bounce5733 Date: Tue, 28 Oct 2025 15:40:06 +0800 Subject: [PATCH 4/6] =?UTF-8?q?=E6=96=87=E6=A1=A3=E5=8F=82=E6=95=B0?= =?UTF-8?q?=E6=AF=94=E5=AF=B9=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- front/src/utils/i18n/languages/en-us.js | 7 +- front/src/utils/i18n/languages/zh-cn.js | 7 +- .../ModuleSetting/ModSetting/index.vue | 70 ++++++++++++++++ .../src/views/project/ModuleSetting/index.vue | 6 +- front/src/views/view/index.vue | 8 +- .../main/java/cn/torna/api/open/DocApi.java | 26 +++--- .../{DocInfoTmp.java => DocInfoPush.java} | 11 ++- .../{DocParamTmp.java => DocParamPush.java} | 8 +- ...oTmpMapper.java => DocInfoPushMapper.java} | 4 +- .../torna/dao/mapper/DocParamDiffMapper.java | 1 - ...TmpMapper.java => DocParamPushMapper.java} | 4 +- ...mpService.java => DocInfoPushService.java} | 48 +++++------ .../java/cn/torna/service/DocInfoService.java | 79 ++++++++++--------- ...pService.java => DocParamPushService.java} | 26 +++--- .../java/cn/torna/service/ScheduleTask.java | 38 ++++++++- 15 files changed, 238 insertions(+), 105 deletions(-) create mode 100644 front/src/views/project/ModuleSetting/ModSetting/index.vue rename server/server-dao/src/main/java/cn/torna/dao/entity/{DocInfoTmp.java => DocInfoPush.java} (78%) rename server/server-dao/src/main/java/cn/torna/dao/entity/{DocParamTmp.java => DocParamPush.java} (83%) rename server/server-dao/src/main/java/cn/torna/dao/mapper/{DocInfoTmpMapper.java => DocInfoPushMapper.java} (50%) rename server/server-dao/src/main/java/cn/torna/dao/mapper/{DocParamTmpMapper.java => DocParamPushMapper.java} (49%) rename server/server-service/src/main/java/cn/torna/service/{DocInfoTmpService.java => DocInfoPushService.java} (38%) rename server/server-service/src/main/java/cn/torna/service/{DocParamTmpService.java => DocParamPushService.java} (59%) diff --git a/front/src/utils/i18n/languages/en-us.js b/front/src/utils/i18n/languages/en-us.js index 569be7a2..b9d6def9 100644 --- a/front/src/utils/i18n/languages/en-us.js +++ b/front/src/utils/i18n/languages/en-us.js @@ -562,6 +562,10 @@ export default { 'weComWebhookUrlPlacehoder': 'Input full url with token parameter', 'weComWebhookUrlTip': 'Push message to weCom group when doc is changed' }, + ModSetting: { + 'isMonitorSetting': 'Is Monitor', + 'isMonitorSettingTip': 'When monitoring is enabled, data will be pushed to the document push table for parameter difference comparison. otherwise, the registration document will be updated' + }, UserInfo: { 'bindDingDingTip': 'Use DingDing app scan the QR to bind account' }, @@ -569,7 +573,8 @@ export default { 'weComSetting': 'WeCom Setting', 'dingdingSetting': 'DingTalk Setting', 'swaggerSetting': 'Swagger Setting', - 'meterSphereSetting': 'MeterSphere Setting' + 'meterSphereSetting': 'MeterSphere Setting', + 'modSetting': 'Base Setting' }, DocChangelog: { confirmRestore: 'Restore this version?' diff --git a/front/src/utils/i18n/languages/zh-cn.js b/front/src/utils/i18n/languages/zh-cn.js index 05d9f5d4..5336855d 100644 --- a/front/src/utils/i18n/languages/zh-cn.js +++ b/front/src/utils/i18n/languages/zh-cn.js @@ -565,6 +565,10 @@ export default { 'weComWebhookUrlPlacehoder': '输入完整带token参数的url', 'weComWebhookUrlTip': '当文档变更时推送消息到企业微信群。' }, + ModSetting: { + 'isMonitorSetting': '是否监控', + 'isMonitorSettingTip': '开启监控则推送数据入文档推送表,用于比对参数差异。否则更新登记文档' + }, UserInfo: { 'bindDingDingTip': '使用钉钉App扫一扫进行账号绑定' }, @@ -572,7 +576,8 @@ export default { 'weComSetting': '企业微信配置', 'dingdingSetting': '钉钉配置', 'swaggerSetting': 'Swagger设置', - 'meterSphereSetting': 'MeterSphere设置' + 'meterSphereSetting': 'MeterSphere设置', + 'modSetting': '基础配置' }, DocChangelog: { confirmRestore: '确认还原到此版本吗?' diff --git a/front/src/views/project/ModuleSetting/ModSetting/index.vue b/front/src/views/project/ModuleSetting/ModSetting/index.vue new file mode 100644 index 00000000..226f8f28 --- /dev/null +++ b/front/src/views/project/ModuleSetting/ModSetting/index.vue @@ -0,0 +1,70 @@ + + diff --git a/front/src/views/project/ModuleSetting/index.vue b/front/src/views/project/ModuleSetting/index.vue index 5296fae8..160eae39 100644 --- a/front/src/views/project/ModuleSetting/index.vue +++ b/front/src/views/project/ModuleSetting/index.vue @@ -31,6 +31,9 @@ + + + @@ -42,10 +45,11 @@ import PopoverUpdate from '@/components/PopoverUpdate' import SwaggerSetting from '@/components/ModuleSetting/SwaggerSetting' import MeterSphereSetting from './MeterSphereSetting' import EnvSetting from './EnvSetting' +import ModSetting from './ModSetting' export default { name: 'ModuleSetting', - components: { MeterSphereSetting, WeComSetting, DingDingSetting, PopoverUpdate, SwaggerSetting, EnvSetting }, + components: { MeterSphereSetting, WeComSetting, DingDingSetting, PopoverUpdate, SwaggerSetting, EnvSetting, ModSetting }, props: { projectId: { type: String, diff --git a/front/src/views/view/index.vue b/front/src/views/view/index.vue index 27f716f9..0b215b71 100644 --- a/front/src/views/view/index.vue +++ b/front/src/views/view/index.vue @@ -2,21 +2,21 @@
- {{ $t('apiInfo') }} + {{ $t('apiInfo') }} - {{ $t('debugApi') }} + {{ $t('debugApi') }} - Mock + Mock - {{ $t('apiInfo') }} + {{ $t('apiInfo') }} diff --git a/server/server-api/src/main/java/cn/torna/api/open/DocApi.java b/server/server-api/src/main/java/cn/torna/api/open/DocApi.java index a114d303..bad845dc 100644 --- a/server/server-api/src/main/java/cn/torna/api/open/DocApi.java +++ b/server/server-api/src/main/java/cn/torna/api/open/DocApi.java @@ -109,7 +109,7 @@ public class DocApi { private DocInfoService docInfoService; @Autowired - private DocInfoTmpService docInfoTmpService; + private DocInfoPushService docInfoPushService; @Autowired private ModuleConfigService moduleConfigService; @@ -153,10 +153,13 @@ public class DocApi { log.info("【PUSH】推送内容:{}", JSON.toJSONString(param)); } // 获取该模块是否开启监控 - boolean isMonitor = true; + boolean isMonitor = moduleConfigService.getCommonConfigValue(module.getId(), "isMonitor", "0") + .equals("0") ? false : true; if (isMonitor) { - ThreadPoolUtil.execute(() -> doPushTmp(param, context)); + log.info("===========开始更新推送文档信息==========="); + ThreadPoolUtil.execute(() -> doMonitorPush(param, context)); } else { + log.info("===========开始更新平台文档信息==========="); // 允许有相同的目录 String allowSameFolder = EnvironmentKeys.TORNA_PUSH_ALLOW_SAME_FOLDER.getValue(); if (Boolean.parseBoolean(allowSameFolder)) { @@ -221,12 +224,12 @@ public class DocApi { } /** - * 保存api到临时表用于比对差异 + * 监控比对推送 * * @param param * @param context */ - private void doPushTmp(DocPushParam param, RequestContext context) { + private void doMonitorPush(DocPushParam param, RequestContext context) { Module module = context.getModule(); ThreadLocal docPushItemParamThreadLocal = new ThreadLocal<>(); synchronized (lock) { @@ -234,13 +237,16 @@ public class DocApi { // 处理文档 for (DocPushItemParam detailPushParam : param.getApis()) { docPushItemParamThreadLocal.set(detailPushParam); - this.saveDocItemTmp(detailPushParam, module.getId()); + this.saveDocItemPush(detailPushParam, module.getId()); } + log.info("完成模块【{}】推送文档更新,更新比对状态缓存", module.getName()); + ScheduleTask.MODULE_COMPARE_STATUS_CACHE.put(module.getId(), true); return true; }, e -> { DocPushItemParam docPushItemParam = docPushItemParamThreadLocal.get(); String paramInfo = JSON.toJSONString(docPushItemParam); - log.error("【PUSH_TMP】保存临时文档失败,模块名称:{},推送人:{},ip:{},token:{}, 文档信息:{}", module.getName(), param.getAuthor(), context.getIp(), context.getToken(), paramInfo, e); + log.error("【PUSH_DOC】保存推送文档失败,模块名称:{},推送人:{},ip:{},token:{}, 文档信息:{}", module.getName(), + param.getAuthor(), context.getIp(), context.getToken(), paramInfo, e); }); } } @@ -380,12 +386,12 @@ public class DocApi { } } - public void saveDocItemTmp(DocPushItemParam param, long moduleId) { + public void saveDocItemPush(DocPushItemParam param, long moduleId) { if (Booleans.isTrue(param.getIsFolder())) { List items = param.getItems(); if (items != null) { for (DocPushItemParam item : items) { - this.saveDocItemTmp(item, moduleId); + this.saveDocItemPush(item, moduleId); } } } else { @@ -393,7 +399,7 @@ public class DocApi { docInfoDTO.setType(DocTypeEnum.HTTP.getType()); formatUrl(docInfoDTO); docInfoDTO.setModuleId(moduleId); - docInfoTmpService.saveDocInfoTmp(docInfoDTO); + docInfoPushService.saveDocInfo(docInfoDTO); } } diff --git a/server/server-dao/src/main/java/cn/torna/dao/entity/DocInfoTmp.java b/server/server-dao/src/main/java/cn/torna/dao/entity/DocInfoPush.java similarity index 78% rename from server/server-dao/src/main/java/cn/torna/dao/entity/DocInfoTmp.java rename to server/server-dao/src/main/java/cn/torna/dao/entity/DocInfoPush.java index 161fdbee..dc4fd751 100755 --- a/server/server-dao/src/main/java/cn/torna/dao/entity/DocInfoTmp.java +++ b/server/server-dao/src/main/java/cn/torna/dao/entity/DocInfoPush.java @@ -9,14 +9,14 @@ import java.time.LocalDateTime; /** - * 表名:doc_info_tmp - * 备注:推送文档临时信息 + * 表名:doc_info_push + * 备注:文档推送信息 * * @author jyh */ -@Table(name = "doc_info_tmp", pk = @Pk(name = "id", strategy = PkStrategy.INCREMENT)) +@Table(name = "doc_info_push", pk = @Pk(name = "id", strategy = PkStrategy.INCREMENT)) @Data -public class DocInfoTmp { +public class DocInfoPush { /** 数据库字段:id */ private Long id; @@ -36,6 +36,9 @@ public class DocInfoTmp { /** 模块id,module.id, 数据库字段:module_id */ private Long moduleId; + /** 是否比对 1:已经比对,0:未比对 */ + private Byte isCompare; + /** 数据库字段:gmt_create */ private LocalDateTime gmtCreate; diff --git a/server/server-dao/src/main/java/cn/torna/dao/entity/DocParamTmp.java b/server/server-dao/src/main/java/cn/torna/dao/entity/DocParamPush.java similarity index 83% rename from server/server-dao/src/main/java/cn/torna/dao/entity/DocParamTmp.java rename to server/server-dao/src/main/java/cn/torna/dao/entity/DocParamPush.java index cfd08ddd..ccca732a 100755 --- a/server/server-dao/src/main/java/cn/torna/dao/entity/DocParamTmp.java +++ b/server/server-dao/src/main/java/cn/torna/dao/entity/DocParamPush.java @@ -9,14 +9,14 @@ import java.time.LocalDateTime; /** - * 表名:doc_param_tmp - * 备注:文档参数临时表 + * 表名:doc_param_push + * 备注:文档参数推送表 * * @author jyh */ -@Table(name = "doc_param_tmp", pk = @Pk(name = "id", strategy = PkStrategy.INCREMENT)) +@Table(name = "doc_param_push", pk = @Pk(name = "id", strategy = PkStrategy.INCREMENT)) @Data -public class DocParamTmp { +public class DocParamPush { /** 数据库字段:id */ private Long id; diff --git a/server/server-dao/src/main/java/cn/torna/dao/mapper/DocInfoTmpMapper.java b/server/server-dao/src/main/java/cn/torna/dao/mapper/DocInfoPushMapper.java similarity index 50% rename from server/server-dao/src/main/java/cn/torna/dao/mapper/DocInfoTmpMapper.java rename to server/server-dao/src/main/java/cn/torna/dao/mapper/DocInfoPushMapper.java index d0e658b4..e4de8e18 100755 --- a/server/server-dao/src/main/java/cn/torna/dao/mapper/DocInfoTmpMapper.java +++ b/server/server-dao/src/main/java/cn/torna/dao/mapper/DocInfoPushMapper.java @@ -1,11 +1,11 @@ package cn.torna.dao.mapper; -import cn.torna.dao.entity.DocInfoTmp; +import cn.torna.dao.entity.DocInfoPush; import com.gitee.fastmybatis.core.mapper.BaseMapper; /** * @author jyh */ -public interface DocInfoTmpMapper extends BaseMapper { +public interface DocInfoPushMapper extends BaseMapper { } diff --git a/server/server-dao/src/main/java/cn/torna/dao/mapper/DocParamDiffMapper.java b/server/server-dao/src/main/java/cn/torna/dao/mapper/DocParamDiffMapper.java index 6c137b33..3b6b5201 100755 --- a/server/server-dao/src/main/java/cn/torna/dao/mapper/DocParamDiffMapper.java +++ b/server/server-dao/src/main/java/cn/torna/dao/mapper/DocParamDiffMapper.java @@ -1,7 +1,6 @@ package cn.torna.dao.mapper; import cn.torna.dao.entity.DocParamDiff; -import cn.torna.dao.entity.DocParamTmp; import com.gitee.fastmybatis.core.mapper.BaseMapper; /** diff --git a/server/server-dao/src/main/java/cn/torna/dao/mapper/DocParamTmpMapper.java b/server/server-dao/src/main/java/cn/torna/dao/mapper/DocParamPushMapper.java similarity index 49% rename from server/server-dao/src/main/java/cn/torna/dao/mapper/DocParamTmpMapper.java rename to server/server-dao/src/main/java/cn/torna/dao/mapper/DocParamPushMapper.java index e95223f4..4179ad88 100755 --- a/server/server-dao/src/main/java/cn/torna/dao/mapper/DocParamTmpMapper.java +++ b/server/server-dao/src/main/java/cn/torna/dao/mapper/DocParamPushMapper.java @@ -1,11 +1,11 @@ package cn.torna.dao.mapper; -import cn.torna.dao.entity.DocParamTmp; +import cn.torna.dao.entity.DocParamPush; import com.gitee.fastmybatis.core.mapper.BaseMapper; /** * @author jyh */ -public interface DocParamTmpMapper extends BaseMapper { +public interface DocParamPushMapper extends BaseMapper { } diff --git a/server/server-service/src/main/java/cn/torna/service/DocInfoTmpService.java b/server/server-service/src/main/java/cn/torna/service/DocInfoPushService.java similarity index 38% rename from server/server-service/src/main/java/cn/torna/service/DocInfoTmpService.java rename to server/server-service/src/main/java/cn/torna/service/DocInfoPushService.java index d82dce5f..e1262fb1 100644 --- a/server/server-service/src/main/java/cn/torna/service/DocInfoTmpService.java +++ b/server/server-service/src/main/java/cn/torna/service/DocInfoPushService.java @@ -2,8 +2,8 @@ package cn.torna.service; import cn.torna.common.enums.ParamStyleEnum; import cn.torna.common.util.CopyUtil; -import cn.torna.dao.entity.DocInfoTmp; -import cn.torna.dao.mapper.DocInfoTmpMapper; +import cn.torna.dao.entity.DocInfoPush; +import cn.torna.dao.mapper.DocInfoPushMapper; import cn.torna.service.dto.DocInfoDTO; import com.gitee.fastmybatis.core.support.BaseLambdaService; import lombok.extern.slf4j.Slf4j; @@ -18,50 +18,50 @@ import org.springframework.transaction.annotation.Transactional; **/ @Service @Slf4j -public class DocInfoTmpService extends BaseLambdaService { +public class DocInfoPushService extends BaseLambdaService { @Autowired - private DocParamTmpService docParamTmpService; + private DocParamPushService docParamPushService; /** - * 保存临时文档信息 + * 保存推送文档信息 */ @Transactional(rollbackFor = Exception.class) - public synchronized void saveDocInfoTmp(DocInfoDTO docInfoDTO) { + public synchronized void saveDocInfo(DocInfoDTO docInfoDTO) { // 根据doc_key删除原先信息 String docKey = docInfoDTO.buildDocKey(); docInfoDTO.setDocKey(docKey); - DocInfoTmp docInfoTmp = this.getByField(DocInfoTmp::getDocKey, docKey); - if (docInfoTmp != null) { - this.deleteByColumn(DocInfoTmp::getDocKey, docKey); - docParamTmpService.deleteParamByDocId(docInfoTmp.getId()); + DocInfoPush docInfoPush = this.getByField(DocInfoPush::getDocKey, docKey); + if (docInfoPush != null) { + this.deleteByColumn(DocInfoPush::getDocKey, docKey); + docParamPushService.deleteParamByDocId(docInfoPush.getId()); } // 新增基本信息 - long docId = insertDocInfoTmp(docInfoDTO); + long docId = insertDocInfoPush(docInfoDTO); // 新增参数 this.saveParams(docId, docInfoDTO); } private void saveParams(long docId, DocInfoDTO docInfoDTO) { - docParamTmpService.saveParams(docId, docInfoDTO.getPathParams(), ParamStyleEnum.PATH); - docParamTmpService.saveParams(docId, docInfoDTO.getHeaderParams(), ParamStyleEnum.HEADER); - docParamTmpService.saveParams(docId, docInfoDTO.getQueryParams(), ParamStyleEnum.QUERY); - docParamTmpService.saveParams(docId, docInfoDTO.getRequestParams(), ParamStyleEnum.REQUEST); - docParamTmpService.saveParams(docId, docInfoDTO.getResponseParams(), ParamStyleEnum.RESPONSE); - docParamTmpService.saveParams(docId, docInfoDTO.getErrorCodeParams(), ParamStyleEnum.ERROR_CODE); + docParamPushService.saveParams(docId, docInfoDTO.getPathParams(), ParamStyleEnum.PATH); + docParamPushService.saveParams(docId, docInfoDTO.getHeaderParams(), ParamStyleEnum.HEADER); + docParamPushService.saveParams(docId, docInfoDTO.getQueryParams(), ParamStyleEnum.QUERY); + docParamPushService.saveParams(docId, docInfoDTO.getRequestParams(), ParamStyleEnum.REQUEST); + docParamPushService.saveParams(docId, docInfoDTO.getResponseParams(), ParamStyleEnum.RESPONSE); + docParamPushService.saveParams(docId, docInfoDTO.getErrorCodeParams(), ParamStyleEnum.ERROR_CODE); } - private long insertDocInfoTmp(DocInfoDTO docInfoDTO) { - DocInfoTmp docInfoTmp = CopyUtil.copyBean(docInfoDTO, DocInfoTmp::new); - this.getMapper().saveIgnoreNull(docInfoTmp); + private long insertDocInfoPush(DocInfoDTO docInfoDTO) { + DocInfoPush docInfoPush = CopyUtil.copyBean(docInfoDTO, DocInfoPush::new); + this.getMapper().saveIgnoreNull(docInfoPush); // 修复使用非MYSQL数据库插入数据id不返回问题 - if (docInfoTmp.getId() == null) { - DocInfoTmp one = getByField(DocInfoTmp::getDocKey, docInfoTmp.getDocKey()); + if (docInfoPush.getId() == null) { + DocInfoPush one = getByField(DocInfoPush::getDocKey, docInfoPush.getDocKey()); if (one != null) { - docInfoTmp.setId(one.getId()); + docInfoPush.setId(one.getId()); } } - return docInfoTmp.getId(); + return docInfoPush.getId(); } } diff --git a/server/server-service/src/main/java/cn/torna/service/DocInfoService.java b/server/server-service/src/main/java/cn/torna/service/DocInfoService.java index eb4da6a4..687666e2 100755 --- a/server/server-service/src/main/java/cn/torna/service/DocInfoService.java +++ b/server/server-service/src/main/java/cn/torna/service/DocInfoService.java @@ -17,10 +17,10 @@ import cn.torna.common.util.IdGen; import cn.torna.common.util.Markdown2HtmlUtil; import cn.torna.common.util.TreeUtil; import cn.torna.dao.entity.DocInfo; -import cn.torna.dao.entity.DocInfoTmp; +import cn.torna.dao.entity.DocInfoPush; import cn.torna.dao.entity.DocParam; import cn.torna.dao.entity.DocParamDiff; -import cn.torna.dao.entity.DocParamTmp; +import cn.torna.dao.entity.DocParamPush; import cn.torna.dao.entity.EnumInfo; import cn.torna.dao.entity.Module; import cn.torna.dao.entity.ModuleEnvironment; @@ -28,7 +28,7 @@ import cn.torna.dao.entity.ModuleEnvironmentParam; import cn.torna.dao.entity.UserDingtalkInfo; import cn.torna.dao.entity.UserWeComInfo; import cn.torna.dao.mapper.DocInfoMapper; -import cn.torna.dao.mapper.DocInfoTmpMapper; +import cn.torna.dao.mapper.DocInfoPushMapper; import cn.torna.dao.mapper.DocParamDiffMapper; import cn.torna.dao.mapper.UserDingtalkInfoMapper; import cn.torna.dao.mapper.UserWeComInfoMapper; @@ -90,7 +90,7 @@ public class DocInfoService extends BaseLambdaService { private DocParamService docParamService; @Autowired - private DocParamTmpService docParamTmpService; + private DocParamPushService docParamPushService; @Autowired private ModuleConfigService moduleConfigService; @@ -135,7 +135,7 @@ public class DocInfoService extends BaseLambdaService { private MockConfigService mockConfigService; @Autowired - private DocInfoTmpMapper docInfoTmpMapper; + private DocInfoPushMapper docInfoPushMapper; @Autowired private DocParamDiffMapper docParamDiffMapper; @@ -1009,51 +1009,55 @@ public class DocInfoService extends BaseLambdaService { } /** - * 比对文档 + * 按模块比对文档 * * @param moduleId */ - public void compareDoc(Long moduleId) { - log.info("获取模块【{}】所有文档列表,并转换成doc_key为键值的map形式", moduleId); + public void compareDoc(long moduleId) { + // 获取平台文档 List docInfoList = this.listDocDetail(moduleId); Map docInfoMap = docInfoList.stream().collect(Collectors.toMap(item -> item.getDocKey(), item -> item, (existing, replacement) -> existing)); - log.info("获取模块【{}】所有采集文档列表,并转换成doc_key为键值的map形式", moduleId); - List docInfoTmpList = docInfoTmpMapper.listByField(DocInfoTmp::getModuleId, moduleId); - Map docInfoTmpMap = docInfoTmpList.stream().collect(Collectors.toMap(item -> item.getDocKey(), + // 获取推送文档 + List docInfoPushList = docInfoPushMapper.listByField(DocInfoPush::getModuleId, moduleId); + Map docInfoPushMap = docInfoPushList.stream().collect(Collectors.toMap(item -> item.getDocKey(), item -> item, (existing, replacement) -> existing)); + // 遍历比对文档 docInfoMap.forEach((docKey, docInfoDTO) -> { - if (docInfoTmpMap.get(docKey) != null) { - DocInfoTmp docInfoTmp = docInfoTmpMap.get(docKey); + if (docInfoPushMap.get(docKey) != null) { + DocInfoPush docInfoPush = docInfoPushMap.get(docKey); log.info("开始比对文档【id:{},name:{},url:{},httpMethod:{}】", docInfoDTO.getId(), docInfoDTO.getName(), docInfoDTO.getUrl(), docInfoDTO.getHttpMethod()); - + // 获取平台文档参数 List params = docParamService.listByField(DocParam::getDocId, docInfoDTO.getId()); params.sort(Comparator.comparing(DocParam::getOrderIndex)); Map> paramsMap = params.stream() .collect(Collectors.groupingBy(DocParam::getStyle)); - - List tmpParams = docParamTmpService.listByField(DocParamTmp::getDocId, docInfoTmp.getId()); - tmpParams.sort(Comparator.comparing(DocParamTmp::getOrderIndex)); - Map> tmpParamsMap = tmpParams.stream() - .collect(Collectors.groupingBy(DocParamTmp::getStyle)); - + // 获取推送文档参数 + List pushParams = docParamPushService.listByField(DocParamPush::getDocId, docInfoPush.getId()); + pushParams.sort(Comparator.comparing(DocParamPush::getOrderIndex)); + Map> pushParamsMap = pushParams.stream() + .collect(Collectors.groupingBy(DocParamPush::getStyle)); + // 按类型比对参数 paramsMap.forEach((paramType, docParams) -> { - if (tmpParamsMap.get(paramType) != null) { + if (pushParamsMap.get(paramType) != null) { log.info("开始比对参数类型【{}】", paramType); - List docParamDiffList = compareParam(docParams, tmpParamsMap.get(paramType)); + List docParamDiffList = compareParam(docParams, pushParamsMap.get(paramType)); + log.info("更新参数类型【{}】比对结果", paramType); updateDocParamDiffByType(docParamDiffList, docInfoDTO.getId(), paramType); } else { - log.info("采集文档【id:{},name:{},url:{},httpMethod:{}】参数类型【{}】不存在!", docInfoDTO.getId(), docInfoDTO.getName(), + log.info("推送文档【id:{},name:{},url:{},httpMethod:{}】参数类型【{}】不存在!", docInfoDTO.getId(), docInfoDTO.getName(), docInfoDTO.getUrl(), docInfoDTO.getHttpMethod(), paramType); } }); - } else { - log.info("采集文档【id:{},name:{},url:{},httpMethod:{}】不存在!", docInfoDTO.getId(), docInfoDTO.getName(), + log.info("平台文档【id:{},name:{},url:{},httpMethod:{}】无推送内容!", docInfoDTO.getId(), docInfoDTO.getName(), docInfoDTO.getUrl(), docInfoDTO.getHttpMethod()); + // 记录数据库 } }); + log.info("完成模块【{}】比对,更新比对状态缓存", moduleId); + ScheduleTask.MODULE_COMPARE_STATUS_CACHE.put(moduleId, false); } /** @@ -1074,36 +1078,38 @@ public class DocInfoService extends BaseLambdaService { } /** - * 比对文档参数与采集文档参数差异 + * 比对平台参数与推送文档参数差异 * * @param docParams * @param tmpDocParams * @return 比对结果列表 */ - private List compareParam(List docParams, List tmpDocParams) { + private List compareParam(List docParams, List tmpDocParams) { + // DocParam -->> DocParamTmpDTO List docParamDTOS = new ArrayList<>(); for (DocParam item : docParams) { DocParamTmpDTO docParamTmpDTO = new DocParamTmpDTO(); CopyUtil.copyProperties(item, docParamTmpDTO); docParamDTOS.add(docParamTmpDTO); } - Map paramIdMap = new HashMap<>(); - Map paramTypeMap = new HashMap<>(); + // 组装名称全路径和paramId、fieldType映射 + Map paramIdMap = new HashMap<>(); // key: 父子名称全路径, value: paramId + Map paramTypeMap = new HashMap<>(); // key: 父子名称全路径, value: fieldType this.convertTree(docParamDTOS, 0L, null, paramIdMap, paramTypeMap); Set paramNameSet = paramIdMap.keySet(); - + // DocParamTmp -->> DocParamTmpDTO List tmpDocParamDTOS = new ArrayList<>(); - for (DocParamTmp item : tmpDocParams) { + for (DocParamPush item : tmpDocParams) { DocParamTmpDTO docParamTmpDTO = new DocParamTmpDTO(); CopyUtil.copyProperties(item, docParamTmpDTO); tmpDocParamDTOS.add(docParamTmpDTO); } - Map tmpParamIdMap = new HashMap<>(); - Map tmpParamTypeMap = new HashMap<>(); + // 组装名称全路径和paramId、fieldType映射 + Map tmpParamIdMap = new HashMap<>(); // key: 父子名称全路径, value: paramId + Map tmpParamTypeMap = new HashMap<>(); // key: 父子名称全路径, value: fieldType this.convertTree(tmpDocParamDTOS, 0L, null, tmpParamIdMap, tmpParamTypeMap); Set tmpParamNameSet = tmpParamIdMap.keySet(); - - log.info("<-----------开始比对名称差异----------->"); + // 以平台文档维度比对参数 Map nameDiffMap = new HashMap<>(); // key: 参数全路径名(包含父路径,'-'号分隔), value: DocParamDiff paramNameSet.forEach(paramName -> { if (tmpParamNameSet.contains(paramName)) { // 包含字段 @@ -1121,7 +1127,7 @@ public class DocInfoService extends BaseLambdaService { nameDiffMap.put(paramName, docParamDiff); } }); - + // 以推送文档维度比对参数 tmpParamNameSet.forEach(tmpParamName -> { if (!paramNameSet.contains(tmpParamName)) { // 临时参数多出字段 DocParamDiff docParamDiff = new DocParamDiff(); @@ -1131,7 +1137,6 @@ public class DocInfoService extends BaseLambdaService { nameDiffMap.put(tmpParamName, docParamDiff); } }); - // 组装比对结果 List docParamDiffList = new ArrayList<>(); nameDiffMap.forEach((paramName, docParamDiff) -> { diff --git a/server/server-service/src/main/java/cn/torna/service/DocParamTmpService.java b/server/server-service/src/main/java/cn/torna/service/DocParamPushService.java similarity index 59% rename from server/server-service/src/main/java/cn/torna/service/DocParamTmpService.java rename to server/server-service/src/main/java/cn/torna/service/DocParamPushService.java index 155376db..4640c35a 100644 --- a/server/server-service/src/main/java/cn/torna/service/DocParamTmpService.java +++ b/server/server-service/src/main/java/cn/torna/service/DocParamPushService.java @@ -1,8 +1,8 @@ package cn.torna.service; import cn.torna.common.enums.ParamStyleEnum; -import cn.torna.dao.entity.DocParamTmp; -import cn.torna.dao.mapper.DocParamTmpMapper; +import cn.torna.dao.entity.DocParamPush; +import cn.torna.dao.mapper.DocParamPushMapper; import cn.torna.service.dto.DocParamDTO; import com.gitee.fastmybatis.core.support.BaseLambdaService; import org.springframework.stereotype.Service; @@ -15,7 +15,7 @@ import java.util.List; * @Version 1.0 **/ @Service -public class DocParamTmpService extends BaseLambdaService { +public class DocParamPushService extends BaseLambdaService { public void saveParams(long docId, List docParamDTOS, ParamStyleEnum paramStyleEnum) { for (DocParamDTO docParamDTO : docParamDTOS) { @@ -24,23 +24,23 @@ public class DocParamTmpService extends BaseLambdaService children = docParamDTO.getChildren(); if (children != null) { - Long pid = docParamTmp.getId(); + Long pid = docParamPush.getId(); for (DocParamDTO child : children) { this.doSave(child, pid, docId, paramStyleEnum); } diff --git a/server/server-service/src/main/java/cn/torna/service/ScheduleTask.java b/server/server-service/src/main/java/cn/torna/service/ScheduleTask.java index a10e1e26..983d5e83 100644 --- a/server/server-service/src/main/java/cn/torna/service/ScheduleTask.java +++ b/server/server-service/src/main/java/cn/torna/service/ScheduleTask.java @@ -1,7 +1,12 @@ package cn.torna.service; import cn.torna.common.bean.EnvironmentKeys; +import cn.torna.common.enums.ModuleConfigTypeEnum; +import cn.torna.dao.entity.ModuleConfig; +import cn.torna.dao.mapper.ModuleConfigMapper; import cn.torna.service.dto.DocDiffDTO; +import com.gitee.fastmybatis.core.query.Query; +import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.math.NumberUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.scheduling.annotation.EnableScheduling; @@ -9,17 +14,32 @@ import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; /** * @author thc */ +@Slf4j @Component @EnableScheduling public class ScheduleTask { + /** + * 记录模块比对状态 + * 结构:{moduleId, compareStatus} + * 逻辑:模块比对完false,有数据推送则true + */ + public static final Map MODULE_COMPARE_STATUS_CACHE = new ConcurrentHashMap<>(); + @Autowired private DocDiffRecordService docDiffRecordService; + @Autowired + private DocInfoService docInfoService; + + @Autowired + private ModuleConfigMapper moduleConfigMapper; @Scheduled(initialDelay = 1000, fixedDelay = 15 * 1000) public void saveDocDiff() { @@ -31,5 +51,21 @@ public class ScheduleTask { } } - + /** + * 比对文档差异 + */ + @Scheduled(initialDelay = 300 * 1000, fixedDelay = 300 * 1000) + public void compareDocDiff() { + Query query = Query.create() + .eq("type", ModuleConfigTypeEnum.COMMON) + .eq("config_key", "isMonitor") + .eq("config_value", "1"); + List compareModuleIdList = moduleConfigMapper.listUniqueValue(query, ModuleConfig::getModuleId); + compareModuleIdList.forEach(moduleId -> { + if (MODULE_COMPARE_STATUS_CACHE.getOrDefault(moduleId, false)) { + log.info("==========开始比对模块【{}】推送文档=====", moduleId); + docInfoService.compareDoc(moduleId); + } + }); + } } -- Gitee From 9a54ea7fb3d21df4b570a40c2c5f4aa1a9120023 Mon Sep 17 00:00:00 2001 From: bounce5733 Date: Thu, 30 Oct 2025 14:56:05 +0800 Subject: [PATCH 5/6] =?UTF-8?q?=E6=96=87=E6=A1=A3=E5=8F=82=E6=95=B0?= =?UTF-8?q?=E6=AF=94=E5=AF=B9=E7=BB=93=E6=9E=9C=E5=B1=95=E7=A4=BA=E5=8F=8A?= =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- front/src/components/DocView/index.vue | 23 +- .../ParameterCompareTable/index.vue | 127 ++++++++++ front/src/views/view/CompareResult/index.vue | 224 ++++++++++++++++++ front/src/views/view/index.vue | 73 +++++- .../cn/torna/dao/entity/DocParamDiff.java | 3 + .../java/cn/torna/service/DocInfoService.java | 109 +++++---- .../cn/torna/service/dto/DocParamDiffDTO.java | 59 +++++ ...cParamTmpDTO.java => DocParamPushDTO.java} | 13 +- .../web/controller/doc/DocController.java | 1 + .../web/controller/doc/ViewController.java | 13 + 10 files changed, 567 insertions(+), 78 deletions(-) create mode 100644 front/src/components/ParameterCompareTable/index.vue create mode 100644 front/src/views/view/CompareResult/index.vue create mode 100644 server/server-service/src/main/java/cn/torna/service/dto/DocParamDiffDTO.java rename server/server-service/src/main/java/cn/torna/service/dto/{DocParamTmpDTO.java => DocParamPushDTO.java} (72%) diff --git a/front/src/components/DocView/index.vue b/front/src/components/DocView/index.vue index c0a88c16..f5c83a60 100644 --- a/front/src/components/DocView/index.vue +++ b/front/src/components/DocView/index.vue @@ -18,12 +18,12 @@
- +
- +
@@ -65,7 +65,8 @@ size="small" effect="plain" class="copyBtn" - @click.stop="copyCurl(buildRequestUrl(hostConfig))">{{ $t('copy') + 'CURL' }} + @click.stop="copyCurl(buildRequestUrl(hostConfig))" + >{{ $t('copy') + 'CURL' }}
@@ -81,15 +82,15 @@

{{ $t('description') }}

-
+

ContentType{{ docInfo.contentType }}

@@ -189,7 +190,7 @@
{{ $t('updateRemark') }} -
+
-

+

@@ -244,7 +245,7 @@ import CodeGenDrawer from '@/components/CodeGenDrawer' import CopyText from '@/components/CopyText' import ExportUtil from '@/utils/export' import { generate } from 'json2interface' -import {get_effective_url, parse_root_array, StringBuilder} from '@/utils/common' +import { get_effective_url, parse_root_array, StringBuilder } from '@/utils/common' import { mavonEditor } from 'mavon-editor' export default { @@ -529,7 +530,7 @@ export default { // --location --globoff const str = new StringBuilder(`curl -L -g `) - const httpMethod = this.docInfo.httpMethod; + const httpMethod = this.docInfo.httpMethod if (httpMethod === 'POST' || httpMethod === 'PUT') { str.append(`-X ${httpMethod} `) } diff --git a/front/src/components/ParameterCompareTable/index.vue b/front/src/components/ParameterCompareTable/index.vue new file mode 100644 index 00000000..8040766d --- /dev/null +++ b/front/src/components/ParameterCompareTable/index.vue @@ -0,0 +1,127 @@ + + + diff --git a/front/src/views/view/CompareResult/index.vue b/front/src/views/view/CompareResult/index.vue new file mode 100644 index 00000000..17b0cc06 --- /dev/null +++ b/front/src/views/view/CompareResult/index.vue @@ -0,0 +1,224 @@ + + + + diff --git a/front/src/views/view/index.vue b/front/src/views/view/index.vue index 0b215b71..fc973322 100644 --- a/front/src/views/view/index.vue +++ b/front/src/views/view/index.vue @@ -13,6 +13,10 @@ Mock + + 比对结果 + + @@ -31,15 +35,18 @@ import DubboView from '@/components/DubboView' import DocDebug from '@/components/DocDebug' import Mock from '@/components/Mock' import DocViewCustom from '@/components/DocViewCustom' +import CompareResult from './CompareResult' export default { - components: { DocView, DocDebug, Mock, DubboView, DocViewCustom }, + components: { DocView, DocDebug, Mock, DubboView, DocViewCustom, CompareResult }, data() { return { active: 'info', item: { type: 0 }, + compareModifyParam: { pathParams: {}, headerParams: {}, requestParams: {}, responseParams: {}, queryParams: {}}, // 文档比对差异字段 + compareNewParam: { pathParams: [], headerParams: [], requestParams: [], responseParams: [], queryParams: [] }, // 文档比对新增字段 infoItem: {}, debugItem: {}, mockItem: {} @@ -61,17 +68,61 @@ export default { if (docId) { this.$nextTick(() => { this.get('/doc/view/detail', { id: docId }, function(resp) { - const data = resp.data - this.setProjectId(data.projectId) - this.initDocInfoView(data) - this.item = data - this.selectTab('info') - this.setTitle(data.name) - if (this.item.type === this.getEnums().DOC_TYPE.DUBBO) { - this.$nextTick(() => { - this.$refs.docViewDubbo.setData(this.item) + this.get('/doc/view/compare/result', { id: docId }, function(compareResp) { + const data = resp.data + this.setProjectId(data.projectId) + this.initDocInfoView(data) + this.item = data + this.selectTab('info') + this.setTitle(data.name) + if (this.item.type === this.getEnums().DOC_TYPE.DUBBO) { + this.$nextTick(() => { + this.$refs.docViewDubbo.setData(this.item) + }) + } + const compareModifyData = compareResp.data.filter(item => item.diffType !== -1) + compareModifyData.forEach(item => { + switch (item.style) { + case 0: + this.compareModifyParam.pathParams[item.paramId] = item + break + case 1: + this.compareModifyParam.headerParams[item.paramId] = item + break + case 2: + this.compareModifyParam.requestParams[item.paramId] = item + break + case 3: + this.compareModifyParam.responseParams[item.paramId] = item + break + case 5: + this.compareModifyParam.queryParams[item.paramId] = item + break + default: + } + }) + const compareNewData = compareResp.data.filter(item => item.diffType === -1) + compareNewData.forEach(item => { + switch (item.style) { + case 0: + this.compareNewParam.pathParams.push(item) + break + case 1: + this.compareNewParam.headerParams.push(item) + break + case 2: + this.compareNewParam.requestParams.push(item) + break + case 3: + this.compareNewParam.responseParams.push(item) + break + case 5: + this.compareNewParam.queryParams.push(item) + break + default: + } }) - } + }) }) }) } else { diff --git a/server/server-dao/src/main/java/cn/torna/dao/entity/DocParamDiff.java b/server/server-dao/src/main/java/cn/torna/dao/entity/DocParamDiff.java index 6412573c..efac157a 100644 --- a/server/server-dao/src/main/java/cn/torna/dao/entity/DocParamDiff.java +++ b/server/server-dao/src/main/java/cn/torna/dao/entity/DocParamDiff.java @@ -33,6 +33,9 @@ public class DocParamDiff { /** 差异类型: 1: 临时参数缺少字段,-1: 临时参数多出字段, 2: 名称一致,类型不一致 */ private Byte diffType; + /** 排序索引, 数据库字段:order_index */ + private Integer orderIndex; + /** 差异字段名称 */ private String diffParamName; diff --git a/server/server-service/src/main/java/cn/torna/service/DocInfoService.java b/server/server-service/src/main/java/cn/torna/service/DocInfoService.java index 687666e2..4d61b326 100755 --- a/server/server-service/src/main/java/cn/torna/service/DocInfoService.java +++ b/server/server-service/src/main/java/cn/torna/service/DocInfoService.java @@ -39,7 +39,8 @@ import cn.torna.service.dto.DocItemCreateDTO; import cn.torna.service.dto.DocListFormDTO; import cn.torna.service.dto.DocMeta; import cn.torna.service.dto.DocParamDTO; -import cn.torna.service.dto.DocParamTmpDTO; +import cn.torna.service.dto.DocParamDiffDTO; +import cn.torna.service.dto.DocParamPushDTO; import cn.torna.service.dto.DocRefDTO; import cn.torna.service.dto.DubboInfoDTO; import cn.torna.service.dto.EnumInfoDTO; @@ -283,6 +284,19 @@ public class DocInfoService extends BaseLambdaService { return getDocDetail(docInfo); } + /** + * 返回文档比对结果 + * + * @param docId + * @return + */ + public List getCompareResult(long docId) { + Query query = Query.create().eq("doc_id", docId).orderByAsc("order_index"); + List docParamDiffList = docParamDiffMapper.list(query); + return docParamDiffList.stream().map(item -> CopyUtil.copyBean(item, DocParamDiffDTO::new)) + .collect(Collectors.toList()); + } + /** * 返回文档详情 * @@ -1016,8 +1030,9 @@ public class DocInfoService extends BaseLambdaService { public void compareDoc(long moduleId) { // 获取平台文档 List docInfoList = this.listDocDetail(moduleId); - Map docInfoMap = docInfoList.stream().collect(Collectors.toMap(item -> item.getDocKey(), - item -> item, (existing, replacement) -> existing)); + Map docInfoMap = docInfoList.stream().filter(item -> item.getIsFolder() == 0) + .collect(Collectors.toMap(item -> item.getDocKey(), + item -> item, (existing, replacement) -> existing)); // 获取推送文档 List docInfoPushList = docInfoPushMapper.listByField(DocInfoPush::getModuleId, moduleId); Map docInfoPushMap = docInfoPushList.stream().collect(Collectors.toMap(item -> item.getDocKey(), @@ -1040,15 +1055,17 @@ public class DocInfoService extends BaseLambdaService { .collect(Collectors.groupingBy(DocParamPush::getStyle)); // 按类型比对参数 paramsMap.forEach((paramType, docParams) -> { - if (pushParamsMap.get(paramType) != null) { - log.info("开始比对参数类型【{}】", paramType); - List docParamDiffList = compareParam(docParams, pushParamsMap.get(paramType)); - log.info("更新参数类型【{}】比对结果", paramType); - updateDocParamDiffByType(docParamDiffList, docInfoDTO.getId(), paramType); + log.info("开始比对参数类型【{}】", paramType); + List pushDocParams = pushParamsMap.get(paramType) == null ? new ArrayList<>() : pushParamsMap.get(paramType); + List docParamDiffList = compareParam(docParams, pushDocParams); + if (docParamDiffList.size() > 0) { + log.info("【id:{},name:{},url:{},httpMethod:{}】参数类型【{}】有差异,更新比对结果", docInfoDTO.getId(), docInfoDTO.getName(), + docInfoDTO.getUrl(), docInfoDTO.getHttpMethod(), paramType); } else { - log.info("推送文档【id:{},name:{},url:{},httpMethod:{}】参数类型【{}】不存在!", docInfoDTO.getId(), docInfoDTO.getName(), + log.debug("【id:{},name:{},url:{},httpMethod:{}】参数类型【{}】无差异,清除比对结果", docInfoDTO.getId(), docInfoDTO.getName(), docInfoDTO.getUrl(), docInfoDTO.getHttpMethod(), paramType); } + updateDocParamDiffByType(docParamDiffList, docInfoDTO.getId(), paramType); }); } else { log.info("平台文档【id:{},name:{},url:{},httpMethod:{}】无推送内容!", docInfoDTO.getId(), docInfoDTO.getName(), @@ -1081,59 +1098,58 @@ public class DocInfoService extends BaseLambdaService { * 比对平台参数与推送文档参数差异 * * @param docParams - * @param tmpDocParams + * @param pushDocParams * @return 比对结果列表 */ - private List compareParam(List docParams, List tmpDocParams) { + private List compareParam(List docParams, List pushDocParams) { // DocParam -->> DocParamTmpDTO - List docParamDTOS = new ArrayList<>(); + List docParamDTOS = new ArrayList<>(); for (DocParam item : docParams) { - DocParamTmpDTO docParamTmpDTO = new DocParamTmpDTO(); - CopyUtil.copyProperties(item, docParamTmpDTO); - docParamDTOS.add(docParamTmpDTO); + DocParamPushDTO docParamPushDTO = new DocParamPushDTO(); + CopyUtil.copyProperties(item, docParamPushDTO); + docParamDTOS.add(docParamPushDTO); } - // 组装名称全路径和paramId、fieldType映射 - Map paramIdMap = new HashMap<>(); // key: 父子名称全路径, value: paramId - Map paramTypeMap = new HashMap<>(); // key: 父子名称全路径, value: fieldType - this.convertTree(docParamDTOS, 0L, null, paramIdMap, paramTypeMap); - Set paramNameSet = paramIdMap.keySet(); + // 组装全名称路径的参数映射 + Map paramNamePathMap = new HashMap<>(); + this.convertTree(docParamDTOS, 0L, null, paramNamePathMap); + Set paramNamePathSet = paramNamePathMap.keySet(); // DocParamTmp -->> DocParamTmpDTO - List tmpDocParamDTOS = new ArrayList<>(); - for (DocParamPush item : tmpDocParams) { - DocParamTmpDTO docParamTmpDTO = new DocParamTmpDTO(); - CopyUtil.copyProperties(item, docParamTmpDTO); - tmpDocParamDTOS.add(docParamTmpDTO); + List docParamPushDTOS = new ArrayList<>(); + for (DocParamPush item : pushDocParams) { + DocParamPushDTO docParamPushDTO = new DocParamPushDTO(); + CopyUtil.copyProperties(item, docParamPushDTO); + docParamPushDTOS.add(docParamPushDTO); } - // 组装名称全路径和paramId、fieldType映射 - Map tmpParamIdMap = new HashMap<>(); // key: 父子名称全路径, value: paramId - Map tmpParamTypeMap = new HashMap<>(); // key: 父子名称全路径, value: fieldType - this.convertTree(tmpDocParamDTOS, 0L, null, tmpParamIdMap, tmpParamTypeMap); - Set tmpParamNameSet = tmpParamIdMap.keySet(); + Map tmpParamNamePathMap = new HashMap<>(); + this.convertTree(docParamPushDTOS, 0L, null, tmpParamNamePathMap); + Set tmpParamNameSet = tmpParamNamePathMap.keySet(); // 以平台文档维度比对参数 Map nameDiffMap = new HashMap<>(); // key: 参数全路径名(包含父路径,'-'号分隔), value: DocParamDiff - paramNameSet.forEach(paramName -> { + paramNamePathSet.forEach(paramName -> { if (tmpParamNameSet.contains(paramName)) { // 包含字段 - if (!paramTypeMap.get(paramName).equals(tmpParamTypeMap.get(paramName))) { // 类型不一致 + if (!paramNamePathMap.get(paramName).getType().equals(tmpParamNamePathMap.get(paramName).getType())) { // 类型不一致 DocParamDiff docParamDiff = new DocParamDiff(); - docParamDiff.setParamId(paramIdMap.get(paramName)); + docParamDiff.setParamId(paramNamePathMap.get(paramName).getId()); docParamDiff.setDiffType((byte) 2); - docParamDiff.setDiffParamType(tmpParamTypeMap.get(paramName)); + docParamDiff.setDiffParamType(tmpParamNamePathMap.get(paramName).getType()); + docParamDiff.setOrderIndex(paramNamePathMap.get(paramName).getOrderIndex()); nameDiffMap.put(paramName, docParamDiff); } } else { // 临时参数缺少字段 DocParamDiff docParamDiff = new DocParamDiff(); - docParamDiff.setParamId(paramIdMap.get(paramName)); + docParamDiff.setParamId(paramNamePathMap.get(paramName).getId()); docParamDiff.setDiffType((byte) 1); + docParamDiff.setOrderIndex(paramNamePathMap.get(paramName).getOrderIndex()); nameDiffMap.put(paramName, docParamDiff); } }); // 以推送文档维度比对参数 tmpParamNameSet.forEach(tmpParamName -> { - if (!paramNameSet.contains(tmpParamName)) { // 临时参数多出字段 + if (!paramNamePathSet.contains(tmpParamName)) { // 临时参数多出字段 DocParamDiff docParamDiff = new DocParamDiff(); - docParamDiff.setParamId(tmpParamIdMap.get(tmpParamName)); docParamDiff.setDiffType((byte) -1); - docParamDiff.setDiffParamType(tmpParamTypeMap.get(tmpParamName)); + docParamDiff.setDiffParamType(tmpParamNamePathMap.get(tmpParamName).getType()); + docParamDiff.setOrderIndex(tmpParamNamePathMap.get(tmpParamName).getOrderIndex()); nameDiffMap.put(tmpParamName, docParamDiff); } }); @@ -1152,25 +1168,20 @@ public class DocInfoService extends BaseLambdaService { * @param list * @param parentId 当前父节点id * @param parentName 拼接父节点名称 - * @param idMap 记录全路径名称->id映射 - * @param typeMap 记录全路径名称->类型映射 + * @param paramNamePathMap 记录全路径名称->param映射 * @return */ - private List convertTree(List list, long parentId, String parentName, - Map idMap, Map typeMap) { + private List convertTree(List list, long parentId, String parentName, Map paramNamePathMap) { if (list == null) { return Collections.emptyList(); } - List temp = new ArrayList<>(); + List temp = new ArrayList<>(); for (int i = 0; i < list.size(); i++) { - DocParamTmpDTO item = list.get(i); + DocParamPushDTO item = list.get(i); if (Objects.equals(item.getParentId(), parentId)) { String fullPath = (parentId == 0L ? item.getName() : parentName + "-" + item.getName()); - List children = convertTree(list, item.getId(), fullPath, idMap, typeMap); - if (children.size() == 0) { - idMap.put(fullPath, item.getId()); - typeMap.put(fullPath, item.getType()); - } + List children = convertTree(list, item.getId(), fullPath, paramNamePathMap); + paramNamePathMap.put(fullPath, item); item.setChildren(children); temp.add(item); } diff --git a/server/server-service/src/main/java/cn/torna/service/dto/DocParamDiffDTO.java b/server/server-service/src/main/java/cn/torna/service/dto/DocParamDiffDTO.java new file mode 100644 index 00000000..227ca6f6 --- /dev/null +++ b/server/server-service/src/main/java/cn/torna/service/dto/DocParamDiffDTO.java @@ -0,0 +1,59 @@ +package cn.torna.service.dto; + +import cn.torna.common.support.IdCodec; +import com.alibaba.fastjson.annotation.JSONField; +import lombok.Data; + +import java.time.LocalDateTime; + +/** + * @Author jyh + * @Date 2025/10/24 14:53 + * @Version 1.0 + **/ +@Data +public class DocParamDiffDTO { + + @JSONField(serializeUsing = IdCodec.class, deserializeUsing = IdCodec.class) + private Long id; + + /** + * 根据diff_type决定doc_param.id 或 doc_param_tmp.id + */ + @JSONField(serializeUsing = IdCodec.class, deserializeUsing = IdCodec.class) + private Long paramId; + + /** + * doc_info.id, 数据库字段:doc_id + */ + private Long docId; + + /** + * 0:path, 1:header, 2:请求参数,3:返回参数,4:错误码, 数据库字段:style + */ + private Byte style; + + /** + * 差异类型: 1: 临时参数缺少字段,-1: 临时参数多出字段, 2: 名称一致,类型不一致 + */ + private Byte diffType; + + /** 排序索引, 数据库字段:order_index */ + private Integer orderIndex; + + /** + * 差异字段名称 + */ + private String diffParamName; + + /** + * 差异字段类型 + */ + private String diffParamType; + + /** + * 数据库字段:gmt_create + */ + private LocalDateTime gmtCreate; + +} diff --git a/server/server-service/src/main/java/cn/torna/service/dto/DocParamTmpDTO.java b/server/server-service/src/main/java/cn/torna/service/dto/DocParamPushDTO.java similarity index 72% rename from server/server-service/src/main/java/cn/torna/service/dto/DocParamTmpDTO.java rename to server/server-service/src/main/java/cn/torna/service/dto/DocParamPushDTO.java index 442a30a2..4b25235a 100644 --- a/server/server-service/src/main/java/cn/torna/service/dto/DocParamTmpDTO.java +++ b/server/server-service/src/main/java/cn/torna/service/dto/DocParamPushDTO.java @@ -11,12 +11,12 @@ import java.time.LocalDateTime; import java.util.List; /** - * @Author jiangyh + * @Author jyh * @Date 2025/10/24 14:53 * @Version 1.0 **/ @Data -public class DocParamTmpDTO implements TreeAware { +public class DocParamPushDTO implements TreeAware { @JSONField(serializeUsing = IdCodec.class, deserializeUsing = IdCodec.class) private Long id; @@ -24,25 +24,24 @@ public class DocParamTmpDTO implements TreeAware { /** * 字段名称, 数据库字段:name */ - @Diff(positionType = PositionType.PARAM_NAME) private String name; /** * 字段类型, 数据库字段:type */ - @Diff(positionType = PositionType.PARAM_TYPE) private String type; /** * doc_info.id, 数据库字段:doc_id */ - @JSONField(serializeUsing = IdCodec.class, deserializeUsing = IdCodec.class) private Long docId; + /** 排序索引, 数据库字段:order_index */ + private Integer orderIndex; + /** * 父节点, 数据库字段:parent_id */ - @JSONField(serializeUsing = IdCodec.class, deserializeUsing = IdCodec.class) private Long parentId; /** @@ -55,6 +54,6 @@ public class DocParamTmpDTO implements TreeAware { */ private LocalDateTime gmtCreate; - private List children; + private List children; } diff --git a/server/server-web/src/main/java/cn/torna/web/controller/doc/DocController.java b/server/server-web/src/main/java/cn/torna/web/controller/doc/DocController.java index 1d3f57f1..0ed92ec5 100644 --- a/server/server-web/src/main/java/cn/torna/web/controller/doc/DocController.java +++ b/server/server-web/src/main/java/cn/torna/web/controller/doc/DocController.java @@ -10,6 +10,7 @@ import cn.torna.common.enums.ParamStyleEnum; import cn.torna.common.exception.BizException; import cn.torna.common.util.CopyUtil; import cn.torna.dao.entity.DocInfo; +import cn.torna.dao.entity.DocParamDiff; import cn.torna.dao.entity.ModuleEnvironment; import cn.torna.dao.entity.ModuleEnvironmentParam; import cn.torna.service.DocInfoService; diff --git a/server/server-web/src/main/java/cn/torna/web/controller/doc/ViewController.java b/server/server-web/src/main/java/cn/torna/web/controller/doc/ViewController.java index a3022914..19c17942 100644 --- a/server/server-web/src/main/java/cn/torna/web/controller/doc/ViewController.java +++ b/server/server-web/src/main/java/cn/torna/web/controller/doc/ViewController.java @@ -5,6 +5,7 @@ import cn.torna.common.bean.Result; import cn.torna.common.bean.User; import cn.torna.common.exception.BizException; import cn.torna.common.util.CopyUtil; +import cn.torna.dao.entity.DocParamDiff; import cn.torna.dao.entity.Project; import cn.torna.dao.entity.Space; import cn.torna.dao.entity.SpaceUser; @@ -13,6 +14,7 @@ import cn.torna.service.DocViewService; import cn.torna.service.ProjectService; import cn.torna.service.SpaceService; import cn.torna.service.dto.DocInfoDTO; +import cn.torna.service.dto.DocParamDiffDTO; import cn.torna.service.dto.ProjectDTO; import cn.torna.service.dto.SpaceProjectDTO; import cn.torna.service.dto.TreeDTO; @@ -116,5 +118,16 @@ public class ViewController { return Result.ok(docInfoDTO); } + /** + * 比对结果 + * + * @param id 主键 + * @return 比对结果 + */ + @GetMapping("compare/result") + public Result> compareResult(@HashId Long id) { + List compareResultList = docInfoService.getCompareResult(id); + return Result.ok(compareResultList); + } } -- Gitee From 95f3cbc716eed5ee669df1442f1e50a2ad5f4644 Mon Sep 17 00:00:00 2001 From: bounce5733 Date: Mon, 3 Nov 2025 16:45:35 +0800 Subject: [PATCH 6/6] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E5=AF=B9=E5=8A=A8?= =?UTF-8?q?=E6=80=81=E5=8F=82=E6=95=B0=E7=A6=81=E7=94=A8=E5=8F=82=E6=95=B0?= =?UTF-8?q?=E6=AF=94=E5=AF=B9=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ParameterCompareTable/index.vue | 6 +- front/src/utils/http.js | 2 +- front/src/views/project/DocTable/index.vue | 56 +++++- front/src/views/view/index.vue | 2 +- mysql.sql | 70 ++++++++ .../java/cn/torna/dao/entity/DocInfoDiff.java | 37 ++++ .../java/cn/torna/dao/entity/DocInfoExt.java | 41 +++++ .../torna/dao/mapper/DocInfoDiffMapper.java | 12 ++ .../cn/torna/dao/mapper/DocInfoExtMapper.java | 13 ++ .../java/cn/torna/service/DocInfoService.java | 168 +++++++++++++----- .../java/cn/torna/service/ScheduleTask.java | 2 +- .../cn/torna/service/dto/DocInfoDiffDTO.java | 37 ++++ .../cn/torna/service/dto/DocInfoExtDTO.java | 41 +++++ .../web/controller/doc/DocController.java | 40 +++-- .../web/controller/doc/ViewController.java | 38 +++- 15 files changed, 491 insertions(+), 74 deletions(-) create mode 100644 server/server-dao/src/main/java/cn/torna/dao/entity/DocInfoDiff.java create mode 100644 server/server-dao/src/main/java/cn/torna/dao/entity/DocInfoExt.java create mode 100644 server/server-dao/src/main/java/cn/torna/dao/mapper/DocInfoDiffMapper.java create mode 100644 server/server-dao/src/main/java/cn/torna/dao/mapper/DocInfoExtMapper.java create mode 100644 server/server-service/src/main/java/cn/torna/service/dto/DocInfoDiffDTO.java create mode 100644 server/server-service/src/main/java/cn/torna/service/dto/DocInfoExtDTO.java diff --git a/front/src/components/ParameterCompareTable/index.vue b/front/src/components/ParameterCompareTable/index.vue index 8040766d..9c9765b6 100644 --- a/front/src/components/ParameterCompareTable/index.vue +++ b/front/src/components/ParameterCompareTable/index.vue @@ -116,10 +116,8 @@ export default { } }, rowStyle({ row, rowIndex }) { - if (this.compareModifyParam[row.id]) { - if (this.compareModifyParam[row.id].diffType === 1) { - return { 'text-decoration-line': 'line-through', 'text-decoration-color': 'red' } - } + if (this.compareModifyParam[row.id] && this.compareModifyParam[row.id].diffType === 1) { + return { 'text-decoration-line': 'line-through', 'text-decoration-color': 'red' } } } } diff --git a/front/src/utils/http.js b/front/src/utils/http.js index dbf9f8c5..107a7b0c 100644 --- a/front/src/utils/http.js +++ b/front/src/utils/http.js @@ -20,7 +20,7 @@ const frontURL = getBrowserUrl() const serverUrl = process.env.VUE_APP_BASE_API || frontURL // 创建axios实例 -const client = axios.create({ +export const client = axios.create({ baseURL: serverUrl, // api 的 base_url timeout: 600000, // 请求超时时间,600秒 headers: { diff --git a/front/src/views/project/DocTable/index.vue b/front/src/views/project/DocTable/index.vue index 9416b6ff..a9a96002 100644 --- a/front/src/views/project/DocTable/index.vue +++ b/front/src/views/project/DocTable/index.vue @@ -75,6 +75,7 @@ :height="tableHeight" :row-height="30" border + :row-style="rowStyle" >

+
+ + + +
md @@ -233,6 +239,17 @@ :title="$t('unlock')" :command="() => { onDocUnLock(scope.row) }" /> + + + + + +
@@ -300,6 +317,7 @@ import SvgIcon from '@/components/SvgIcon' import TimeTooltip from '@/components/TimeTooltip' import DocExportDialog from '@/components/DocExportDialog' import PopoverUpdate from '@/components/PopoverUpdate' +import { client } from '@/utils/http' export default { name: 'DocTable', @@ -336,7 +354,9 @@ export default { status: null, filterEmptyFolder: null }, - token: '' + token: '', + docDiffMap: {}, // 文档比对差异map {key: docId, value: diffType} + docParamIgnoreMap: {} // 文档参数比对是否忽略map {key: docId, value: 1 | 0} } }, computed: { @@ -397,9 +417,22 @@ export default { } Object.assign(searchData, this.searchForm) this.post('/doc/list-v2', searchData, function(resp) { - this.tableData = this.convertTree(resp.data) - callback && callback.call(this) - this.loading = false + Promise.all([client.get('/doc/view/compare/doc/result', { moduleId: moduleId }), + client.get('/doc/view/ext/isIgnoreCompareParam/' + moduleId + '/list')]).then(resps => { + this.tableData = this.convertTree(resp.data) + callback && callback.call(this) + this.loading = false + // 组装文档比对差异map + this.docDiffMap = {} + resps[0].data.data.forEach(docDiff => { + this.docDiffMap[docDiff.docId] = docDiff.diffType + }) + // 组装是否忽略参数比对map + this.docParamIgnoreMap = {} + resps[1].data.data.forEach(docInfoExt => { + this.docParamIgnoreMap[docInfoExt.docId] = docInfoExt.docValue + }) + }) }) this.loadToken(moduleId) }, @@ -547,6 +580,12 @@ export default { this.loadTable() }) }, + onDocParamIgnore(row, status) { + this.get('/doc/monitor/ignore/status', { docId: row.id, moduleId: row.moduleId, status: status }, () => { + this.tipSuccess(this.$t('operateSuccess')) + this.loadTable() + }) + }, onDocUnLock(row) { this.post('/doc/unlock', { id: row.id }, () => { this.tipSuccess(this.$t('operateSuccess')) @@ -609,6 +648,15 @@ export default { }, onCopyPostmanUrl() { this.copyText(this.postmanUrl) + }, + rowStyle({ row, rowIndex }) { + if (this.docDiffMap[row.id]) { + if (this.docDiffMap[row.id] === 1) { + return { 'color': '#C0C4CC' } + } else if (this.docDiffMap[row.id] === 2) { + return { 'color': '#F56C6C' } + } + } } } } diff --git a/front/src/views/view/index.vue b/front/src/views/view/index.vue index fc973322..79bf1eec 100644 --- a/front/src/views/view/index.vue +++ b/front/src/views/view/index.vue @@ -68,7 +68,7 @@ export default { if (docId) { this.$nextTick(() => { this.get('/doc/view/detail', { id: docId }, function(resp) { - this.get('/doc/view/compare/result', { id: docId }, function(compareResp) { + this.get('/doc/view/compare/param/result', { id: docId }, function(compareResp) { const data = resp.data this.setProjectId(data.projectId) this.initDocInfoView(data) diff --git a/mysql.sql b/mysql.sql index 66908b2f..59fe81d2 100644 --- a/mysql.sql +++ b/mysql.sql @@ -731,6 +731,76 @@ CREATE TABLE `user_wecom_info` ( KEY `idx_userid` (`user_info_id`) USING BTREE ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; +DROP TABLE IF EXISTS `doc_info_ext`; +CREATE TABLE `doc_info_ext` ( + `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + `doc_id` varchar(64) NOT NULL DEFAULT '' COMMENT '文档唯一key', + `module_id` bigint(20) unsigned NOT NULL DEFAULT '0' COMMENT '模块id,module.id', + `doc_prop` varchar(64) NOT NULL COMMENT '文档属性', + `doc_value` varchar(128) NOT NULL COMMENT '文档属性值', + `gmt_create` datetime DEFAULT CURRENT_TIMESTAMP, + `gmt_modified` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + PRIMARY KEY (`id`) USING BTREE, + KEY `idx_docid` (`doc_id`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='文档信息扩展表'; + +DROP TABLE IF EXISTS `doc_info_push`; +CREATE TABLE `doc_info_push` ( + `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + `doc_key` varchar(64) NOT NULL DEFAULT '' COMMENT '文档唯一key', + `name` varchar(128) NOT NULL DEFAULT '' COMMENT '文档名称', + `url` varchar(256) NOT NULL DEFAULT '' COMMENT '访问URL', + `http_method` varchar(12) NOT NULL DEFAULT '' COMMENT 'http方法', + `content_type` varchar(128) NOT NULL DEFAULT '' COMMENT 'contentType', + `module_id` bigint(20) unsigned NOT NULL DEFAULT '0' COMMENT '模块id,module.id', + `is_compare` tinyint(4) NOT NULL DEFAULT '0' COMMENT '是否比对 1:已经比对,0:未比对', + `gmt_create` datetime DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`id`) USING BTREE, + KEY `idx_moduleid` (`module_id`) USING BTREE, + KEY `idx_dockey` (`doc_key`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='文档信息推送表'; + +DROP TABLE IF EXISTS `doc_param_push`; +CREATE TABLE `doc_param_push` ( + `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + `name` varchar(64) NOT NULL DEFAULT '' COMMENT '字段名称', + `type` varchar(64) NOT NULL DEFAULT 'String' COMMENT '字段类型', + `doc_id` bigint(20) unsigned NOT NULL DEFAULT '0' COMMENT 'doc_info.id', + `parent_id` bigint(20) unsigned NOT NULL DEFAULT '0', + `style` tinyint(4) NOT NULL DEFAULT '0' COMMENT '0:path, 1:header, 2:body参数,3:返回参数,4:错误码, 5:query参数', + `order_index` int(11) NOT NULL DEFAULT '0' COMMENT '排序索引', + `gmt_create` datetime DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`id`) USING BTREE, + KEY `idx_docid` (`doc_id`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='文档参数推送表'; + +DROP TABLE IF EXISTS `doc_info_diff`; +CREATE TABLE `doc_info_diff` ( + `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + `doc_id` bigint(20) unsigned NOT NULL DEFAULT '0' COMMENT 'doc_info.id', + `diff_type` tinyint(4) NOT NULL COMMENT '差异类型: 1: 推送缺少文档 2: 文档比对差异', + `module_id` bigint(20) unsigned NOT NULL DEFAULT '0' COMMENT '模块id,module.id', + `gmt_create` datetime DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`id`) USING BTREE, + KEY `idx_docid` (`doc_id`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='文档差异表'; + +DROP TABLE IF EXISTS `doc_param_diff`; +CREATE TABLE `doc_param_diff` ( + `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + `param_id` bigint(20) unsigned COMMENT '根据diff_type决定doc_param.id 或 doc_param_push.id', + `doc_id` bigint(20) unsigned NOT NULL DEFAULT '0' COMMENT 'doc_info.id', + `style` tinyint(4) NOT NULL DEFAULT '0' COMMENT '0:path, 1:header, 2:body参数,3:返回参数,4:错误码, 5:query参数', + `diff_type` tinyint(4) NOT NULL COMMENT '差异类型: 1: 推送参数缺少字段,-1: 推送参数多出字段, 2: 名称一致,类型不一致', + `order_index` int(11) NOT NULL DEFAULT '0' COMMENT '排序索引', + `diff_param_name` varchar(256) NOT NULL DEFAULT 'String' COMMENT '差异字段名称', + `diff_param_type` varchar(64) COMMENT '差异字段类型', + `gmt_create` datetime DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`id`) USING BTREE, + KEY `idx_docid` (`doc_id`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='文档参数差异表'; + + INSERT INTO `constant_info` (`id`, `project_id`, `module_id`, `doc_id`, `content`, `gmt_create`, `gmt_modified`) VALUES (1, 5, 0, 0, '

全局状态码

HTTP状态码说明
200OK
400Bad Request
401Unauthorized
403Forbidden
404Not Found
405Method Not Allowed
500Internal Server Error
502Bad Gateway
503Service Unavailable
504Gateway Timeout
', '2022-11-03 20:32:43', '2022-11-03 20:32:43'), (2, 0, 5, 0, '

商品中心错误码

  • 10001:商品不存在
  • 10002:分类不存在
  • 10003:商品已下架
  • 10004:商品已售罄
', '2022-11-03 20:33:53', '2022-11-03 20:33:53'); diff --git a/server/server-dao/src/main/java/cn/torna/dao/entity/DocInfoDiff.java b/server/server-dao/src/main/java/cn/torna/dao/entity/DocInfoDiff.java new file mode 100644 index 00000000..cf64a4d7 --- /dev/null +++ b/server/server-dao/src/main/java/cn/torna/dao/entity/DocInfoDiff.java @@ -0,0 +1,37 @@ +package cn.torna.dao.entity; + +import com.gitee.fastmybatis.annotation.Pk; +import com.gitee.fastmybatis.annotation.PkStrategy; +import com.gitee.fastmybatis.annotation.Table; +import lombok.Data; + +import java.time.LocalDateTime; + +/** + * 文档差异 + * + * @Author jyh + * @Date 2025/10/30 16:34 + * @Version 1.0 + **/ +@Table(name = "doc_info_diff", pk = @Pk(name = "id", strategy = PkStrategy.INCREMENT)) +@Data +public class DocInfoDiff { + + /** 数据库字段:id */ + private Long id; + + /** doc_info.id, 数据库字段:doc_id */ + private Long docId; + + /** + * 模块id,module.id + */ + private long moduleId; + + /** 差异类型: 1: 推送缺少文档,2:文档比对差异 */ + private Byte diffType; + + /** 数据库字段:gmt_create */ + private LocalDateTime gmtCreate; +} diff --git a/server/server-dao/src/main/java/cn/torna/dao/entity/DocInfoExt.java b/server/server-dao/src/main/java/cn/torna/dao/entity/DocInfoExt.java new file mode 100644 index 00000000..f2c75411 --- /dev/null +++ b/server/server-dao/src/main/java/cn/torna/dao/entity/DocInfoExt.java @@ -0,0 +1,41 @@ +package cn.torna.dao.entity; + +import com.gitee.fastmybatis.annotation.Pk; +import com.gitee.fastmybatis.annotation.PkStrategy; +import com.gitee.fastmybatis.annotation.Table; +import lombok.Data; + +import java.time.LocalDateTime; + +/** + * 文档信息扩展表 + * + * @Author jyh + * @Date 2025/11/3 09:02 + * @Version 1.0 + **/ +@Table(name = "doc_info_ext", pk = @Pk(name = "id", strategy = PkStrategy.INCREMENT)) +@Data +public class DocInfoExt { + + /** 数据库字段:id */ + private Long id; + + /** doc_info.id, 数据库字段:doc_id */ + private Long docId; + + /** 模块id,module.id */ + private long moduleId; + + /** 文档属性 */ + private String docProp; + + /** 文档属性值 */ + private String docValue; + + /** 数据库字段:gmt_create */ + private LocalDateTime gmtCreate; + + /** 数据库字段:gmt_modified */ + private LocalDateTime gmtModified; +} diff --git a/server/server-dao/src/main/java/cn/torna/dao/mapper/DocInfoDiffMapper.java b/server/server-dao/src/main/java/cn/torna/dao/mapper/DocInfoDiffMapper.java new file mode 100644 index 00000000..96ee87d8 --- /dev/null +++ b/server/server-dao/src/main/java/cn/torna/dao/mapper/DocInfoDiffMapper.java @@ -0,0 +1,12 @@ +package cn.torna.dao.mapper; + +import cn.torna.dao.entity.DocInfoDiff; +import com.gitee.fastmybatis.core.mapper.BaseMapper; + +/** + * @Author jyh + * @Date 2025/10/30 16:40 + * @Version 1.0 + **/ +public interface DocInfoDiffMapper extends BaseMapper { +} diff --git a/server/server-dao/src/main/java/cn/torna/dao/mapper/DocInfoExtMapper.java b/server/server-dao/src/main/java/cn/torna/dao/mapper/DocInfoExtMapper.java new file mode 100644 index 00000000..2c218b90 --- /dev/null +++ b/server/server-dao/src/main/java/cn/torna/dao/mapper/DocInfoExtMapper.java @@ -0,0 +1,13 @@ +package cn.torna.dao.mapper; + +import cn.torna.dao.entity.DocInfoExt; +import com.gitee.fastmybatis.core.mapper.BaseMapper; + +/** + * + * @Author jyh + * @Date 2025/11/3 09:09 + * @Version 1.0 + **/ +public interface DocInfoExtMapper extends BaseMapper { +} diff --git a/server/server-service/src/main/java/cn/torna/service/DocInfoService.java b/server/server-service/src/main/java/cn/torna/service/DocInfoService.java index 4d61b326..b2cade9b 100755 --- a/server/server-service/src/main/java/cn/torna/service/DocInfoService.java +++ b/server/server-service/src/main/java/cn/torna/service/DocInfoService.java @@ -17,6 +17,8 @@ import cn.torna.common.util.IdGen; import cn.torna.common.util.Markdown2HtmlUtil; import cn.torna.common.util.TreeUtil; import cn.torna.dao.entity.DocInfo; +import cn.torna.dao.entity.DocInfoDiff; +import cn.torna.dao.entity.DocInfoExt; import cn.torna.dao.entity.DocInfoPush; import cn.torna.dao.entity.DocParam; import cn.torna.dao.entity.DocParamDiff; @@ -27,26 +29,15 @@ import cn.torna.dao.entity.ModuleEnvironment; import cn.torna.dao.entity.ModuleEnvironmentParam; import cn.torna.dao.entity.UserDingtalkInfo; import cn.torna.dao.entity.UserWeComInfo; +import cn.torna.dao.mapper.DocInfoDiffMapper; +import cn.torna.dao.mapper.DocInfoExtMapper; import cn.torna.dao.mapper.DocInfoMapper; import cn.torna.dao.mapper.DocInfoPushMapper; import cn.torna.dao.mapper.DocParamDiffMapper; import cn.torna.dao.mapper.UserDingtalkInfoMapper; import cn.torna.dao.mapper.UserWeComInfoMapper; import cn.torna.manager.doc.DataType; -import cn.torna.service.dto.DocFolderCreateDTO; -import cn.torna.service.dto.DocInfoDTO; -import cn.torna.service.dto.DocItemCreateDTO; -import cn.torna.service.dto.DocListFormDTO; -import cn.torna.service.dto.DocMeta; -import cn.torna.service.dto.DocParamDTO; -import cn.torna.service.dto.DocParamDiffDTO; -import cn.torna.service.dto.DocParamPushDTO; -import cn.torna.service.dto.DocRefDTO; -import cn.torna.service.dto.DubboInfoDTO; -import cn.torna.service.dto.EnumInfoDTO; -import cn.torna.service.dto.EnumItemDTO; -import cn.torna.service.dto.ModuleEnvironmentDTO; -import cn.torna.service.dto.UpdateDocFolderDTO; +import cn.torna.service.dto.*; import cn.torna.service.event.DocAddEvent; import cn.torna.service.event.DocUpdateEvent; import com.gitee.fastmybatis.core.PageInfo; @@ -141,6 +132,11 @@ public class DocInfoService extends BaseLambdaService { @Autowired private DocParamDiffMapper docParamDiffMapper; + @Autowired + private DocInfoDiffMapper docInfoDiffMapper; + + @Autowired + private DocInfoExtMapper docInfoExtMapper; /** * 查询模块下的所有文档 @@ -285,18 +281,33 @@ public class DocInfoService extends BaseLambdaService { } /** - * 返回文档比对结果 + * 返回参数比对结果 * * @param docId * @return */ - public List getCompareResult(long docId) { + public List getParamCompareResult(long docId) { Query query = Query.create().eq("doc_id", docId).orderByAsc("order_index"); List docParamDiffList = docParamDiffMapper.list(query); return docParamDiffList.stream().map(item -> CopyUtil.copyBean(item, DocParamDiffDTO::new)) .collect(Collectors.toList()); } + /** + * 获取文档比对结果 + * + * @param moduleId + * @return + */ + public List getDocCompareResult(Long moduleId) { + List docInfoDiffList = docInfoDiffMapper.listByField(DocInfoDiff::getModuleId, moduleId); + return docInfoDiffList.stream().map(docInfoDiff -> { + DocInfoDiffDTO docInfoDiffDTO = new DocInfoDiffDTO(); + CopyUtil.copyProperties(docInfoDiff, docInfoDiffDTO); + return docInfoDiffDTO; + }).collect(Collectors.toList()); + } + /** * 返回文档详情 * @@ -1027,7 +1038,7 @@ public class DocInfoService extends BaseLambdaService { * * @param moduleId */ - public void compareDoc(long moduleId) { + public void compareMonitorDoc(long moduleId) { // 获取平台文档 List docInfoList = this.listDocDetail(moduleId); Map docInfoMap = docInfoList.stream().filter(item -> item.getIsFolder() == 0) @@ -1037,46 +1048,113 @@ public class DocInfoService extends BaseLambdaService { List docInfoPushList = docInfoPushMapper.listByField(DocInfoPush::getModuleId, moduleId); Map docInfoPushMap = docInfoPushList.stream().collect(Collectors.toMap(item -> item.getDocKey(), item -> item, (existing, replacement) -> existing)); + + // 获取文档参数忽略比对数据 + Query docInfoExtQuery = Query.create().eq("module_id", moduleId).eq("doc_prop", "isIgnoreCompareParam"); + List ignoreCompareParamDocIds = docInfoExtMapper.listUniqueValue(docInfoExtQuery, DocInfoExt::getDocId); // 遍历比对文档 docInfoMap.forEach((docKey, docInfoDTO) -> { if (docInfoPushMap.get(docKey) != null) { - DocInfoPush docInfoPush = docInfoPushMap.get(docKey); - log.info("开始比对文档【id:{},name:{},url:{},httpMethod:{}】", docInfoDTO.getId(), docInfoDTO.getName(), - docInfoDTO.getUrl(), docInfoDTO.getHttpMethod()); - // 获取平台文档参数 - List params = docParamService.listByField(DocParam::getDocId, docInfoDTO.getId()); - params.sort(Comparator.comparing(DocParam::getOrderIndex)); - Map> paramsMap = params.stream() - .collect(Collectors.groupingBy(DocParam::getStyle)); - // 获取推送文档参数 - List pushParams = docParamPushService.listByField(DocParamPush::getDocId, docInfoPush.getId()); - pushParams.sort(Comparator.comparing(DocParamPush::getOrderIndex)); - Map> pushParamsMap = pushParams.stream() - .collect(Collectors.groupingBy(DocParamPush::getStyle)); - // 按类型比对参数 - paramsMap.forEach((paramType, docParams) -> { - log.info("开始比对参数类型【{}】", paramType); - List pushDocParams = pushParamsMap.get(paramType) == null ? new ArrayList<>() : pushParamsMap.get(paramType); - List docParamDiffList = compareParam(docParams, pushDocParams); - if (docParamDiffList.size() > 0) { - log.info("【id:{},name:{},url:{},httpMethod:{}】参数类型【{}】有差异,更新比对结果", docInfoDTO.getId(), docInfoDTO.getName(), - docInfoDTO.getUrl(), docInfoDTO.getHttpMethod(), paramType); - } else { - log.debug("【id:{},name:{},url:{},httpMethod:{}】参数类型【{}】无差异,清除比对结果", docInfoDTO.getId(), docInfoDTO.getName(), - docInfoDTO.getUrl(), docInfoDTO.getHttpMethod(), paramType); - } - updateDocParamDiffByType(docParamDiffList, docInfoDTO.getId(), paramType); - }); + if (!ignoreCompareParamDocIds.contains(docInfoDTO.getId())) { // 未忽略参数比对 + DocInfoPush docInfoPush = docInfoPushMap.get(docKey); + log.info("开始比对文档【id:{},name:{},url:{},httpMethod:{}】", docInfoDTO.getId(), docInfoDTO.getName(), + docInfoDTO.getUrl(), docInfoDTO.getHttpMethod()); + // 获取平台文档参数 + List params = docParamService.listByField(DocParam::getDocId, docInfoDTO.getId()); + params.sort(Comparator.comparing(DocParam::getOrderIndex)); + Map> paramsMap = params.stream() + .collect(Collectors.groupingBy(DocParam::getStyle)); + // 获取推送文档参数 + List pushParams = docParamPushService.listByField(DocParamPush::getDocId, docInfoPush.getId()); + pushParams.sort(Comparator.comparing(DocParamPush::getOrderIndex)); + Map> pushParamsMap = pushParams.stream() + .collect(Collectors.groupingBy(DocParamPush::getStyle)); + // 按类型比对参数 + paramsMap.forEach((paramType, docParams) -> { + log.info("开始比对参数类型【{}】", paramType); + List pushDocParams = pushParamsMap.get(paramType) == null ? new ArrayList<>() : pushParamsMap.get(paramType); + List docParamDiffList = compareParam(docParams, pushDocParams); + if (docParamDiffList.size() > 0) { + log.info("【id:{},name:{},url:{},httpMethod:{}】参数类型【{}】有差异,更新比对结果", docInfoDTO.getId(), docInfoDTO.getName(), + docInfoDTO.getUrl(), docInfoDTO.getHttpMethod(), paramType); + docInfoDiffMapper.deleteByColumn(DocInfoDiff::getDocId, docInfoDTO.getId()); + saveDocInfoCompareResult(docInfoDTO, moduleId, (byte) 2); + } else { + log.debug("【id:{},name:{},url:{},httpMethod:{}】参数类型【{}】无差异,清除比对结果", docInfoDTO.getId(), docInfoDTO.getName(), + docInfoDTO.getUrl(), docInfoDTO.getHttpMethod(), paramType); + docInfoDiffMapper.deleteByColumn(DocInfoDiff::getDocId, docInfoDTO.getId()); + } + updateDocParamDiffByType(docParamDiffList, docInfoDTO.getId(), paramType); + }); + } } else { log.info("平台文档【id:{},name:{},url:{},httpMethod:{}】无推送内容!", docInfoDTO.getId(), docInfoDTO.getName(), docInfoDTO.getUrl(), docInfoDTO.getHttpMethod()); - // 记录数据库 + docInfoDiffMapper.deleteByColumn(DocInfoDiff::getDocId, docInfoDTO.getId()); + saveDocInfoCompareResult(docInfoDTO, moduleId, (byte) 1); } }); log.info("完成模块【{}】比对,更新比对状态缓存", moduleId); ScheduleTask.MODULE_COMPARE_STATUS_CACHE.put(moduleId, false); } + /** + * 是否忽略参数比较(应用于动态参数) + * 逻辑:status == false 直接删除条目,否则新增条目 docValue = 1 + * + * @param docId + * @param moduleId + * @param status + */ + @Transactional(rollbackFor = Exception.class) + public void ignoreCompareParam(Long docId, Long moduleId, boolean status) { + if (status) { + DocInfoExt docInfoExt = new DocInfoExt(); + docInfoExt.setDocId(docId); + docInfoExt.setModuleId(moduleId); + docInfoExt.setDocProp("isIgnoreCompareParam"); + docInfoExt.setDocValue("1"); + docInfoExtMapper.save(docInfoExt); + + log.info("平台文档【id:{}】开启禁止参数比对,清除之前比对结果!", docId); + docParamDiffMapper.deleteByColumn(DocParamDiff::getDocId, docId); + Query query = Query.create().eq("doc_id", docId).eq("diff_type", (byte) 2); + docInfoDiffMapper.deleteByQuery(query); + } else { + Query query = Query.create() + .eq("doc_prop", "isIgnoreCompareParam") + .eq("doc_id", docId) + .eq("module_id", moduleId); + docInfoExtMapper.deleteByQuery(query); + + } + } + + /** + * 列出该文档属性和模块ID下所有扩展属性 + * + * @param docProp + * @param moduleId + * @return 扩展属性列表 + */ + public List listDocExtByPropAndModuleId(String docProp, Long moduleId) { + Query query = Query.create().eq("doc_prop", docProp).eq("module_id", moduleId); + List docInfoExtList = docInfoExtMapper.list(query); + return docInfoExtList.stream().map(item -> { + DocInfoExtDTO docInfoExtDTO = new DocInfoExtDTO(); + CopyUtil.copyProperties(item, docInfoExtDTO); + return docInfoExtDTO; + }).collect(Collectors.toList()); + } + + private void saveDocInfoCompareResult(DocInfoDTO docInfoDTO, long moduleId, byte diffType) { + DocInfoDiff docInfoDiff = new DocInfoDiff(); + docInfoDiff.setDocId(docInfoDTO.getId()); + docInfoDiff.setDiffType(diffType); + docInfoDiff.setModuleId(moduleId); + docInfoDiffMapper.save(docInfoDiff); + } + /** * 保存比对结果列表 * diff --git a/server/server-service/src/main/java/cn/torna/service/ScheduleTask.java b/server/server-service/src/main/java/cn/torna/service/ScheduleTask.java index 983d5e83..f55a7530 100644 --- a/server/server-service/src/main/java/cn/torna/service/ScheduleTask.java +++ b/server/server-service/src/main/java/cn/torna/service/ScheduleTask.java @@ -64,7 +64,7 @@ public class ScheduleTask { compareModuleIdList.forEach(moduleId -> { if (MODULE_COMPARE_STATUS_CACHE.getOrDefault(moduleId, false)) { log.info("==========开始比对模块【{}】推送文档=====", moduleId); - docInfoService.compareDoc(moduleId); + docInfoService.compareMonitorDoc(moduleId); } }); } diff --git a/server/server-service/src/main/java/cn/torna/service/dto/DocInfoDiffDTO.java b/server/server-service/src/main/java/cn/torna/service/dto/DocInfoDiffDTO.java new file mode 100644 index 00000000..9673f714 --- /dev/null +++ b/server/server-service/src/main/java/cn/torna/service/dto/DocInfoDiffDTO.java @@ -0,0 +1,37 @@ +package cn.torna.service.dto; + +import cn.torna.common.support.IdCodec; +import com.alibaba.fastjson.annotation.JSONField; +import lombok.Data; + +import java.time.LocalDateTime; + +/** + * + * @Author jyh + * @Date 2025/10/30 16:36 + * @Version 1.0 + **/ +@Data +public class DocInfoDiffDTO { + + @JSONField(serializeUsing = IdCodec.class, deserializeUsing = IdCodec.class) + private Long id; + + /** + * doc_info.id, 数据库字段:doc_id + */ + @JSONField(serializeUsing = IdCodec.class, deserializeUsing = IdCodec.class) + private Long docId; + + /** + * 模块id,module.id + */ + private long moduleId; + + /** 差异类型: 1: 推送缺少文档,2:文档比对差异 */ + private Byte diffType; + + /** 数据库字段:gmt_create */ + private LocalDateTime gmtCreate; +} diff --git a/server/server-service/src/main/java/cn/torna/service/dto/DocInfoExtDTO.java b/server/server-service/src/main/java/cn/torna/service/dto/DocInfoExtDTO.java new file mode 100644 index 00000000..50b63262 --- /dev/null +++ b/server/server-service/src/main/java/cn/torna/service/dto/DocInfoExtDTO.java @@ -0,0 +1,41 @@ +package cn.torna.service.dto; + +import cn.torna.common.support.IdCodec; +import com.alibaba.fastjson.annotation.JSONField; +import lombok.Data; + +import java.time.LocalDateTime; + +/** + * + * @Author jyh + * @Date 2025/11/3 09:07 + * @Version 1.0 + **/ +@Data +public class DocInfoExtDTO { + + @JSONField(serializeUsing = IdCodec.class, deserializeUsing = IdCodec.class) + private Long id; + + /** + * doc_info.id, 数据库字段:doc_id + */ + @JSONField(serializeUsing = IdCodec.class, deserializeUsing = IdCodec.class) + private Long docId; + + /** 模块id,module.id */ + private long moduleId; + + /** 文档属性 */ + private String docProp; + + /** 文档属性值 */ + private String docValue; + + /** 数据库字段:gmt_create */ + private LocalDateTime gmtCreate; + + /** 数据库字段:gmt_modified */ + private LocalDateTime gmtModified; +} diff --git a/server/server-web/src/main/java/cn/torna/web/controller/doc/DocController.java b/server/server-web/src/main/java/cn/torna/web/controller/doc/DocController.java index 0ed92ec5..4759a446 100644 --- a/server/server-web/src/main/java/cn/torna/web/controller/doc/DocController.java +++ b/server/server-web/src/main/java/cn/torna/web/controller/doc/DocController.java @@ -10,7 +10,7 @@ import cn.torna.common.enums.ParamStyleEnum; import cn.torna.common.exception.BizException; import cn.torna.common.util.CopyUtil; import cn.torna.dao.entity.DocInfo; -import cn.torna.dao.entity.DocParamDiff; +import cn.torna.dao.entity.DocInfoExt; import cn.torna.dao.entity.ModuleEnvironment; import cn.torna.dao.entity.ModuleEnvironmentParam; import cn.torna.service.DocInfoService; @@ -39,6 +39,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.util.CollectionUtils; import org.springframework.util.StringUtils; import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; @@ -69,18 +70,6 @@ public class DocController { @Autowired private ModuleEnvironmentService moduleEnvironmentService; - /** - * 比对文档 - * - * @param moduleId - * @return 比对结果 - */ - @GetMapping("compare") - public Result compareDoc(@HashId Long moduleId) { - docInfoService.compareDoc(moduleId); - return Result.ok(); - } - /** * 获取项目文档目录,可用于文档菜单 * @@ -395,4 +384,29 @@ public class DocController { return Result.ok(); } + /** + * 比对文档 + * + * @param moduleId + * @return 比对结果 + */ + @GetMapping("monitor/compare") + public Result compareMonitorDoc(@HashId Long moduleId) { + docInfoService.compareMonitorDoc(moduleId); + return Result.ok(); + } + + /** + * 是否忽略参数比较(应用于动态参数) + * + * @param docId + * @param moduleId + * @param status 1:是,0:否 + * @return + */ + @GetMapping("monitor/ignore/status") + public Result ignoreCompareParam(@HashId Long docId, @HashId Long moduleId, boolean status) { + docInfoService.ignoreCompareParam(docId, moduleId, status); + return Result.ok(); + } } diff --git a/server/server-web/src/main/java/cn/torna/web/controller/doc/ViewController.java b/server/server-web/src/main/java/cn/torna/web/controller/doc/ViewController.java index 19c17942..3298957a 100644 --- a/server/server-web/src/main/java/cn/torna/web/controller/doc/ViewController.java +++ b/server/server-web/src/main/java/cn/torna/web/controller/doc/ViewController.java @@ -5,7 +5,7 @@ import cn.torna.common.bean.Result; import cn.torna.common.bean.User; import cn.torna.common.exception.BizException; import cn.torna.common.util.CopyUtil; -import cn.torna.dao.entity.DocParamDiff; +import cn.torna.common.util.IdUtil; import cn.torna.dao.entity.Project; import cn.torna.dao.entity.Space; import cn.torna.dao.entity.SpaceUser; @@ -14,6 +14,8 @@ import cn.torna.service.DocViewService; import cn.torna.service.ProjectService; import cn.torna.service.SpaceService; import cn.torna.service.dto.DocInfoDTO; +import cn.torna.service.dto.DocInfoDiffDTO; +import cn.torna.service.dto.DocInfoExtDTO; import cn.torna.service.dto.DocParamDiffDTO; import cn.torna.service.dto.ProjectDTO; import cn.torna.service.dto.SpaceProjectDTO; @@ -23,6 +25,7 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.util.CollectionUtils; import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @@ -119,15 +122,40 @@ public class ViewController { } /** - * 比对结果 + * 参数比对结果 * * @param id 主键 * @return 比对结果 */ - @GetMapping("compare/result") - public Result> compareResult(@HashId Long id) { - List compareResultList = docInfoService.getCompareResult(id); + @GetMapping("compare/param/result") + public Result> paramCompareResult(@HashId Long id) { + List compareResultList = docInfoService.getParamCompareResult(id); return Result.ok(compareResultList); } + /** + * 文档比对结果 + * + * @param moduleId 主键 + * @return 比对结果 + */ + @GetMapping("compare/doc/result") + public Result> docCompareResult(@HashId Long moduleId) { + List compareResultList = docInfoService.getDocCompareResult(moduleId); + return Result.ok(compareResultList); + } + + /** + * 列出该文档属性和模块ID下所有扩展属性 + * + * @param docProp + * @param moduleId + * @return 扩展属性列表 + */ + @GetMapping("ext/{docProp}/{moduleId}/list") + public Result> listDocExtByPropAndModuleId(@PathVariable("docProp") String docProp, + @PathVariable("moduleId") String moduleId) { + return Result.ok(docInfoService.listDocExtByPropAndModuleId(docProp, IdUtil.decode(moduleId))); + } + } -- Gitee