diff --git a/safety-eval-adapter/src/main/java/org/qinan/safetyeval/adapter/web/regulator/RegulatorEvalReportController.java b/safety-eval-adapter/src/main/java/org/qinan/safetyeval/adapter/web/regulator/RegulatorEvalReportController.java index adb661e3..0e962b73 100644 --- a/safety-eval-adapter/src/main/java/org/qinan/safetyeval/adapter/web/regulator/RegulatorEvalReportController.java +++ b/safety-eval-adapter/src/main/java/org/qinan/safetyeval/adapter/web/regulator/RegulatorEvalReportController.java @@ -9,10 +9,7 @@ import org.qinan.safetyeval.client.co.report.EvalReportLibraryCO; import org.qinan.safetyeval.client.co.report.RegulatorEvalReportSummaryCO; import org.qinan.safetyeval.client.dto.PageResponse; import org.qinan.safetyeval.client.dto.SingleResponse; -import org.qinan.safetyeval.client.dto.regulator.RegulatorEvalReportAddCmd; -import org.qinan.safetyeval.client.dto.regulator.RegulatorEvalReportBatchDownloadCmd; -import org.qinan.safetyeval.client.dto.regulator.RegulatorEvalReportExportCmd; -import org.qinan.safetyeval.client.dto.regulator.RegulatorEvalReportPageQuery; +import org.qinan.safetyeval.client.dto.regulator.*; import org.qinan.safetyeval.domain.exception.BizException; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; @@ -23,6 +20,7 @@ import java.io.IOException; import java.net.URLEncoder; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; +import java.util.List; @Api(tags = "监管端-安评报告库") @RestController @@ -107,4 +105,10 @@ public class RegulatorEvalReportController { } return message.replace("\\", "\\\\").replace("\"", "\\\""); } + + @ApiOperation("报告抽查") + @PostMapping("/spotCheckReport") + public SingleResponse> spotCheckReport(@RequestBody SpotCheckReportCmd cmd) { + return regulatorEvalReportApi.spotCheckReport(cmd); + } } diff --git a/safety-eval-app/src/main/java/org/qinan/safetyeval/app/executor/regulator/RegulatorEvalReportExecutor.java b/safety-eval-app/src/main/java/org/qinan/safetyeval/app/executor/regulator/RegulatorEvalReportExecutor.java index 4fcc3e93..c05bb1ee 100644 --- a/safety-eval-app/src/main/java/org/qinan/safetyeval/app/executor/regulator/RegulatorEvalReportExecutor.java +++ b/safety-eval-app/src/main/java/org/qinan/safetyeval/app/executor/regulator/RegulatorEvalReportExecutor.java @@ -1,5 +1,6 @@ package org.qinan.safetyeval.app.executor.regulator; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import org.qinan.safetyeval.app.executor.support.ReportProfileCoConverter; import org.qinan.safetyeval.client.api.regulator.RegulatorEvalReportApi; import org.qinan.safetyeval.client.co.report.EvalReportLibraryCO; @@ -8,6 +9,7 @@ import org.qinan.safetyeval.client.dto.PageResponse; import org.qinan.safetyeval.client.dto.SingleResponse; import org.qinan.safetyeval.client.dto.regulator.RegulatorEvalReportAddCmd; import org.qinan.safetyeval.client.dto.regulator.RegulatorEvalReportPageQuery; +import org.qinan.safetyeval.client.dto.regulator.SpotCheckReportCmd; import org.qinan.safetyeval.domain.entity.EvalReportEntity; import org.qinan.safetyeval.domain.entity.OrgInfoEntity; import org.qinan.safetyeval.domain.gateway.OrgInfoGateway; @@ -15,6 +17,9 @@ import org.qinan.safetyeval.domain.query.EvalReportQuery; import org.qinan.safetyeval.domain.query.OrgInfoQuery; import org.qinan.safetyeval.domain.query.PageResult; import org.qinan.safetyeval.domain.service.EvalReportDomainService; +import org.qinan.safetyeval.infrastructure.dataobject.EvalReportDO; +import org.qinan.safetyeval.infrastructure.mapper.EvalReportMapper; +import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Service; @@ -23,13 +28,8 @@ import org.springframework.util.StringUtils; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.LocalTime; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; +import java.util.*; +import java.util.function.Function; import java.util.stream.Collectors; @Service @@ -41,6 +41,8 @@ public class RegulatorEvalReportExecutor implements RegulatorEvalReportApi { @Autowired(required = false) private OrgInfoGateway orgInfoGateway; + @Autowired + private EvalReportMapper evalReportMapper; @Override public SingleResponse summary() { @@ -136,6 +138,55 @@ public class RegulatorEvalReportExecutor implements RegulatorEvalReportApi { return get(result.getId()); } + @Override + public SingleResponse> spotCheckReport(SpotCheckReportCmd cmd) { + List evalReportDOS = evalReportMapper.selectList(new LambdaQueryWrapper() + .eq(EvalReportDO::getOrgId, cmd.getOrgId())); + List evalReports = pickDistinctRandom(evalReportDOS, cmd.getRandomNumber(), EvalReportDO::getId); + List vo = evalReports.stream().map(item -> { + EvalReportLibraryCO evalReportLibraryCO = new EvalReportLibraryCO(); + BeanUtils.copyProperties(item, evalReportLibraryCO); + OrgInfoEntity org = orgInfoGateway.get(item.getOrgId()); + if (org != null) { + evalReportLibraryCO.setOrgName(org.getUnitName()); + } + return evalReportLibraryCO; + }).collect(Collectors.toList()); + return SingleResponse.success(vo); + } + + /** + * 高性能随机抽取(按ID去重,不重复抽取) + * @param list 原始数据列表(可能包含重复ID) + * @param n 需要抽取的数量 + * @param idExtractor 获取ID的函数,例如 User::getId + * @return 抽取的结果列表 + */ + public static List pickDistinctRandom(List list, int n, Function idExtractor) { + if (list == null || list.isEmpty() || n <= 0) { + return Collections.emptyList(); + } + Map distinctMap = new LinkedHashMap<>(list.size()); + for (T item : list) { + distinctMap.putIfAbsent(idExtractor.apply(item), item); + } + List distinctList = new ArrayList<>(distinctMap.values()); + int total = distinctList.size(); + if (total <= n) { + return distinctList; + } + Random rand = new Random(); + Set selectedIndices = new HashSet<>(n); + while (selectedIndices.size() < n) { + selectedIndices.add(rand.nextInt(total)); + } + List result = new ArrayList<>(n); + for (int idx : selectedIndices) { + result.add(distinctList.get(idx)); + } + return result; + } + private long countSubmitted(Integer yearFrom, Integer exactYear) { EvalReportQuery q = new EvalReportQuery(); q.setPageNum(1L); diff --git a/safety-eval-client/src/main/java/org/qinan/safetyeval/client/api/regulator/RegulatorEvalReportApi.java b/safety-eval-client/src/main/java/org/qinan/safetyeval/client/api/regulator/RegulatorEvalReportApi.java index af9938aa..1fd2a17d 100644 --- a/safety-eval-client/src/main/java/org/qinan/safetyeval/client/api/regulator/RegulatorEvalReportApi.java +++ b/safety-eval-client/src/main/java/org/qinan/safetyeval/client/api/regulator/RegulatorEvalReportApi.java @@ -6,6 +6,9 @@ import org.qinan.safetyeval.client.dto.PageResponse; import org.qinan.safetyeval.client.dto.SingleResponse; import org.qinan.safetyeval.client.dto.regulator.RegulatorEvalReportAddCmd; import org.qinan.safetyeval.client.dto.regulator.RegulatorEvalReportPageQuery; +import org.qinan.safetyeval.client.dto.regulator.SpotCheckReportCmd; + +import java.util.List; public interface RegulatorEvalReportApi { @@ -16,4 +19,6 @@ public interface RegulatorEvalReportApi { SingleResponse get(Long id); SingleResponse add(RegulatorEvalReportAddCmd cmd); + + SingleResponse> spotCheckReport(SpotCheckReportCmd cmd); } diff --git a/safety-eval-client/src/main/java/org/qinan/safetyeval/client/dto/regulator/SpotCheckReportCmd.java b/safety-eval-client/src/main/java/org/qinan/safetyeval/client/dto/regulator/SpotCheckReportCmd.java new file mode 100644 index 00000000..ac4b2612 --- /dev/null +++ b/safety-eval-client/src/main/java/org/qinan/safetyeval/client/dto/regulator/SpotCheckReportCmd.java @@ -0,0 +1,16 @@ +package org.qinan.safetyeval.client.dto.regulator; + +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * 机构端上传历史报告(对齐原型「上传历史报告」) + */ +@Data +public class SpotCheckReportCmd { + @ApiModelProperty(value = "报告编号") + private String orgId; + + @ApiModelProperty(value = "报告随机数, 最大值10") + private Integer randomNumber; +}