diff --git a/yudao-module-education/src/main/java/cn/iocoder/yudao/module/education/controller/admin/EducationCapabilityController.java b/yudao-module-education/src/main/java/cn/iocoder/yudao/module/education/controller/admin/EducationCapabilityController.java index 0187b69f..3cfc1d47 100644 --- a/yudao-module-education/src/main/java/cn/iocoder/yudao/module/education/controller/admin/EducationCapabilityController.java +++ b/yudao-module-education/src/main/java/cn/iocoder/yudao/module/education/controller/admin/EducationCapabilityController.java @@ -41,7 +41,8 @@ public class EducationCapabilityController { "answer-save", "session-submit", "practice-report", "vocabulary-review", "exam-reminder", "learning-award", "student-feedback", "learning-summary", "tenant-leaderboard", "content-import-assets", "content-import-jobs", - "content-export-policy")) + "content-export-policy", "class-management", "class-invitations", + "education-entitlements", "resource-product-bindings")) .themes(describeThemes()) .catalogReadEnabled(educationProperties.isCatalogReadEnabled()) .practiceWriteEnabled(educationProperties.isPracticeWriteEnabled()) @@ -58,14 +59,16 @@ public class EducationCapabilityController { List.of("education", "infra"), List.of("production-scanner-adapter", "production-import-parser", "export-artifact-generation"), List.of(), "FEATURE_FLAG", "POSTGRESQL_INTEGRATION_TESTED"), - theme("EDU-012", "classes-relationships", "BLOCKED", + theme("EDU-012", "classes-relationships", "BOUNDED_IMPLEMENTED", List.of("education", "member", "system"), - List.of("relationship-role-model", "class-data-scope", "invitation-contract"), - List.of(), "FEATURE_FLAG", "CONTRACT_ONLY"), + List.of("teacher-role-expansion", "platform-admin-cross-tenant-operations"), + List.of(), "FEATURE_FLAG", "POSTGRESQL_INTEGRATION_TESTED", + List.of("/admin-api/education/classes", "/app-api/education/class-invitations")), theme("EDU-013", "commercialization", "BOUNDED_IMPLEMENTED", - List.of("education", "mall", "pay"), + List.of("education", "mall", "pay", "member", "crm"), List.of("mall-order-item-public-event", "pay-refund-public-event", "crm-referral-contract"), - List.of(), "ACCESS_FAIL_CLOSED", "POSTGRESQL_INTEGRATION_TESTED"), + List.of(), "ACCESS_FAIL_CLOSED", "POSTGRESQL_INTEGRATION_TESTED", + List.of("/admin-api/education/commercialization", "EducationEntitlementApi")), theme("EDU-014", "extended-learning", "PARTIAL", List.of("education", "member", "system"), List.of("video-entitlement-contract", "ai-recommendation-contract", "legacy-data-import"), diff --git a/yudao-module-education/src/main/java/cn/iocoder/yudao/module/education/service/question/QuestionCatalogServiceImpl.java b/yudao-module-education/src/main/java/cn/iocoder/yudao/module/education/service/question/QuestionCatalogServiceImpl.java index 1b47a4e0..20d2d454 100644 --- a/yudao-module-education/src/main/java/cn/iocoder/yudao/module/education/service/question/QuestionCatalogServiceImpl.java +++ b/yudao-module-education/src/main/java/cn/iocoder/yudao/module/education/service/question/QuestionCatalogServiceImpl.java @@ -57,6 +57,9 @@ public class QuestionCatalogServiceImpl implements QuestionCatalogService { int pageNo = reqVO.getPageNo() != null ? reqVO.getPageNo() : 1; int pageSize = reqVO.getPageSize() != null ? reqVO.getPageSize() : 20; + if (reqVO.getCollectionId() != null && !reqVO.getCollectionId().isBlank()) { + assertCollectionAccess(reqVO.getCollectionId()); + } CatalogQuestionPageResult pageResult = provider.listQuestions( reqVO.getCollectionId(), reqVO.getNodeId(), reqVO.getType(), reqVO.getDifficulty(), @@ -127,6 +130,9 @@ public class QuestionCatalogServiceImpl implements QuestionCatalogService { } int requestedCount = reqVO.getQuestionCount() != null ? reqVO.getQuestionCount() : 10; + if (reqVO.getCollectionId() != null && !reqVO.getCollectionId().isBlank()) { + assertCollectionAccess(reqVO.getCollectionId()); + } CatalogPracticeBlueprintDTO blueprint = provider.getPracticeBlueprint( reqVO.getCollectionId(), reqVO.getNodeId(), reqVO.getType(), reqVO.getDifficulty()); diff --git a/yudao-module-education/src/test/java/cn/iocoder/yudao/module/education/controller/admin/EducationCapabilityControllerTest.java b/yudao-module-education/src/test/java/cn/iocoder/yudao/module/education/controller/admin/EducationCapabilityControllerTest.java index 27305ce6..1dba0836 100644 --- a/yudao-module-education/src/test/java/cn/iocoder/yudao/module/education/controller/admin/EducationCapabilityControllerTest.java +++ b/yudao-module-education/src/test/java/cn/iocoder/yudao/module/education/controller/admin/EducationCapabilityControllerTest.java @@ -52,12 +52,21 @@ public class EducationCapabilityControllerTest { assertEquals("1.0.0-test", data.getVersion(), "版本应匹配"); assertNotNull(data.getCapabilities(), "能力列表不应为空"); assertTrue(data.getCapabilities().contains("shell"), "应包含 shell 能力"); + assertTrue(data.getCapabilities().containsAll(List.of("class-management", "class-invitations", + "education-entitlements", "resource-product-bindings")), "能力清单应包含已交付的 EDU-012/013 接口"); assertNotNull(data.getThemes(), "迁移主题不应为空"); assertEquals(5, data.getThemes().size(), "应完整列出 EDU-011 至 EDU-015"); assertEquals(5, data.getThemes().stream().map(EducationThemeRespVO::getKey).distinct().count(), "迁移主题不应重复"); assertTrue(data.getThemes().stream().noneMatch(theme -> "AVAILABLE".equals(theme.getStatus())), "未交付主题不得声明为可用"); + EducationThemeRespVO classes = data.getThemes().stream() + .filter(theme -> "EDU-012".equals(theme.getKey())).findFirst().orElseThrow(); + assertEquals("BOUNDED_IMPLEMENTED", classes.getStatus(), "EDU-012 已交付的有界能力不得继续标为阻塞"); + assertTrue(classes.getExecutableInterfaces().contains("/admin-api/education/classes")); + EducationThemeRespVO commercialization = data.getThemes().stream() + .filter(theme -> "EDU-013".equals(theme.getKey())).findFirst().orElseThrow(); + assertTrue(commercialization.getExecutableInterfaces().contains("EducationEntitlementApi")); EducationThemeRespVO operations = data.getThemes().stream() .filter(theme -> "EDU-015".equals(theme.getKey())).findFirst().orElseThrow(); assertEquals("LEGACY_DEPENDENT", operations.getStatus(), "默认 Scalar 模式必须披露遗留依赖");