From afb57a5d5f2fcebf65dd610e98c3f60cd1e45de8 Mon Sep 17 00:00:00 2001 From: XuqmGroup Date: Sat, 16 May 2026 00:24:10 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20ops=E5=BA=94=E7=94=A8=E5=88=97=E8=A1=A8?= =?UTF-8?q?=E6=94=AF=E6=8C=81=E7=A7=9F=E6=88=B7=E7=AD=9B=E9=80=89=20+=20?= =?UTF-8?q?=E8=BF=94=E5=9B=9E=E7=A7=9F=E6=88=B7=E5=90=8D=E7=A7=B0=20+=20?= =?UTF-8?q?=E6=9C=8D=E5=8A=A1=E6=8C=89=E7=B1=BB=E5=9E=8B=E5=B1=95=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - AppRepository: 新增 JOIN 查询,返回应用+租户名称 - OpsService: listApps 支持 tenantId 筛选,getAppDetail 按 serviceType 去重 - OpsController: listApps 新增 tenantId 可选参数 Co-Authored-By: Claude Opus 4.7 --- .../xuqm/tenant/controller/OpsController.java | 3 +- .../xuqm/tenant/repository/AppRepository.java | 14 ++++++++ .../com/xuqm/tenant/service/OpsService.java | 35 ++++++++++++++++--- 3 files changed, 46 insertions(+), 6 deletions(-) diff --git a/tenant-service/src/main/java/com/xuqm/tenant/controller/OpsController.java b/tenant-service/src/main/java/com/xuqm/tenant/controller/OpsController.java index 6a1823e..6f54e5c 100644 --- a/tenant-service/src/main/java/com/xuqm/tenant/controller/OpsController.java +++ b/tenant-service/src/main/java/com/xuqm/tenant/controller/OpsController.java @@ -135,9 +135,10 @@ public class OpsController { @PreAuthorize("hasAuthority('ROLE_OPS')") public ResponseEntity>> listApps( @RequestParam(defaultValue = "") String keyword, + @RequestParam(required = false) String tenantId, @RequestParam(defaultValue = "0") int page, @RequestParam(defaultValue = "20") int size) { - Page result = opsService.listApps(keyword, page, size); + Page> result = opsService.listApps(keyword, tenantId, page, size); return ResponseEntity.ok(ApiResponse.success(Map.of( "content", result.getContent(), "total", result.getTotalElements(), diff --git a/tenant-service/src/main/java/com/xuqm/tenant/repository/AppRepository.java b/tenant-service/src/main/java/com/xuqm/tenant/repository/AppRepository.java index e3ff1c2..b2b0103 100644 --- a/tenant-service/src/main/java/com/xuqm/tenant/repository/AppRepository.java +++ b/tenant-service/src/main/java/com/xuqm/tenant/repository/AppRepository.java @@ -4,6 +4,8 @@ import com.xuqm.tenant.entity.AppEntity; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; import java.util.List; import java.util.Optional; @@ -14,4 +16,16 @@ public interface AppRepository extends JpaRepository { boolean existsByPackageNameAndTenantId(String packageName, String tenantId); long count(); Page findByNameContainingIgnoreCaseOrAppKeyContainingIgnoreCase(String name, String appKey, Pageable pageable); + + @Query("SELECT a, t.nickname FROM AppEntity a LEFT JOIN TenantEntity t ON a.tenantId = t.id WHERE a.tenantId = :tenantId") + Page findByTenantIdJoined(@Param("tenantId") String tenantId, Pageable pageable); + + @Query("SELECT a, t.nickname FROM AppEntity a LEFT JOIN TenantEntity t ON a.tenantId = t.id") + Page findAllJoined(Pageable pageable); + + @Query("SELECT a, t.nickname FROM AppEntity a LEFT JOIN TenantEntity t ON a.tenantId = t.id WHERE a.tenantId = :tenantId AND (LOWER(a.name) LIKE LOWER(CONCAT('%',:kw,'%')) OR LOWER(a.appKey) LIKE LOWER(CONCAT('%',:kw,'%')))") + Page findByTenantIdAndKeywordJoined(@Param("tenantId") String tenantId, @Param("kw") String keyword, Pageable pageable); + + @Query("SELECT a, t.nickname FROM AppEntity a LEFT JOIN TenantEntity t ON a.tenantId = t.id WHERE LOWER(a.name) LIKE LOWER(CONCAT('%',:kw,'%')) OR LOWER(a.appKey) LIKE LOWER(CONCAT('%',:kw,'%'))") + Page findByKeywordJoined(@Param("kw") String keyword, Pageable pageable); } diff --git a/tenant-service/src/main/java/com/xuqm/tenant/service/OpsService.java b/tenant-service/src/main/java/com/xuqm/tenant/service/OpsService.java index 44d85e9..10d0a98 100644 --- a/tenant-service/src/main/java/com/xuqm/tenant/service/OpsService.java +++ b/tenant-service/src/main/java/com/xuqm/tenant/service/OpsService.java @@ -36,6 +36,7 @@ public class OpsService { private final TenantRepository tenantRepository; private final AppRepository appRepository; private final FeatureServiceRepository featureServiceRepository; + private final FeatureServiceManager featureServiceManager; private final OpsAdminRepository opsAdminRepository; private final ServiceActivationRequestRepository requestRepository; private final OperationLogRepository operationLogRepository; @@ -44,6 +45,7 @@ public class OpsService { public OpsService(TenantRepository tenantRepository, AppRepository appRepository, FeatureServiceRepository featureServiceRepository, + FeatureServiceManager featureServiceManager, OpsAdminRepository opsAdminRepository, ServiceActivationRequestRepository requestRepository, OperationLogRepository operationLogRepository, @@ -51,6 +53,7 @@ public class OpsService { this.tenantRepository = tenantRepository; this.appRepository = appRepository; this.featureServiceRepository = featureServiceRepository; + this.featureServiceManager = featureServiceManager; this.opsAdminRepository = opsAdminRepository; this.requestRepository = requestRepository; this.operationLogRepository = operationLogRepository; @@ -196,18 +199,40 @@ public class OpsService { ); } - public Page listApps(String keyword, int page, int size) { + public Page> listApps(String keyword, String tenantId, int page, int size) { var pageable = PageRequest.of(page, size, Sort.by(Sort.Direction.DESC, "createdAt")); - if (keyword == null || keyword.isBlank()) { - return appRepository.findAll(pageable); + boolean hasKw = keyword != null && !keyword.isBlank(); + boolean hasTenant = tenantId != null && !tenantId.isBlank(); + Page result; + if (hasKw && hasTenant) { + result = appRepository.findByTenantIdAndKeywordJoined(tenantId, keyword, pageable); + } else if (hasTenant) { + result = appRepository.findByTenantIdJoined(tenantId, pageable); + } else if (hasKw) { + result = appRepository.findByKeywordJoined(keyword, pageable); + } else { + result = appRepository.findAllJoined(pageable); } - return appRepository.findByNameContainingIgnoreCaseOrAppKeyContainingIgnoreCase(keyword, keyword, pageable); + return result.map(row -> { + AppEntity app = (AppEntity) row[0]; + String tenantName = row[1] != null ? (String) row[1] : null; + Map m = new LinkedHashMap<>(); + m.put("id", app.getId()); + m.put("appKey", app.getAppKey()); + m.put("appSecret", app.getAppSecret()); + m.put("name", app.getName()); + m.put("packageName", app.getPackageName()); + m.put("tenantId", app.getTenantId()); + m.put("tenantName", tenantName); + m.put("createdAt", app.getCreatedAt()); + return m; + }); } public Map getAppDetail(String appKey) { AppEntity app = appRepository.findByAppKey(appKey) .orElseThrow(() -> new IllegalArgumentException("应用不存在")); - List services = featureServiceRepository.findByAppKey(app.getAppKey()); + List services = featureServiceManager.listByApp(appKey); long enabledCount = services.stream().filter(FeatureServiceEntity::isEnabled).count(); Map result = new LinkedHashMap<>(); result.put("app", app);