diff --git a/frontend/src/components/bypass/BypassStepFields.tsx b/frontend/src/components/bypass/BypassStepFields.tsx index db4b6d9..cacc8f3 100644 --- a/frontend/src/components/bypass/BypassStepFields.tsx +++ b/frontend/src/components/bypass/BypassStepFields.tsx @@ -110,9 +110,15 @@ export default function BypassStepFields({ fields, onChange }: BypassStepFieldsP ) : (
| # | 필드명 | JSON Property | 타입 | @@ -123,6 +129,11 @@ export default function BypassStepFields({ fields, onChange }: BypassStepFieldsP||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| + + #{index + 1} + + |
= {
GET: 'bg-emerald-100 text-emerald-700',
POST: 'bg-blue-100 text-blue-700',
@@ -30,6 +32,8 @@ export default function BypassConfig() {
const [configs, setConfigs] = useState
+
+
+ {/* 빈 상태 */}
{configs.length === 0 ? (
+ {/* 검색 */}
+
+
+ {searchTerm && (
+
+
+
+
+ setSearchTerm(e.target.value)}
+ className="w-full pl-10 pr-4 py-2 border border-wing-border rounded-lg text-sm
+ focus:ring-2 focus:ring-wing-accent focus:border-wing-accent outline-none bg-wing-surface text-wing-text"
+ />
+ {searchTerm && (
+
+ )}
+
+
+ {/* 뷰 전환 토글 */}
+
+
+
+
+ + {filteredConfigs.length}개 API 검색됨 + + )} +등록된 BYPASS API가 없습니다. 위 버튼을 눌러 새 API를 등록하세요.
+
+ ) : viewMode === 'card' ? (
+ /* 카드 뷰 */
검색 결과가 없습니다. +다른 검색어를 사용해 보세요. +
- {configs.map((config) => (
+ {filteredConfigs.map((config) => (
))}
+ ) : (
+ /* 테이블 뷰 */
+
+
)}
{/* 등록/수정 모달 */}
diff --git a/src/main/java/com/snp/batch/global/config/SwaggerConfig.java b/src/main/java/com/snp/batch/global/config/SwaggerConfig.java
index 8cb1a22..15b3971 100644
--- a/src/main/java/com/snp/batch/global/config/SwaggerConfig.java
+++ b/src/main/java/com/snp/batch/global/config/SwaggerConfig.java
@@ -5,6 +5,7 @@ import io.swagger.v3.oas.models.info.Contact;
import io.swagger.v3.oas.models.info.Info;
import io.swagger.v3.oas.models.info.License;
import io.swagger.v3.oas.models.servers.Server;
+import org.springdoc.core.models.GroupedOpenApi;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@@ -33,6 +34,31 @@ public class SwaggerConfig {
@Value("${server.servlet.context-path:}")
private String contextPath;
+ @Bean
+ public GroupedOpenApi batchManagementApi() {
+ return GroupedOpenApi.builder()
+ .group("1. Batch Management")
+ .pathsToMatch("/api/batch/**")
+ .build();
+ }
+
+ @Bean
+ public GroupedOpenApi bypassConfigApi() {
+ return GroupedOpenApi.builder()
+ .group("2. Bypass Config")
+ .pathsToMatch("/api/bypass-config/**")
+ .build();
+ }
+
+ @Bean
+ public GroupedOpenApi bypassApi() {
+ return GroupedOpenApi.builder()
+ .group("3. Bypass API")
+ .pathsToMatch("/api/**")
+ .pathsToExclude("/api/batch/**", "/api/bypass-config/**")
+ .build();
+ }
+
@Bean
public OpenAPI openAPI() {
return new OpenAPI()
diff --git a/src/main/java/com/snp/batch/jobs/web/risk/controller/RiskController.java b/src/main/java/com/snp/batch/jobs/web/risk/controller/RiskController.java
index 9f4397a..2e96d20 100644
--- a/src/main/java/com/snp/batch/jobs/web/risk/controller/RiskController.java
+++ b/src/main/java/com/snp/batch/jobs/web/risk/controller/RiskController.java
@@ -23,7 +23,7 @@ import java.util.List;
@RestController
@RequestMapping("/api/risk")
@RequiredArgsConstructor
-@Tag(name = "Risk", description = "선박 Risk 상세 정보 bypass API")
+@Tag(name = "Risk", description = "[Service API] 선박 Risk 상세 정보 bypass API")
public class RiskController extends BaseBypassController {
private final RiskBypassService riskBypassService;
diff --git a/src/main/java/com/snp/batch/service/BypassCodeGenerator.java b/src/main/java/com/snp/batch/service/BypassCodeGenerator.java
index 1088079..5e7be1b 100644
--- a/src/main/java/com/snp/batch/service/BypassCodeGenerator.java
+++ b/src/main/java/com/snp/batch/service/BypassCodeGenerator.java
@@ -232,7 +232,7 @@ public class BypassCodeGenerator {
@RestController
@RequestMapping("{{REQUEST_MAPPING_PATH}}")
@RequiredArgsConstructor
- @Tag(name = "{{DOMAIN_CAP}}", description = "{{DISPLAY_NAME}} bypass API")
+ @Tag(name = "{{DOMAIN_CAP}}", description = "{{TAG_PREFIX}} {{DISPLAY_NAME}} bypass API")
public class {{DOMAIN_CAP}}Controller extends BaseBypassController {
private final {{SERVICE_CLASS}} {{SERVICE_FIELD}};
@@ -255,6 +255,7 @@ public class BypassCodeGenerator {
.replace("{{REQUEST_PARAM_IMPORT}}", requestParamImport)
.replace("{{REQUEST_BODY_IMPORT}}", requestBodyImport)
.replace("{{MAPPING_IMPORT}}", mappingImport)
+ .replace("{{TAG_PREFIX}}", getTagPrefix(config.getWebclientBean()))
.replace("{{DISPLAY_NAME}}", config.getDisplayName())
.replace("{{DOMAIN_CAP}}", domainCap)
.replace("{{REQUEST_MAPPING_PATH}}", requestMappingPath)
@@ -331,14 +332,15 @@ public class BypassCodeGenerator {
String description = p.getDescription() != null ? p.getDescription() : p.getParamName();
String javaType = toJavaType(p.getParamType());
String paramName = p.getParamName();
+ String example = getDefaultExample(p.getParamType());
return switch (p.getParamIn().toUpperCase()) {
- case "PATH" -> "@Parameter(description = \"" + description + "\")\n"
+ case "PATH" -> "@Parameter(description = \"" + description + "\", example = \"" + example + "\")\n"
+ " @PathVariable " + javaType + " " + paramName;
- case "BODY" -> "@Parameter(description = \"" + description + "\")\n"
+ case "BODY" -> "@Parameter(description = \"" + description + "\", example = \"" + example + "\")\n"
+ " @RequestBody " + javaType + " " + paramName;
default -> {
String required = Boolean.TRUE.equals(p.getRequired()) ? "true" : "false";
- yield "@Parameter(description = \"" + description + "\")\n"
+ yield "@Parameter(description = \"" + description + "\", example = \"" + example + "\")\n"
+ " @RequestParam(required = " + required + ") " + javaType + " " + paramName;
}
};
@@ -401,6 +403,35 @@ public class BypassCodeGenerator {
return filePath;
}
+ /**
+ * webclientBean 이름 → Swagger @Tag description 접두사 변환
+ */
+ private String getTagPrefix(String webclientBean) {
+ if (webclientBean == null) {
+ return "[Ship API]";
+ }
+ return switch (webclientBean) {
+ case "maritimeAisApiWebClient" -> "[AIS API]";
+ case "maritimeServiceApiWebClient" -> "[Service API]";
+ default -> "[Ship API]";
+ };
+ }
+
+ /**
+ * paramType → Swagger @Parameter example 기본값 결정
+ */
+ private String getDefaultExample(String paramType) {
+ if (paramType == null) {
+ return "9876543";
+ }
+ return switch (paramType.toUpperCase()) {
+ case "INTEGER" -> "0";
+ case "LONG" -> "0";
+ case "BOOLEAN" -> "true";
+ default -> "9876543";
+ };
+ }
+
private String capitalize(String s) {
if (s == null || s.isEmpty()) {
return s;
+
+
|