diff --git a/src/main/java/com/yunhai/cms/controller/oapi/site/SiteOapiController.java b/src/main/java/com/yunhai/cms/controller/oapi/site/SiteOapiController.java index b3372f8..408d353 100644 --- a/src/main/java/com/yunhai/cms/controller/oapi/site/SiteOapiController.java +++ b/src/main/java/com/yunhai/cms/controller/oapi/site/SiteOapiController.java @@ -16,8 +16,10 @@ import java.util.List; /** * 站点目录开放接口(/oapi/site/list,appKey 签名访问;V2.0 Part C.3)。 * 消费方=办事大厅 svc-hall(CmsSiteDirectoryImpl:resolveSite 反解 siteCode→schId、 - * 站点选择器按校拉取;本地缓存 5min)。schId 可选:不传=全部启用站点(跨校全量, - * 供 siteCode 反解);传了=按校过滤(P0-1 契约对齐,两侧注释口径一致)。 + * 站点选择器按校拉取;本地缓存 5min)。schId 可选: + * 不传=全部启用站点(跨校全量,供 siteCode 反解 siteCode→schId,旧办件仍可定位); + * 传了=按校过滤且仅主站(parentSiteId=0):院系子站不接入办事大厅(2026-09-17 口径收窄, + * 办事大厅按校接入一间学校只对应主站一个站点),SiteOapiIT 冻结该契约。 */ @RestController @RequestMapping("/oapi/site") @@ -38,6 +40,8 @@ public class SiteOapiController { } return siteRepository.findBySchId(schId).stream() .filter(site -> site.getStatus() != null && site.getStatus() == 1) + // 仅主站:院系子站不接入办事大厅(反解全量不受影响) + .filter(site -> site.getParentSiteId() == null || site.getParentSiteId() == 0) .map(SiteOapiController::toVo) .collect(java.util.stream.Collectors.toList()); } diff --git a/src/test/java/com/yunhai/cms/controller/oapi/SiteOapiIT.java b/src/test/java/com/yunhai/cms/controller/oapi/SiteOapiIT.java index 63eb3f4..11a7acb 100644 --- a/src/test/java/com/yunhai/cms/controller/oapi/SiteOapiIT.java +++ b/src/test/java/com/yunhai/cms/controller/oapi/SiteOapiIT.java @@ -41,8 +41,10 @@ class SiteOapiIT extends CmsIntegrationTestBase { @BeforeEach void seed() { purgeTables(); - persistSite("demo1", 1, "演示站点一"); - persistSite("schx", 1, "主站X子站"); + CmsSite demo1 = persistSite("demo1", 1, "演示站点一"); + // schx 为 demo1 的院系子站:《院系子站方案》接入口径——子站不进办事大厅, + // 按校下发(svc-hall 站点选择器 listSites(schId))只含主站;反解全量仍含子站。 + persistSite("schx", 1, "主站X子站", demo1.getId()); persistSite("demo2", 2, "演示站点二"); // 停用站点:任何形态(全量/按校)都不得下发 CmsSite disabled = persistSite("off1", 1, "停用站点"); @@ -73,26 +75,28 @@ class SiteOapiIT extends CmsIntegrationTestBase { } @Test - @DisplayName("带签名不传 schId → 全部启用站点(跨校全量,供 resolveSite 反解 siteCode)") + @DisplayName("带签名不传 schId → 全部启用站点(含子站,供 resolveSite 反解 siteCode→schId)") void signed_withoutSchId_returnsAllEnabledSites() throws Exception { MvcResult result = mockMvc.perform(get("/oapi/site/list").headers(signHeaders("/oapi/site/list"))) .andExpect(status().isOk()) .andReturn(); String body = result.getResponse().getContentAsString(StandardCharsets.UTF_8); - assertThat(body).contains("\"siteCode\":\"demo1\"").contains("\"siteCode\":\"demo2\""); + assertThat(body).contains("\"siteCode\":\"demo1\"").contains("\"siteCode\":\"demo2\"") + .contains("\"siteCode\":\"schx\""); assertThat(body).doesNotContain("off1").doesNotContain("停用站点"); } @Test - @DisplayName("带签名传 schId → 仅该校启用站点") - void signed_withSchId_filtersBySchool() throws Exception { + @DisplayName("带签名传 schId → 仅该校启用主站(院系子站不接入办事大厅,不下发)") + void signed_withSchId_returnsMainSitesOnly() throws Exception { MvcResult result = mockMvc.perform(get("/oapi/site/list?schId=1") .headers(signHeaders("/oapi/site/list?schId=1"))) .andExpect(status().isOk()) .andReturn(); String body = result.getResponse().getContentAsString(StandardCharsets.UTF_8); - assertThat(body).contains("\"siteCode\":\"demo1\"").contains("\"siteCode\":\"schx\""); - assertThat(body).doesNotContain("demo2"); + assertThat(body).contains("\"siteCode\":\"demo1\""); + assertThat(body).doesNotContain("schx").doesNotContain("主站X子站"); + assertThat(body).doesNotContain("demo2").doesNotContain("off1"); } @Test