From 16a7b9513d29fa22bd2232b9319c606e7a0e793a Mon Sep 17 00:00:00 2001 From: dengqichen Date: Mon, 29 Dec 2025 14:53:46 +0800 Subject: [PATCH] =?UTF-8?q?1.46=20=E5=A2=9E=E5=8A=A0=E9=80=9A=E7=94=A8?= =?UTF-8?q?=E7=BB=9F=E8=AE=A1=E6=9F=A5=E8=AF=A2=E6=96=B9=E6=B3=95=EF=BC=8C?= =?UTF-8?q?=E5=AD=90=E7=B1=BB=E7=9B=B4=E6=8E=A5=E5=AE=9E=E7=8E=B0=E5=8D=B3?= =?UTF-8?q?=E5=8F=AF=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../deploy/api/ApplicationApiController.java | 6 - .../deploy/query/ApplicationQuery.java | 5 +- .../repository/IApplicationRepository.java | 15 --- .../ApplicationEnabledStatistics.java | 20 --- .../deploy/service/IApplicationService.java | 9 -- .../service/impl/ApplicationServiceImpl.java | 46 +++---- .../framework/controller/BaseController.java | 2 +- .../dto/{PageResult.java => PageStats.java} | 119 +++--------------- .../framework/service/IBaseService.java | 2 +- .../service/impl/BaseServiceImpl.java | 14 ++- 10 files changed, 51 insertions(+), 187 deletions(-) delete mode 100644 backend/src/main/java/com/qqchen/deploy/backend/deploy/repository/projection/ApplicationEnabledStatistics.java rename backend/src/main/java/com/qqchen/deploy/backend/framework/dto/{PageResult.java => PageStats.java} (50%) diff --git a/backend/src/main/java/com/qqchen/deploy/backend/deploy/api/ApplicationApiController.java b/backend/src/main/java/com/qqchen/deploy/backend/deploy/api/ApplicationApiController.java index 00ac7f12..266bf817 100644 --- a/backend/src/main/java/com/qqchen/deploy/backend/deploy/api/ApplicationApiController.java +++ b/backend/src/main/java/com/qqchen/deploy/backend/deploy/api/ApplicationApiController.java @@ -7,7 +7,6 @@ import com.qqchen.deploy.backend.deploy.query.ApplicationQuery; import com.qqchen.deploy.backend.deploy.service.IApplicationService; import com.qqchen.deploy.backend.framework.api.Response; import com.qqchen.deploy.backend.framework.controller.BaseController; -import com.qqchen.deploy.backend.framework.dto.PageResult; import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.annotation.Resource; import jakarta.servlet.http.HttpServletResponse; @@ -54,11 +53,6 @@ public class ApplicationApiController extends BaseController> pageWithStats(ApplicationQuery query) { - return Response.success(applicationService.pageWithStats(query)); - } - @Override public Response> findAll(ApplicationQuery query) { return super.findAll(query); diff --git a/backend/src/main/java/com/qqchen/deploy/backend/deploy/query/ApplicationQuery.java b/backend/src/main/java/com/qqchen/deploy/backend/deploy/query/ApplicationQuery.java index 4cc81e32..0aabe9fc 100644 --- a/backend/src/main/java/com/qqchen/deploy/backend/deploy/query/ApplicationQuery.java +++ b/backend/src/main/java/com/qqchen/deploy/backend/deploy/query/ApplicationQuery.java @@ -1,5 +1,6 @@ package com.qqchen.deploy.backend.deploy.query; +import com.qqchen.deploy.backend.deploy.enums.DevelopmentLanguageTypeEnum; import com.qqchen.deploy.backend.framework.annotation.QueryField; import com.qqchen.deploy.backend.framework.enums.QueryType; import com.qqchen.deploy.backend.framework.query.BaseQuery; @@ -28,8 +29,8 @@ public class ApplicationQuery extends BaseQuery { @QueryField(field = "buildType") private String buildType; - @QueryField(field = "languageType") - private String languageType; + @QueryField(field = "language") + private DevelopmentLanguageTypeEnum language; @QueryField(field = "applicationCategoryId") private Long applicationCategoryId; diff --git a/backend/src/main/java/com/qqchen/deploy/backend/deploy/repository/IApplicationRepository.java b/backend/src/main/java/com/qqchen/deploy/backend/deploy/repository/IApplicationRepository.java index 1e49e302..81410b23 100644 --- a/backend/src/main/java/com/qqchen/deploy/backend/deploy/repository/IApplicationRepository.java +++ b/backend/src/main/java/com/qqchen/deploy/backend/deploy/repository/IApplicationRepository.java @@ -1,13 +1,9 @@ package com.qqchen.deploy.backend.deploy.repository; import com.qqchen.deploy.backend.deploy.entity.Application; -import com.qqchen.deploy.backend.deploy.repository.projection.ApplicationEnabledStatistics; import com.qqchen.deploy.backend.framework.repository.IBaseRepository; -import org.springframework.data.jpa.repository.Query; import org.springframework.stereotype.Repository; -import java.util.List; - @Repository public interface IApplicationRepository extends IBaseRepository { @@ -16,15 +12,4 @@ public interface IApplicationRepository extends IBaseRepository countByEnabledGroupBy(); - } \ No newline at end of file diff --git a/backend/src/main/java/com/qqchen/deploy/backend/deploy/repository/projection/ApplicationEnabledStatistics.java b/backend/src/main/java/com/qqchen/deploy/backend/deploy/repository/projection/ApplicationEnabledStatistics.java deleted file mode 100644 index 97118663..00000000 --- a/backend/src/main/java/com/qqchen/deploy/backend/deploy/repository/projection/ApplicationEnabledStatistics.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.qqchen.deploy.backend.deploy.repository.projection; - -/** - * 应用启用状态统计投影接口 - * 用于Spring Data JPA的查询结果映射 - */ -public interface ApplicationEnabledStatistics { - - /** - * 获取启用状态 - * @return true=已启用,false=已禁用 - */ - Boolean getEnabled(); - - /** - * 获取该状态下的应用数量 - * @return 应用数量 - */ - Long getCount(); -} diff --git a/backend/src/main/java/com/qqchen/deploy/backend/deploy/service/IApplicationService.java b/backend/src/main/java/com/qqchen/deploy/backend/deploy/service/IApplicationService.java index 08b6a1a2..683b0f17 100644 --- a/backend/src/main/java/com/qqchen/deploy/backend/deploy/service/IApplicationService.java +++ b/backend/src/main/java/com/qqchen/deploy/backend/deploy/service/IApplicationService.java @@ -4,21 +4,12 @@ import com.qqchen.deploy.backend.deploy.dto.ApplicationDTO; import com.qqchen.deploy.backend.deploy.dto.DevelopmentLanguageTypeDTO; import com.qqchen.deploy.backend.deploy.entity.Application; import com.qqchen.deploy.backend.deploy.query.ApplicationQuery; -import com.qqchen.deploy.backend.framework.dto.PageResult; import com.qqchen.deploy.backend.framework.service.IBaseService; import java.util.List; public interface IApplicationService extends IBaseService { - /** - * 分页查询应用(带统计信息) - * - * @param query 查询条件 - * @return 分页结果,包含已启用和已禁用的总数统计 - */ - PageResult pageWithStats(ApplicationQuery query); - List getAllDevelopmentLanguageTypes(); } \ No newline at end of file diff --git a/backend/src/main/java/com/qqchen/deploy/backend/deploy/service/impl/ApplicationServiceImpl.java b/backend/src/main/java/com/qqchen/deploy/backend/deploy/service/impl/ApplicationServiceImpl.java index 47808470..267caa5d 100644 --- a/backend/src/main/java/com/qqchen/deploy/backend/deploy/service/impl/ApplicationServiceImpl.java +++ b/backend/src/main/java/com/qqchen/deploy/backend/deploy/service/impl/ApplicationServiceImpl.java @@ -11,6 +11,7 @@ import com.qqchen.deploy.backend.system.model.ExternalSystemDTO; import com.qqchen.deploy.backend.deploy.entity.Application; import com.qqchen.deploy.backend.deploy.entity.ApplicationCategory; import com.qqchen.deploy.backend.deploy.entity.ExternalSystem; +import com.qqchen.deploy.backend.deploy.entity.QApplication; import com.qqchen.deploy.backend.deploy.entity.RepositoryProject; import com.qqchen.deploy.backend.deploy.enums.DevelopmentLanguageTypeEnum; import com.qqchen.deploy.backend.deploy.query.ApplicationQuery; @@ -19,23 +20,21 @@ import com.qqchen.deploy.backend.deploy.repository.IApplicationRepository; import com.qqchen.deploy.backend.deploy.repository.IExternalSystemRepository; import com.qqchen.deploy.backend.deploy.repository.IRepositoryProjectRepository; import com.qqchen.deploy.backend.deploy.repository.ITeamApplicationRepository; -import com.qqchen.deploy.backend.deploy.repository.projection.ApplicationEnabledStatistics; import com.qqchen.deploy.backend.deploy.service.IApplicationService; -import com.qqchen.deploy.backend.framework.dto.PageResult; +import com.qqchen.deploy.backend.framework.dto.PageStats; import com.qqchen.deploy.backend.framework.enums.ResponseCode; +import org.springframework.data.domain.Page; import com.qqchen.deploy.backend.framework.exception.BusinessException; import com.qqchen.deploy.backend.framework.service.impl.BaseServiceImpl; +import com.querydsl.core.BooleanBuilder; import jakarta.annotation.Resource; import lombok.extern.slf4j.Slf4j; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.PageImpl; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.util.ArrayList; import java.util.Arrays; import java.util.List; -import java.util.Optional; import static java.util.stream.Collectors.toList; @@ -111,36 +110,27 @@ public class ApplicationServiceImpl extends BaseServiceImpl pageWithStats(ApplicationQuery query) { - Page page = super.page(query); - fillApplicationRelations(page.getContent()); + protected void addStats(PageStats result, ApplicationQuery query) { + // 复用框架的查询条件构建 + BooleanBuilder predicate = createQueryPredicate(query); - // 一次查询获取启用和禁用状态的应用总数(按enabled分组统计) - List statistics = applicationRepository.countByEnabledGroupBy(); + // 统计启用和禁用数量(带筛选条件) + Long enabledCount = applicationRepository.count(predicate.and(QApplication.application.enabled.eq(true))); + Long disabledCount = applicationRepository.count(predicate.and(QApplication.application.enabled.eq(false))); - // 解析统计结果 - Long enabledCount = 0L; - Long disabledCount = 0L; - for (ApplicationEnabledStatistics stat : statistics) { - if (Boolean.TRUE.equals(stat.getEnabled())) { - enabledCount = stat.getCount(); - } else if (Boolean.FALSE.equals(stat.getEnabled())) { - disabledCount = stat.getCount(); - } - } - - // 构建PageResult并添加统计字段 - return new PageResult<>(page) - .addExtraField("enabledCount", enabledCount) - .addExtraField("disabledCount", disabledCount); + result.addStat("enabledCount", enabledCount); + result.addStat("disabledCount", disabledCount); } @Override public Page page(ApplicationQuery query) { - Page page = super.page(query); - fillApplicationRelations(page.getContent()); - return page; + Page result = super.page(query); + fillApplicationRelations(result.getContent()); + return result; } @Override diff --git a/backend/src/main/java/com/qqchen/deploy/backend/framework/controller/BaseController.java b/backend/src/main/java/com/qqchen/deploy/backend/framework/controller/BaseController.java index 17a73476..72ff7014 100644 --- a/backend/src/main/java/com/qqchen/deploy/backend/framework/controller/BaseController.java +++ b/backend/src/main/java/com/qqchen/deploy/backend/framework/controller/BaseController.java @@ -2,12 +2,12 @@ package com.qqchen.deploy.backend.framework.controller; import com.qqchen.deploy.backend.framework.domain.Entity; import com.qqchen.deploy.backend.framework.dto.BaseDTO; +import org.springframework.data.domain.Page; import com.qqchen.deploy.backend.framework.query.BaseQuery; import com.qqchen.deploy.backend.framework.api.Response; import com.qqchen.deploy.backend.framework.service.IBaseService; import jakarta.annotation.Resource; import jakarta.servlet.http.HttpServletResponse; -import org.springframework.data.domain.Page; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; diff --git a/backend/src/main/java/com/qqchen/deploy/backend/framework/dto/PageResult.java b/backend/src/main/java/com/qqchen/deploy/backend/framework/dto/PageStats.java similarity index 50% rename from backend/src/main/java/com/qqchen/deploy/backend/framework/dto/PageResult.java rename to backend/src/main/java/com/qqchen/deploy/backend/framework/dto/PageStats.java index 47ea765a..c0a53c53 100644 --- a/backend/src/main/java/com/qqchen/deploy/backend/framework/dto/PageResult.java +++ b/backend/src/main/java/com/qqchen/deploy/backend/framework/dto/PageStats.java @@ -15,225 +15,136 @@ import java.util.Map; import java.util.function.Function; /** - * 通用分页结果包装类 + * 带统计信息的分页结果包装类 * 实现Page接口,保留Spring Data Page的所有字段,并支持添加额外的统计字段 * 额外字段会通过@JsonAnyGetter展开到与totalElements同一层级 * * @param 分页数据类型 */ -public class PageResult implements Page, Serializable { +public class PageStats implements Page, Serializable { private static final long serialVersionUID = 1L; - /** - * 内部Page对象,用于委托所有Page接口方法 - */ @JsonIgnore private final Page page; - /** - * 额外的统计字段,会被展开到JSON的顶层 - */ @JsonIgnore - private final Map extraFields = new HashMap<>(); + private final Map stats = new HashMap<>(); - /** - * 构造函数 - * - * @param page Spring Data Page对象 - */ - public PageResult(Page page) { + public PageStats(Page page) { this.page = page; } /** - * 添加额外的统计字段 - * - * @param key 字段名 - * @param value 字段值 - * @return 当前对象(支持链式调用) + * 添加统计字段 */ - public PageResult addExtraField(String key, Object value) { - this.extraFields.put(key, value); + public PageStats addStat(String key, Object value) { + this.stats.put(key, value); return this; } - /** - * Jackson注解:将extraFields的内容展开到JSON的顶层 - * 使得额外字段与totalElements等在同一层级 - */ @JsonAnyGetter - public Map getExtraFields() { - return extraFields; + public Map getStats() { + return stats; } - /** - * Jackson注解:支持反序列化时设置额外字段 - */ @JsonAnySetter - public void setExtraField(String key, Object value) { - extraFields.put(key, value); + public void setStat(String key, Object value) { + stats.put(key, value); } - // ==================== 实现Page接口的所有方法 ==================== + // ==================== 实现Page接口 ==================== - /** - * 获取当前页的数据列表 - */ @Override public List getContent() { return page.getContent(); } - /** - * 获取总记录数 - */ @Override public long getTotalElements() { return page.getTotalElements(); } - /** - * 获取总页数 - */ @Override public int getTotalPages() { return page.getTotalPages(); } - /** - * 获取当前页码(从0开始) - */ @Override public int getNumber() { return page.getNumber(); } - /** - * 获取每页大小 - */ @Override public int getSize() { return page.getSize(); } - /** - * 获取当前页的实际记录数 - */ @Override public int getNumberOfElements() { return page.getNumberOfElements(); } - /** - * 是否有内容 - */ @Override public boolean hasContent() { return page.hasContent(); } - /** - * 是否为空 - */ @Override public boolean isEmpty() { return page.isEmpty(); } - /** - * 是否为第一页 - */ @Override public boolean isFirst() { return page.isFirst(); } - /** - * 是否为最后一页 - */ @Override public boolean isLast() { return page.isLast(); } - /** - * 是否有下一页 - */ @Override public boolean hasNext() { return page.hasNext(); } - /** - * 是否有上一页 - */ @Override public boolean hasPrevious() { return page.hasPrevious(); } - /** - * 获取排序信息 - */ @Override public Sort getSort() { return page.getSort(); } - /** - * 获取分页信息 - */ @Override public Pageable getPageable() { return page.getPageable(); } - /** - * 获取下一页的分页信息 - */ @Override public Pageable nextPageable() { return page.nextPageable(); } - /** - * 获取上一页的分页信息 - */ @Override public Pageable previousPageable() { return page.previousPageable(); } - /** - * 转换当前页的数据类型 - * - * @param converter 转换函数 - * @param 目标类型 - * @return 新的PageResult对象 - */ @Override - public PageResult map(Function converter) { + public PageStats map(Function converter) { Page mappedPage = page.map(converter); - PageResult result = new PageResult<>(mappedPage); - // 复制额外字段 - result.extraFields.putAll(this.extraFields); + PageStats result = new PageStats<>(mappedPage); + result.stats.putAll(this.stats); return result; } - /** - * 获取迭代器 - */ @Override public Iterator iterator() { return page.iterator(); } - - /** - * 获取内部Page对象(用于需要直接访问Page的场景) - */ - @JsonIgnore - public Page getPage() { - return page; - } } diff --git a/backend/src/main/java/com/qqchen/deploy/backend/framework/service/IBaseService.java b/backend/src/main/java/com/qqchen/deploy/backend/framework/service/IBaseService.java index e6c9b0d0..c0a078a8 100644 --- a/backend/src/main/java/com/qqchen/deploy/backend/framework/service/IBaseService.java +++ b/backend/src/main/java/com/qqchen/deploy/backend/framework/service/IBaseService.java @@ -2,8 +2,8 @@ package com.qqchen.deploy.backend.framework.service; import com.qqchen.deploy.backend.framework.domain.Entity; import com.qqchen.deploy.backend.framework.dto.BaseDTO; -import com.qqchen.deploy.backend.framework.query.BaseQuery; import org.springframework.data.domain.Page; +import com.qqchen.deploy.backend.framework.query.BaseQuery; import java.io.Serializable; import java.util.List; diff --git a/backend/src/main/java/com/qqchen/deploy/backend/framework/service/impl/BaseServiceImpl.java b/backend/src/main/java/com/qqchen/deploy/backend/framework/service/impl/BaseServiceImpl.java index 319816e3..1dc7ed1d 100644 --- a/backend/src/main/java/com/qqchen/deploy/backend/framework/service/impl/BaseServiceImpl.java +++ b/backend/src/main/java/com/qqchen/deploy/backend/framework/service/impl/BaseServiceImpl.java @@ -11,6 +11,7 @@ import com.qqchen.deploy.backend.framework.annotation.LogicDelete; import com.qqchen.deploy.backend.framework.converter.BaseConverter; import com.qqchen.deploy.backend.framework.domain.Entity; import com.qqchen.deploy.backend.framework.dto.BaseDTO; +import com.qqchen.deploy.backend.framework.dto.PageStats; import com.qqchen.deploy.backend.framework.enums.QueryType; import com.qqchen.deploy.backend.framework.query.BaseQuery; import com.qqchen.deploy.backend.framework.query.DateRange; @@ -131,7 +132,18 @@ public abstract class BaseServiceImpl, D extends BaseDTO, Q public Page page(Q query) { validateDatabaseOperation("page"); Page page = repository.findAll(createQueryPredicate(query), createPageRequest(query)); - return converter.toDtoPage(page); + Page dtoPage = converter.toDtoPage(page); + PageStats result = new PageStats<>(dtoPage); + addStats(result, query); + return result; + } + + /** + * 添加统计信息钩子方法 + * 子类可重写此方法添加自定义统计字段 + */ + protected void addStats(PageStats result, Q query) { + // 默认空实现,子类可重写 } protected BooleanBuilder createQueryPredicate(BaseQuery query) {