From addea20fa1b2c4fc02d2fbbcde6c870d9ce3ff73 Mon Sep 17 00:00:00 2001 From: wjj <2069666735@qq.com> Date: Tue, 21 Apr 2026 16:46:47 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E9=A1=B9=E7=9B=AE=E8=AF=81?= =?UTF-8?q?=E6=8D=AE=E5=BA=93=E4=B8=80=E6=9C=9F=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/CcdiEvidenceController.java | 69 +++++++ .../domain/dto/CcdiEvidenceQueryDTO.java | 21 ++ .../domain/dto/CcdiEvidenceSaveDTO.java | 54 ++++++ .../project/domain/entity/CcdiEvidence.java | 84 ++++++++ .../project/domain/vo/CcdiEvidenceVO.java | 56 ++++++ ...diProjectPersonAnalysisObjectRecordVO.java | 2 + .../project/mapper/CcdiEvidenceMapper.java | 12 ++ .../project/service/ICcdiEvidenceService.java | 40 ++++ .../service/impl/CcdiEvidenceServiceImpl.java | 84 ++++++++ .../project/CcdiProjectOverviewMapper.xml | 1 + ...ce-minimal-feature-validation-checklist.md | 44 +++++ ...dence-minimal-feature-validation-record.md | 51 +++++ ruoyi-ui/src/api/ccdiEvidence.js | 27 +++ ruoyi-ui/src/utils/ccdiEvidence.js | 78 ++++++++ ruoyi-ui/src/utils/md5.js | 161 ++++++++++++++++ .../components/detail/DetailQuery.vue | 60 +++++- .../detail/EvidenceConfirmDialog.vue | 136 +++++++++++++ .../components/detail/EvidenceDrawer.vue | 180 ++++++++++++++++++ .../detail/FamilyAssetLiabilitySection.vue | 81 +++++++- .../components/detail/PreliminaryCheck.vue | 6 +- .../detail/ProjectAnalysisAbnormalTab.vue | 99 +++++++++- .../detail/ProjectAnalysisDialog.vue | 7 +- .../components/detail/RiskDetailSection.vue | 62 +++++- .../components/detail/SpecialCheck.vue | 1 + ruoyi-ui/src/views/ccdiProject/detail.vue | 60 ++++++ .../2026-04-21-create-ccdi-evidence.sql | 26 +++ 26 files changed, 1489 insertions(+), 13 deletions(-) create mode 100644 ccdi-project/src/main/java/com/ruoyi/ccdi/project/controller/CcdiEvidenceController.java create mode 100644 ccdi-project/src/main/java/com/ruoyi/ccdi/project/domain/dto/CcdiEvidenceQueryDTO.java create mode 100644 ccdi-project/src/main/java/com/ruoyi/ccdi/project/domain/dto/CcdiEvidenceSaveDTO.java create mode 100644 ccdi-project/src/main/java/com/ruoyi/ccdi/project/domain/entity/CcdiEvidence.java create mode 100644 ccdi-project/src/main/java/com/ruoyi/ccdi/project/domain/vo/CcdiEvidenceVO.java create mode 100644 ccdi-project/src/main/java/com/ruoyi/ccdi/project/mapper/CcdiEvidenceMapper.java create mode 100644 ccdi-project/src/main/java/com/ruoyi/ccdi/project/service/ICcdiEvidenceService.java create mode 100644 ccdi-project/src/main/java/com/ruoyi/ccdi/project/service/impl/CcdiEvidenceServiceImpl.java create mode 100644 docs/tests/plans/2026-04-21-evidence-minimal-feature-validation-checklist.md create mode 100644 docs/tests/records/2026-04-21-evidence-minimal-feature-validation-record.md create mode 100644 ruoyi-ui/src/api/ccdiEvidence.js create mode 100644 ruoyi-ui/src/utils/ccdiEvidence.js create mode 100644 ruoyi-ui/src/utils/md5.js create mode 100644 ruoyi-ui/src/views/ccdiProject/components/detail/EvidenceConfirmDialog.vue create mode 100644 ruoyi-ui/src/views/ccdiProject/components/detail/EvidenceDrawer.vue create mode 100644 sql/migration/2026-04-21-create-ccdi-evidence.sql diff --git a/ccdi-project/src/main/java/com/ruoyi/ccdi/project/controller/CcdiEvidenceController.java b/ccdi-project/src/main/java/com/ruoyi/ccdi/project/controller/CcdiEvidenceController.java new file mode 100644 index 00000000..c977876b --- /dev/null +++ b/ccdi-project/src/main/java/com/ruoyi/ccdi/project/controller/CcdiEvidenceController.java @@ -0,0 +1,69 @@ +package com.ruoyi.ccdi.project.controller; + +import com.ruoyi.ccdi.project.domain.dto.CcdiEvidenceQueryDTO; +import com.ruoyi.ccdi.project.domain.dto.CcdiEvidenceSaveDTO; +import com.ruoyi.ccdi.project.domain.vo.CcdiEvidenceVO; +import com.ruoyi.ccdi.project.service.ICcdiEvidenceService; +import com.ruoyi.common.core.controller.BaseController; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.utils.SecurityUtils; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +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; +import org.springframework.web.bind.annotation.RestController; + +import java.util.List; + +/** + * 项目证据Controller + * + * @author ruoyi + */ +@RestController +@RequestMapping("/ccdi/evidence") +@Tag(name = "项目证据") +public class CcdiEvidenceController extends BaseController { + + @Resource + private ICcdiEvidenceService evidenceService; + + /** + * 保存证据 + */ + @PostMapping + @Operation(summary = "保存证据") + @PreAuthorize("@ss.hasPermi('ccdi:project:query')") + public AjaxResult saveEvidence(@Validated @RequestBody CcdiEvidenceSaveDTO dto) { + CcdiEvidenceVO vo = evidenceService.saveEvidence(dto, SecurityUtils.getUsername()); + return AjaxResult.success("证据入库成功", vo); + } + + /** + * 查询项目证据列表 + */ + @GetMapping("/list") + @Operation(summary = "查询项目证据列表") + @PreAuthorize("@ss.hasPermi('ccdi:project:query')") + public AjaxResult listEvidence(CcdiEvidenceQueryDTO queryDTO) { + List list = evidenceService.listEvidence(queryDTO); + return AjaxResult.success(list); + } + + /** + * 查询证据详情 + */ + @GetMapping("/{evidenceId}") + @Operation(summary = "查询证据详情") + @PreAuthorize("@ss.hasPermi('ccdi:project:query')") + public AjaxResult getEvidence(@PathVariable Long evidenceId) { + CcdiEvidenceVO vo = evidenceService.getEvidence(evidenceId); + return AjaxResult.success(vo); + } +} diff --git a/ccdi-project/src/main/java/com/ruoyi/ccdi/project/domain/dto/CcdiEvidenceQueryDTO.java b/ccdi-project/src/main/java/com/ruoyi/ccdi/project/domain/dto/CcdiEvidenceQueryDTO.java new file mode 100644 index 00000000..5ffe3813 --- /dev/null +++ b/ccdi-project/src/main/java/com/ruoyi/ccdi/project/domain/dto/CcdiEvidenceQueryDTO.java @@ -0,0 +1,21 @@ +package com.ruoyi.ccdi.project.domain.dto; + +import lombok.Data; + +/** + * 项目证据查询入参 + * + * @author ruoyi + */ +@Data +public class CcdiEvidenceQueryDTO { + + /** 项目ID */ + private Long projectId; + + /** 证据类型:FLOW/MODEL/ASSET */ + private String evidenceType; + + /** 关键词:姓名、标题、摘要、证据编号 */ + private String keyword; +} diff --git a/ccdi-project/src/main/java/com/ruoyi/ccdi/project/domain/dto/CcdiEvidenceSaveDTO.java b/ccdi-project/src/main/java/com/ruoyi/ccdi/project/domain/dto/CcdiEvidenceSaveDTO.java new file mode 100644 index 00000000..a26addad --- /dev/null +++ b/ccdi-project/src/main/java/com/ruoyi/ccdi/project/domain/dto/CcdiEvidenceSaveDTO.java @@ -0,0 +1,54 @@ +package com.ruoyi.ccdi.project.domain.dto; + +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +/** + * 保存项目证据入参 + * + * @author ruoyi + */ +@Data +public class CcdiEvidenceSaveDTO { + + /** 项目ID */ + @NotNull(message = "项目ID不能为空") + private Long projectId; + + /** 证据类型:FLOW/MODEL/ASSET */ + @NotBlank(message = "证据类型不能为空") + private String evidenceType; + + /** 关联人员姓名 */ + @NotBlank(message = "关联人员不能为空") + private String relatedPersonName; + + /** 关联人员标识 */ + private String relatedPersonId; + + /** 证据标题 */ + @NotBlank(message = "证据标题不能为空") + private String evidenceTitle; + + /** 证据摘要 */ + @NotBlank(message = "证据摘要不能为空") + private String evidenceSummary; + + /** 来源类型 */ + @NotBlank(message = "来源类型不能为空") + private String sourceType; + + /** 来源记录ID */ + private String sourceRecordId; + + /** 来源页面名称 */ + private String sourcePage; + + /** 证据快照JSON */ + private String snapshotJson; + + /** 确认理由/备注 */ + @NotBlank(message = "确认理由/备注不能为空") + private String confirmReason; +} diff --git a/ccdi-project/src/main/java/com/ruoyi/ccdi/project/domain/entity/CcdiEvidence.java b/ccdi-project/src/main/java/com/ruoyi/ccdi/project/domain/entity/CcdiEvidence.java new file mode 100644 index 00000000..c3e8fb87 --- /dev/null +++ b/ccdi-project/src/main/java/com/ruoyi/ccdi/project/domain/entity/CcdiEvidence.java @@ -0,0 +1,84 @@ +package com.ruoyi.ccdi.project.domain.entity; + +import com.baomidou.mybatisplus.annotation.FieldFill; +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +import java.io.Serial; +import java.io.Serializable; +import java.util.Date; + +/** + * 项目证据对象 ccdi_evidence + * + * @author ruoyi + */ +@Data +@TableName("ccdi_evidence") +public class CcdiEvidence implements Serializable { + + @Serial + private static final long serialVersionUID = 1L; + + /** 证据ID */ + @TableId(type = IdType.AUTO) + private Long evidenceId; + + /** 项目ID */ + private Long projectId; + + /** 证据类型:FLOW/MODEL/ASSET */ + private String evidenceType; + + /** 关联人员姓名 */ + private String relatedPersonName; + + /** 关联人员标识,优先存身份证号或员工号 */ + private String relatedPersonId; + + /** 证据标题 */ + private String evidenceTitle; + + /** 证据摘要 */ + private String evidenceSummary; + + /** 来源类型:BANK_STATEMENT/MODEL_DETAIL/ASSET_DETAIL */ + private String sourceType; + + /** 来源记录ID */ + private String sourceRecordId; + + /** 来源页面名称 */ + private String sourcePage; + + /** 证据快照JSON */ + private String snapshotJson; + + /** 确认理由/备注 */ + private String confirmReason; + + /** 确认人 */ + private String confirmBy; + + /** 确认时间 */ + private Date confirmTime; + + /** 创建者 */ + @TableField(fill = FieldFill.INSERT) + private String createBy; + + /** 创建时间 */ + @TableField(fill = FieldFill.INSERT) + private Date createTime; + + /** 更新者 */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private String updateBy; + + /** 更新时间 */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private Date updateTime; +} diff --git a/ccdi-project/src/main/java/com/ruoyi/ccdi/project/domain/vo/CcdiEvidenceVO.java b/ccdi-project/src/main/java/com/ruoyi/ccdi/project/domain/vo/CcdiEvidenceVO.java new file mode 100644 index 00000000..8668a05f --- /dev/null +++ b/ccdi-project/src/main/java/com/ruoyi/ccdi/project/domain/vo/CcdiEvidenceVO.java @@ -0,0 +1,56 @@ +package com.ruoyi.ccdi.project.domain.vo; + +import lombok.Data; + +import java.util.Date; + +/** + * 项目证据返回对象 + * + * @author ruoyi + */ +@Data +public class CcdiEvidenceVO { + + /** 证据ID */ + private Long evidenceId; + + /** 项目ID */ + private Long projectId; + + /** 证据类型:FLOW/MODEL/ASSET */ + private String evidenceType; + + /** 关联人员姓名 */ + private String relatedPersonName; + + /** 关联人员标识 */ + private String relatedPersonId; + + /** 证据标题 */ + private String evidenceTitle; + + /** 证据摘要 */ + private String evidenceSummary; + + /** 来源类型 */ + private String sourceType; + + /** 来源记录ID */ + private String sourceRecordId; + + /** 来源页面名称 */ + private String sourcePage; + + /** 证据快照JSON */ + private String snapshotJson; + + /** 确认理由/备注 */ + private String confirmReason; + + /** 确认人 */ + private String confirmBy; + + /** 确认时间 */ + private Date confirmTime; +} diff --git a/ccdi-project/src/main/java/com/ruoyi/ccdi/project/domain/vo/CcdiProjectPersonAnalysisObjectRecordVO.java b/ccdi-project/src/main/java/com/ruoyi/ccdi/project/domain/vo/CcdiProjectPersonAnalysisObjectRecordVO.java index 52d26bb2..6df7a53a 100644 --- a/ccdi-project/src/main/java/com/ruoyi/ccdi/project/domain/vo/CcdiProjectPersonAnalysisObjectRecordVO.java +++ b/ccdi-project/src/main/java/com/ruoyi/ccdi/project/domain/vo/CcdiProjectPersonAnalysisObjectRecordVO.java @@ -10,6 +10,8 @@ import lombok.Data; @Data public class CcdiProjectPersonAnalysisObjectRecordVO { + private String modelCode; + private String title; private String subtitle; diff --git a/ccdi-project/src/main/java/com/ruoyi/ccdi/project/mapper/CcdiEvidenceMapper.java b/ccdi-project/src/main/java/com/ruoyi/ccdi/project/mapper/CcdiEvidenceMapper.java new file mode 100644 index 00000000..866561ee --- /dev/null +++ b/ccdi-project/src/main/java/com/ruoyi/ccdi/project/mapper/CcdiEvidenceMapper.java @@ -0,0 +1,12 @@ +package com.ruoyi.ccdi.project.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.ruoyi.ccdi.project.domain.entity.CcdiEvidence; + +/** + * 项目证据Mapper接口 + * + * @author ruoyi + */ +public interface CcdiEvidenceMapper extends BaseMapper { +} diff --git a/ccdi-project/src/main/java/com/ruoyi/ccdi/project/service/ICcdiEvidenceService.java b/ccdi-project/src/main/java/com/ruoyi/ccdi/project/service/ICcdiEvidenceService.java new file mode 100644 index 00000000..ebfe15f1 --- /dev/null +++ b/ccdi-project/src/main/java/com/ruoyi/ccdi/project/service/ICcdiEvidenceService.java @@ -0,0 +1,40 @@ +package com.ruoyi.ccdi.project.service; + +import com.ruoyi.ccdi.project.domain.dto.CcdiEvidenceQueryDTO; +import com.ruoyi.ccdi.project.domain.dto.CcdiEvidenceSaveDTO; +import com.ruoyi.ccdi.project.domain.vo.CcdiEvidenceVO; + +import java.util.List; + +/** + * 项目证据Service接口 + * + * @author ruoyi + */ +public interface ICcdiEvidenceService { + + /** + * 保存证据 + * + * @param dto 保存入参 + * @param operator 操作人 + * @return 证据 + */ + CcdiEvidenceVO saveEvidence(CcdiEvidenceSaveDTO dto, String operator); + + /** + * 查询项目证据列表 + * + * @param queryDTO 查询入参 + * @return 证据列表 + */ + List listEvidence(CcdiEvidenceQueryDTO queryDTO); + + /** + * 查询证据详情 + * + * @param evidenceId 证据ID + * @return 证据 + */ + CcdiEvidenceVO getEvidence(Long evidenceId); +} diff --git a/ccdi-project/src/main/java/com/ruoyi/ccdi/project/service/impl/CcdiEvidenceServiceImpl.java b/ccdi-project/src/main/java/com/ruoyi/ccdi/project/service/impl/CcdiEvidenceServiceImpl.java new file mode 100644 index 00000000..6626b2b5 --- /dev/null +++ b/ccdi-project/src/main/java/com/ruoyi/ccdi/project/service/impl/CcdiEvidenceServiceImpl.java @@ -0,0 +1,84 @@ +package com.ruoyi.ccdi.project.service.impl; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.ruoyi.ccdi.project.domain.dto.CcdiEvidenceQueryDTO; +import com.ruoyi.ccdi.project.domain.dto.CcdiEvidenceSaveDTO; +import com.ruoyi.ccdi.project.domain.entity.CcdiEvidence; +import com.ruoyi.ccdi.project.domain.vo.CcdiEvidenceVO; +import com.ruoyi.ccdi.project.mapper.CcdiEvidenceMapper; +import com.ruoyi.ccdi.project.service.ICcdiEvidenceService; +import com.ruoyi.common.exception.ServiceException; +import jakarta.annotation.Resource; +import org.springframework.beans.BeanUtils; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.util.StringUtils; + +import java.util.Date; +import java.util.List; + +/** + * 项目证据Service实现类 + * + * @author ruoyi + */ +@Service +public class CcdiEvidenceServiceImpl implements ICcdiEvidenceService { + + @Resource + private CcdiEvidenceMapper evidenceMapper; + + @Override + @Transactional(rollbackFor = Exception.class) + public CcdiEvidenceVO saveEvidence(CcdiEvidenceSaveDTO dto, String operator) { + CcdiEvidence evidence = new CcdiEvidence(); + BeanUtils.copyProperties(dto, evidence); + evidence.setConfirmBy(operator); + evidence.setConfirmTime(new Date()); + evidenceMapper.insert(evidence); + return toVO(evidence); + } + + @Override + public List listEvidence(CcdiEvidenceQueryDTO queryDTO) { + if (queryDTO.getProjectId() == null) { + throw new ServiceException("项目ID不能为空"); + } + LambdaQueryWrapper wrapper = new LambdaQueryWrapper() + .eq(CcdiEvidence::getProjectId, queryDTO.getProjectId()) + .orderByDesc(CcdiEvidence::getConfirmTime) + .orderByDesc(CcdiEvidence::getEvidenceId); + + if (StringUtils.hasText(queryDTO.getEvidenceType())) { + wrapper.eq(CcdiEvidence::getEvidenceType, queryDTO.getEvidenceType()); + } + if (StringUtils.hasText(queryDTO.getKeyword())) { + String keyword = queryDTO.getKeyword().trim(); + wrapper.and(item -> item + .like(CcdiEvidence::getRelatedPersonName, keyword) + .or() + .like(CcdiEvidence::getRelatedPersonId, keyword) + .or() + .like(CcdiEvidence::getEvidenceTitle, keyword) + .or() + .like(CcdiEvidence::getEvidenceSummary, keyword) + ); + } + return evidenceMapper.selectList(wrapper).stream().map(this::toVO).toList(); + } + + @Override + public CcdiEvidenceVO getEvidence(Long evidenceId) { + CcdiEvidence evidence = evidenceMapper.selectById(evidenceId); + if (evidence == null) { + throw new ServiceException("证据不存在"); + } + return toVO(evidence); + } + + private CcdiEvidenceVO toVO(CcdiEvidence evidence) { + CcdiEvidenceVO vo = new CcdiEvidenceVO(); + BeanUtils.copyProperties(evidence, vo); + return vo; + } +} diff --git a/ccdi-project/src/main/resources/mapper/ccdi/project/CcdiProjectOverviewMapper.xml b/ccdi-project/src/main/resources/mapper/ccdi/project/CcdiProjectOverviewMapper.xml index 0461042b..ad535139 100644 --- a/ccdi-project/src/main/resources/mapper/ccdi/project/CcdiProjectOverviewMapper.xml +++ b/ccdi-project/src/main/resources/mapper/ccdi/project/CcdiProjectOverviewMapper.xml @@ -741,6 +741,7 @@