From 60ce65f3e4dee0c0c734506b7bb549eb734ebb39 Mon Sep 17 00:00:00 2001 From: Jerry Yan <792602257@qq.com> Date: Fri, 5 Sep 2025 11:46:19 +0800 Subject: [PATCH 01/16] =?UTF-8?q?feat(integration):=20=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?=E6=B8=B2=E6=9F=93=E5=B7=A5=E4=BD=9C=E5=99=A8=E6=9C=8D=E5=8A=A1?= =?UTF-8?q?=E9=9B=86=E6=88=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增 RenderWorkerConfigV2Client 和 RenderWorkerV2Client 接口 - 实现 RenderWorkerConfigIntegrationService 和 RenderWorkerIntegrationService 服务类 - 添加相关 DTO 类和 BatchConfigBuilder 工具类 - 在 IntegrationProperties 中增加 render 相关配置 - 更新 CommonResponse 类,增加 success 字段 - 新增 RenderWorkerIntegrationConfig 配置类 --- .../java/com/ycwl/basic/integration/CLAUDE.md | 216 +++++++++++++ .../common/config/IntegrationProperties.java | 31 ++ .../common/response/CommonResponse.java | 16 +- .../client/RenderWorkerConfigV2Client.java | 59 ++++ .../render/client/RenderWorkerV2Client.java | 76 +++++ .../config/RenderWorkerIntegrationConfig.java | 19 ++ .../BatchRenderWorkerConfigRequest.java | 17 ++ .../dto/config/RenderWorkerConfigV2DTO.java | 63 ++++ .../dto/worker/CreateRenderWorkerRequest.java | 31 ++ .../render/dto/worker/RenderWorkerV2DTO.java | 49 +++ .../worker/RenderWorkerV2ListResponse.java | 33 ++ .../worker/RenderWorkerV2WithConfigDTO.java | 55 ++++ .../RenderWorkerV2WithConfigListResponse.java | 33 ++ .../dto/worker/UpdateRenderWorkerRequest.java | 27 ++ .../RenderWorkerConfigIntegrationService.java | 287 ++++++++++++++++++ .../RenderWorkerIntegrationService.java | 195 ++++++++++++ 16 files changed, 1201 insertions(+), 6 deletions(-) create mode 100644 src/main/java/com/ycwl/basic/integration/render/client/RenderWorkerConfigV2Client.java create mode 100644 src/main/java/com/ycwl/basic/integration/render/client/RenderWorkerV2Client.java create mode 100644 src/main/java/com/ycwl/basic/integration/render/config/RenderWorkerIntegrationConfig.java create mode 100644 src/main/java/com/ycwl/basic/integration/render/dto/config/BatchRenderWorkerConfigRequest.java create mode 100644 src/main/java/com/ycwl/basic/integration/render/dto/config/RenderWorkerConfigV2DTO.java create mode 100644 src/main/java/com/ycwl/basic/integration/render/dto/worker/CreateRenderWorkerRequest.java create mode 100644 src/main/java/com/ycwl/basic/integration/render/dto/worker/RenderWorkerV2DTO.java create mode 100644 src/main/java/com/ycwl/basic/integration/render/dto/worker/RenderWorkerV2ListResponse.java create mode 100644 src/main/java/com/ycwl/basic/integration/render/dto/worker/RenderWorkerV2WithConfigDTO.java create mode 100644 src/main/java/com/ycwl/basic/integration/render/dto/worker/RenderWorkerV2WithConfigListResponse.java create mode 100644 src/main/java/com/ycwl/basic/integration/render/dto/worker/UpdateRenderWorkerRequest.java create mode 100644 src/main/java/com/ycwl/basic/integration/render/service/RenderWorkerConfigIntegrationService.java create mode 100644 src/main/java/com/ycwl/basic/integration/render/service/RenderWorkerIntegrationService.java diff --git a/src/main/java/com/ycwl/basic/integration/CLAUDE.md b/src/main/java/com/ycwl/basic/integration/CLAUDE.md index 2eb1a1e..32f8db0 100644 --- a/src/main/java/com/ycwl/basic/integration/CLAUDE.md +++ b/src/main/java/com/ycwl/basic/integration/CLAUDE.md @@ -23,6 +23,7 @@ The integration package (`com.ycwl.basic.integration`) is responsible for extern Currently implemented: - **Scenic Integration** (`com.ycwl.basic.integration.scenic`): ZT-Scenic microservice integration - **Device Integration** (`com.ycwl.basic.integration.device`): ZT-Device microservice integration +- **Render Worker Integration** (`com.ycwl.basic.integration.render`): ZT-Render-Worker microservice integration ### Integration Pattern @@ -241,6 +242,13 @@ integration: readTimeout: 10000 retryEnabled: false maxRetries: 3 + render: + enabled: true + serviceName: zt-render-worker + connectTimeout: 5000 + readTimeout: 10000 + retryEnabled: false + maxRetries: 3 ``` ### Usage Examples @@ -534,6 +542,11 @@ integration: enabled: true # Enable fallback for device service ttlDays: 5 # Custom TTL for device (shorter due to dynamic data) # cachePrefix: "device:fallback:" # Optional custom prefix + + render: + enabled: true # Enable fallback for render worker service + ttlDays: 7 # Custom TTL for render worker (medium due to stable worker data) + # cachePrefix: "render:fallback:" # Optional custom prefix # Service configurations scenic: @@ -587,6 +600,205 @@ class ScenicIntegrationServiceTest { ### Integration Testing Use `@SpringBootTest` with test profiles and mock external services. +## Render Worker Integration (ZT-Render-Worker Microservice) + +### Key Components + +#### Feign Clients +- **RenderWorkerV2Client**: Main render worker operations (CRUD, listing) +- **RenderWorkerConfigV2Client**: Render worker configuration management + +#### Services +- **RenderWorkerIntegrationService**: High-level render worker operations (with automatic fallback) +- **RenderWorkerConfigIntegrationService**: Configuration management (with automatic fallback) + +#### Configuration +```yaml +integration: + render: + enabled: true + serviceName: zt-render-worker + connectTimeout: 5000 + readTimeout: 10000 + retryEnabled: false + maxRetries: 3 +``` + +### Usage Examples + +#### Basic Render Worker Operations (with Automatic Fallback) +```java +@Autowired +private RenderWorkerIntegrationService renderWorkerService; + +// Get render worker basic info (automatically falls back to cache on failure) +RenderWorkerV2DTO worker = renderWorkerService.getWorker(workerId); + +// Get render worker with configuration (automatically falls back to cache on failure) +RenderWorkerV2WithConfigDTO workerWithConfig = renderWorkerService.getWorkerWithConfig(workerId); + +// Get render worker by key (automatically falls back to cache on failure) +RenderWorkerV2DTO workerByKey = renderWorkerService.getWorkerByKey("video-renderer-001"); + +// Get render worker with config by key (automatically falls back to cache on failure) +RenderWorkerV2WithConfigDTO workerWithConfigByKey = renderWorkerService.getWorkerWithConfigByKey("video-renderer-001"); + +// Create new render worker (direct operation, fails immediately on error) +CreateRenderWorkerRequest request = new CreateRenderWorkerRequest(); +request.setName("Video Renderer"); +request.setKey("video-renderer-001"); +request.setIsActive(1); +RenderWorkerV2DTO newWorker = renderWorkerService.createWorker(request); + +// Update render worker (direct operation, fails immediately on error) +UpdateRenderWorkerRequest updateRequest = new UpdateRenderWorkerRequest(); +updateRequest.setName("Updated Video Renderer"); +renderWorkerService.updateWorker(workerId, updateRequest); + +// Delete render worker (direct operation, fails immediately on error) +renderWorkerService.deleteWorker(workerId); + +// List render workers (no fallback for list operations) +List workers = renderWorkerService.listWorkers(1, 10, 1, null); + +// List render workers with config (no fallback for list operations) +List workersWithConfig = + renderWorkerService.listWorkersWithConfig(1, 10, 1, null); +``` + +#### Configuration Management (with Automatic Fallback) +```java +@Autowired +private RenderWorkerConfigIntegrationService configService; + +// Get worker configurations (with fallback) +List configs = configService.getWorkerConfigs(workerId); + +// Get flat configuration (automatically falls back to cache on failure) +Map flatConfig = configService.getWorkerFlatConfig(workerId); + +// Get specific configuration by key (with fallback) +RenderWorkerConfigV2DTO config = configService.getWorkerConfigByKey(workerId, "render_quality"); + +// Create configuration (direct operation, fails immediately on error) +RenderWorkerConfigV2DTO newConfig = new RenderWorkerConfigV2DTO(); +newConfig.setConfigKey("max_concurrent_tasks"); +newConfig.setConfigValue("4"); +newConfig.setConfigType("int"); +newConfig.setDescription("Maximum concurrent render tasks"); +newConfig.setIsActive(1); +RenderWorkerConfigV2DTO created = configService.createWorkerConfig(workerId, newConfig); + +// Update configuration (direct operation, fails immediately on error) +Map updates = new HashMap<>(); +updates.put("configValue", "8"); +configService.updateWorkerConfig(workerId, configId, updates); + +// Delete configuration (direct operation, fails immediately on error) +configService.deleteWorkerConfig(workerId, configId); +``` + +#### Enhanced Batch Configuration API +```java +// Using Builder Pattern for batch configuration +BatchRenderWorkerConfigRequest request = configService.createBatchConfigBuilder() + .addRenderConfig("high", "mp4", "1920x1080") // Render settings + .addPerformanceConfig(8, 3600) // Performance settings + .addConfig("output_path", "/data/renders", "string", "Output directory") + .addConfig("enable_gpu", "true", "bool", "Enable GPU acceleration") + .build(); + +// Batch update configurations (direct operation, fails immediately on error) +configService.batchUpdateWorkerConfigs(workerId, request); + +// Batch flat update configurations (direct operation, fails immediately on error) +Map flatUpdates = new HashMap<>(); +flatUpdates.put("render_quality", "ultra"); +flatUpdates.put("max_concurrent_tasks", 12); +flatUpdates.put("enable_preview", true); +configService.batchFlatUpdateWorkerConfigs(workerId, flatUpdates); +``` + +#### Render Worker Management Patterns +```java +// Create and configure render worker in one operation +CreateRenderWorkerRequest workerRequest = new CreateRenderWorkerRequest(); +workerRequest.setName("4K Video Renderer"); +workerRequest.setKey("4k-video-renderer"); +RenderWorkerV2DTO worker = renderWorkerService.createWorker(workerRequest); + +// Configure the worker for 4K video rendering +BatchRenderWorkerConfigRequest config = configService.createBatchConfigBuilder() + .addRenderConfig("ultra", "mp4", "3840x2160") + .addPerformanceConfig(4, 7200) // 4 concurrent tasks, 2 hour timeout + .addConfig("gpu_memory_limit", "8192", "int", "GPU memory limit in MB") + .addConfig("codec", "h265", "string", "Video codec") + .addConfig("bitrate", "50000", "int", "Video bitrate in kbps") + .build(); +configService.batchUpdateWorkerConfigs(worker.getId(), config); + +// Monitor worker configuration completeness (with automatic fallback) +Map workerConfig = configService.getWorkerFlatConfig(worker.getId()); +boolean hasRenderConfig = workerConfig.containsKey("render_quality"); +boolean hasPerformanceConfig = workerConfig.containsKey("max_concurrent_tasks"); +// log configuration status... + +// Get all active workers for monitoring +List activeWorkers = + renderWorkerService.listWorkersWithConfig(1, 100, 1, null); + +// Check worker health and configuration +for (RenderWorkerV2WithConfigDTO activeWorker : activeWorkers) { + Map config = activeWorker.getConfig(); + boolean isConfigured = config.containsKey("render_quality") && + config.containsKey("max_concurrent_tasks"); + // log worker status... +} +``` + +#### Fallback Cache Management for Render Workers +```java +@Autowired +private IntegrationFallbackService fallbackService; + +// Check fallback cache status +boolean hasWorkerCache = fallbackService.hasFallbackCache("zt-render-worker", "worker:1001"); +boolean hasWorkerByKeyCache = fallbackService.hasFallbackCache("zt-render-worker", "worker:key:video-renderer-001"); +boolean hasConfigCache = fallbackService.hasFallbackCache("zt-render-worker", "worker:flat:config:1001"); +boolean hasConfigByKeyCache = fallbackService.hasFallbackCache("zt-render-worker", "worker:key:config:video-renderer-001"); + +// Get cache statistics +IntegrationFallbackService.FallbackCacheStats stats = + fallbackService.getFallbackCacheStats("zt-render-worker"); +log.info("Render worker fallback cache: {} items, TTL: {} days", + stats.getTotalCacheCount(), stats.getFallbackTtlDays()); + +// Clear specific cache +fallbackService.clearFallbackCache("zt-render-worker", "worker:1001"); + +// Clear all render worker caches +fallbackService.clearAllFallbackCache("zt-render-worker"); +``` + +### Render Worker Types and Configuration + +#### Common Configuration Keys +- `render_quality`: Render quality level ("low", "medium", "high", "ultra") +- `render_format`: Output format ("mp4", "avi", "mov", "webm") +- `render_resolution`: Video resolution ("1920x1080", "3840x2160", "1280x720") +- `max_concurrent_tasks`: Maximum concurrent render tasks (integer) +- `task_timeout`: Task timeout in seconds (integer) +- `output_path`: Render output directory path (string) +- `enable_gpu`: Enable GPU acceleration (boolean) +- `gpu_memory_limit`: GPU memory limit in MB (integer) +- `codec`: Video codec ("h264", "h265", "vp9") +- `bitrate`: Video bitrate in kbps (integer) +- `enable_preview`: Enable preview generation (boolean) + +#### Worker Status +- **Active (isActive=1)**: Worker is available for tasks +- **Inactive (isActive=0)**: Worker is disabled + ## Common Development Tasks ### Running Integration Tests @@ -600,6 +812,10 @@ mvn test -Dtest="com.ycwl.basic.integration.*Test" # Run device integration tests mvn test -Dtest=DeviceIntegrationServiceTest mvn test -Dtest="com.ycwl.basic.integration.device.*Test" + +# Run render worker integration tests +mvn test -Dtest=RenderWorkerIntegrationServiceTest +mvn test -Dtest="com.ycwl.basic.integration.render.*Test" ``` ### Adding New DTOs diff --git a/src/main/java/com/ycwl/basic/integration/common/config/IntegrationProperties.java b/src/main/java/com/ycwl/basic/integration/common/config/IntegrationProperties.java index a25541e..aa10a5c 100644 --- a/src/main/java/com/ycwl/basic/integration/common/config/IntegrationProperties.java +++ b/src/main/java/com/ycwl/basic/integration/common/config/IntegrationProperties.java @@ -26,6 +26,11 @@ public class IntegrationProperties { */ private DeviceConfig device = new DeviceConfig(); + /** + * 渲染工作器服务配置 + */ + private RenderWorkerConfig render = new RenderWorkerConfig(); + @Data public static class ScenicConfig { /** @@ -98,6 +103,32 @@ public class IntegrationProperties { */ private ServiceFallbackConfig scenic = new ServiceFallbackConfig(); private ServiceFallbackConfig device = new ServiceFallbackConfig(); + private ServiceFallbackConfig render = new ServiceFallbackConfig(); + } + + @Data + public static class RenderWorkerConfig { + /** + * 是否启用渲染工作器服务集成 + */ + private boolean enabled = true; + + /** + * 服务名称 + */ + private String serviceName = "zt-render-worker"; + + /** + * 超时配置(毫秒) + */ + private int connectTimeout = 5000; + private int readTimeout = 10000; + + /** + * 重试配置 + */ + private boolean retryEnabled = false; + private int maxRetries = 3; } @Data diff --git a/src/main/java/com/ycwl/basic/integration/common/response/CommonResponse.java b/src/main/java/com/ycwl/basic/integration/common/response/CommonResponse.java index 2d7d7f1..d5d9541 100644 --- a/src/main/java/com/ycwl/basic/integration/common/response/CommonResponse.java +++ b/src/main/java/com/ycwl/basic/integration/common/response/CommonResponse.java @@ -12,29 +12,33 @@ import lombok.AllArgsConstructor; public class CommonResponse { private Integer code; private String message; + private Boolean success; private T data; public static CommonResponse success() { - return new CommonResponse<>(200, "OK", null); + return new CommonResponse<>(200, "OK", true, null); } public static CommonResponse success(T data) { - return new CommonResponse<>(200, "OK", data); + return new CommonResponse<>(200, "OK", true, data); } public static CommonResponse success(String message, T data) { - return new CommonResponse<>(200, message, data); + return new CommonResponse<>(200, message, true, data); } public static CommonResponse error(Integer code, String message) { - return new CommonResponse<>(code, message, null); + return new CommonResponse<>(code, message, false, null); } public static CommonResponse error(String message) { - return new CommonResponse<>(5000, message, null); + return new CommonResponse<>(5000, message, false, null); } public boolean isSuccess() { - return code != null && code == 200; + if (success == null) { // compatible + return code != null && code == 200; + } + return success; } } \ No newline at end of file diff --git a/src/main/java/com/ycwl/basic/integration/render/client/RenderWorkerConfigV2Client.java b/src/main/java/com/ycwl/basic/integration/render/client/RenderWorkerConfigV2Client.java new file mode 100644 index 0000000..fa478c3 --- /dev/null +++ b/src/main/java/com/ycwl/basic/integration/render/client/RenderWorkerConfigV2Client.java @@ -0,0 +1,59 @@ +package com.ycwl.basic.integration.render.client; + +import com.ycwl.basic.integration.common.response.CommonResponse; +import com.ycwl.basic.integration.render.dto.config.BatchRenderWorkerConfigRequest; +import com.ycwl.basic.integration.render.dto.config.RenderWorkerConfigV2DTO; +import org.springframework.cloud.openfeign.FeignClient; +import org.springframework.web.bind.annotation.*; + +import java.util.List; +import java.util.Map; + +/** + * 渲染工作器配置V2客户端 + */ +@FeignClient(name = "zt-render-worker", contextId = "render-worker-config-v2", path = "/api/render/worker/config/v2") +public interface RenderWorkerConfigV2Client { + + /** + * 获取工作器所有配置 + */ + @GetMapping("/{workerId}") + CommonResponse> getWorkerConfigs(@PathVariable("workerId") Long workerId); + + /** + * 根据配置键获取特定配置 + */ + @GetMapping("/{workerId}/key/{configKey}") + CommonResponse getWorkerConfigByKey(@PathVariable("workerId") Long workerId, + @PathVariable("configKey") String configKey); + + /** + * 创建配置 + */ + @PostMapping("/{workerId}") + CommonResponse createWorkerConfig(@PathVariable("workerId") Long workerId, + @RequestBody RenderWorkerConfigV2DTO config); + + /** + * 更新配置 + */ + @PutMapping("/{workerId}/{id}") + CommonResponse updateWorkerConfig(@PathVariable("workerId") Long workerId, + @PathVariable("id") Long id, + @RequestBody Map updates); + + /** + * 删除配置 + */ + @DeleteMapping("/{workerId}/{id}") + CommonResponse deleteWorkerConfig(@PathVariable("workerId") Long workerId, + @PathVariable("id") Long id); + + /** + * 批量更新配置 + */ + @PostMapping("/{workerId}/batch") + CommonResponse batchUpdateWorkerConfigs(@PathVariable("workerId") Long workerId, + @RequestBody BatchRenderWorkerConfigRequest request); +} \ No newline at end of file diff --git a/src/main/java/com/ycwl/basic/integration/render/client/RenderWorkerV2Client.java b/src/main/java/com/ycwl/basic/integration/render/client/RenderWorkerV2Client.java new file mode 100644 index 0000000..b73df45 --- /dev/null +++ b/src/main/java/com/ycwl/basic/integration/render/client/RenderWorkerV2Client.java @@ -0,0 +1,76 @@ +package com.ycwl.basic.integration.render.client; + +import com.ycwl.basic.integration.common.response.CommonResponse; +import com.ycwl.basic.integration.common.response.PageResponse; +import com.ycwl.basic.integration.render.dto.worker.*; +import org.springframework.cloud.openfeign.FeignClient; +import org.springframework.web.bind.annotation.*; + +/** + * 渲染工作器V2客户端 + */ +@FeignClient(name = "zt-render-worker", contextId = "render-worker-v2", path = "/api/render/worker/v2") +public interface RenderWorkerV2Client { + + /** + * 获取工作器核心信息 + */ + @GetMapping("/{id}") + CommonResponse getWorker(@PathVariable("id") Long id); + + /** + * 获取工作器含配置信息 + */ + @GetMapping("/{id}/with-config") + CommonResponse getWorkerWithConfig(@PathVariable("id") Long id); + + /** + * 创建工作器 + */ + @PostMapping + CommonResponse createWorker(@RequestBody CreateRenderWorkerRequest request); + + /** + * 更新工作器 + */ + @PutMapping("/{id}") + CommonResponse updateWorker(@PathVariable("id") Long id, + @RequestBody UpdateRenderWorkerRequest request); + + /** + * 删除工作器 + */ + @DeleteMapping("/{id}") + CommonResponse deleteWorker(@PathVariable("id") Long id); + + /** + * 分页查询工作器列表(核心信息) + */ + @GetMapping + PageResponse listWorkers(@RequestParam(defaultValue = "1") Integer page, + @RequestParam(defaultValue = "10") Integer pageSize, + @RequestParam(required = false) Integer isEnabled, + @RequestParam(required = false) String name); + + /** + * 分页查询工作器列表(含配置信息) + */ + @GetMapping("/with-config") + PageResponse listWorkersWithConfig( + @RequestParam(defaultValue = "1") Integer page, + @RequestParam(defaultValue = "10") Integer pageSize, + @RequestParam(required = false) Integer isEnabled, + @RequestParam(required = false) String name); + + /** + * 根据key获取工作器核心信息 + */ + @GetMapping("/key/{key}") + CommonResponse getWorkerByKey(@PathVariable("key") String key); + + /** + * 根据key获取工作器完整信息(含配置) + */ + @GetMapping("/key/{key}/with-config") + CommonResponse getWorkerWithConfigByKey(@PathVariable("key") String key); +} \ No newline at end of file diff --git a/src/main/java/com/ycwl/basic/integration/render/config/RenderWorkerIntegrationConfig.java b/src/main/java/com/ycwl/basic/integration/render/config/RenderWorkerIntegrationConfig.java new file mode 100644 index 0000000..65e4edc --- /dev/null +++ b/src/main/java/com/ycwl/basic/integration/render/config/RenderWorkerIntegrationConfig.java @@ -0,0 +1,19 @@ +package com.ycwl.basic.integration.render.config; + +import com.ycwl.basic.integration.common.config.IntegrationProperties; +import lombok.RequiredArgsConstructor; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.cloud.openfeign.EnableFeignClients; +import org.springframework.context.annotation.Configuration; + +/** + * 渲染工作器集成配置 + */ +@Configuration +@ConditionalOnProperty(prefix = "integration.render", name = "enabled", havingValue = "true", matchIfMissing = true) +@EnableFeignClients(basePackages = "com.ycwl.basic.integration.render.client") +@RequiredArgsConstructor +public class RenderWorkerIntegrationConfig { + + private final IntegrationProperties integrationProperties; +} \ No newline at end of file diff --git a/src/main/java/com/ycwl/basic/integration/render/dto/config/BatchRenderWorkerConfigRequest.java b/src/main/java/com/ycwl/basic/integration/render/dto/config/BatchRenderWorkerConfigRequest.java new file mode 100644 index 0000000..c44f5f4 --- /dev/null +++ b/src/main/java/com/ycwl/basic/integration/render/dto/config/BatchRenderWorkerConfigRequest.java @@ -0,0 +1,17 @@ +package com.ycwl.basic.integration.render.dto.config; + +import lombok.Data; + +import java.util.List; + +/** + * 批量更新渲染工作器配置请求DTO + */ +@Data +public class BatchRenderWorkerConfigRequest { + + /** + * 配置列表 + */ + private List configs; +} \ No newline at end of file diff --git a/src/main/java/com/ycwl/basic/integration/render/dto/config/RenderWorkerConfigV2DTO.java b/src/main/java/com/ycwl/basic/integration/render/dto/config/RenderWorkerConfigV2DTO.java new file mode 100644 index 0000000..1f0aaad --- /dev/null +++ b/src/main/java/com/ycwl/basic/integration/render/dto/config/RenderWorkerConfigV2DTO.java @@ -0,0 +1,63 @@ +package com.ycwl.basic.integration.render.dto.config; + +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Data; + +/** + * 渲染工作器配置DTO + */ +@Data +public class RenderWorkerConfigV2DTO { + + /** + * 配置ID + */ + private Long id; + + /** + * 工作器ID + */ + @JsonProperty("worker_id") + private Long workerId; + + /** + * 配置键 + */ + @JsonProperty("config_key") + private String configKey; + + /** + * 配置值 + */ + @JsonProperty("config_value") + private String configValue; + + /** + * 配置类型 (string/int/float/bool/json) + */ + @JsonProperty("config_type") + private String configType; + + /** + * 描述 + */ + private String description; + + /** + * 是否启用 (0-禁用,1-启用) + */ + @JsonProperty("is_active") + private Integer isActive; + + /** + * 创建时间 + */ + @JsonProperty("create_time") + private String createTime; + + /** + * 更新时间 + */ + @JsonProperty("update_time") + private String updateTime; +} \ No newline at end of file diff --git a/src/main/java/com/ycwl/basic/integration/render/dto/worker/CreateRenderWorkerRequest.java b/src/main/java/com/ycwl/basic/integration/render/dto/worker/CreateRenderWorkerRequest.java new file mode 100644 index 0000000..d7d3493 --- /dev/null +++ b/src/main/java/com/ycwl/basic/integration/render/dto/worker/CreateRenderWorkerRequest.java @@ -0,0 +1,31 @@ +package com.ycwl.basic.integration.render.dto.worker; + +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Data; + +import javax.validation.constraints.NotBlank; + +/** + * 创建渲染工作器请求DTO + */ +@Data +public class CreateRenderWorkerRequest { + + /** + * 工作器名称 + */ + @NotBlank(message = "工作器名称不能为空") + private String name; + + /** + * 工作器标识 + */ + @NotBlank(message = "工作器标识不能为空") + private String key; + + /** + * 是否启用 (0-禁用,1-启用) + */ + @JsonProperty("is_active") + private Integer isActive = 1; +} \ No newline at end of file diff --git a/src/main/java/com/ycwl/basic/integration/render/dto/worker/RenderWorkerV2DTO.java b/src/main/java/com/ycwl/basic/integration/render/dto/worker/RenderWorkerV2DTO.java new file mode 100644 index 0000000..32745ee --- /dev/null +++ b/src/main/java/com/ycwl/basic/integration/render/dto/worker/RenderWorkerV2DTO.java @@ -0,0 +1,49 @@ +package com.ycwl.basic.integration.render.dto.worker; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Data; + +import java.util.Date; + +/** + * 渲染工作器核心信息DTO + */ +@Data +public class RenderWorkerV2DTO { + + /** + * 工作器ID + */ + private Long id; + + /** + * 工作器名称 + */ + private String name; + + /** + * 工作器标识 + */ + private String key; + + /** + * 是否启用 (0-禁用,1-启用) + */ + @JsonProperty("is_active") + private Integer isActive; + + /** + * 创建时间 + */ + @JsonProperty("create_time") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date createTime; + + /** + * 更新时间 + */ + @JsonProperty("update_time") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date updateTime; +} \ No newline at end of file diff --git a/src/main/java/com/ycwl/basic/integration/render/dto/worker/RenderWorkerV2ListResponse.java b/src/main/java/com/ycwl/basic/integration/render/dto/worker/RenderWorkerV2ListResponse.java new file mode 100644 index 0000000..a70d365 --- /dev/null +++ b/src/main/java/com/ycwl/basic/integration/render/dto/worker/RenderWorkerV2ListResponse.java @@ -0,0 +1,33 @@ +package com.ycwl.basic.integration.render.dto.worker; + +import lombok.Data; + +import java.util.List; + +/** + * 渲染工作器列表响应DTO + */ +@Data +public class RenderWorkerV2ListResponse { + + /** + * 工作器列表 + */ + private List list; + + /** + * 总数 + */ + private String total; + + /** + * 当前页 + */ + private Integer page; + + /** + * 页大小 + */ + @SuppressWarnings("unused") + private Integer pageSize; +} \ No newline at end of file diff --git a/src/main/java/com/ycwl/basic/integration/render/dto/worker/RenderWorkerV2WithConfigDTO.java b/src/main/java/com/ycwl/basic/integration/render/dto/worker/RenderWorkerV2WithConfigDTO.java new file mode 100644 index 0000000..e3bb5d6 --- /dev/null +++ b/src/main/java/com/ycwl/basic/integration/render/dto/worker/RenderWorkerV2WithConfigDTO.java @@ -0,0 +1,55 @@ +package com.ycwl.basic.integration.render.dto.worker; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Data; + +import java.util.Date; +import java.util.Map; + +/** + * 带配置的渲染工作器DTO + */ +@Data +public class RenderWorkerV2WithConfigDTO { + + /** + * 工作器ID + */ + private Long id; + + /** + * 工作器名称 + */ + private String name; + + /** + * 工作器标识 + */ + private String key; + + /** + * 是否启用 (0-禁用,1-启用) + */ + @JsonProperty("is_active") + private Integer isActive; + + /** + * 创建时间 + */ + @JsonProperty("create_time") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date createTime; + + /** + * 更新时间 + */ + @JsonProperty("update_time") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date updateTime; + + /** + * 动态配置信息 + */ + private Map config; +} \ No newline at end of file diff --git a/src/main/java/com/ycwl/basic/integration/render/dto/worker/RenderWorkerV2WithConfigListResponse.java b/src/main/java/com/ycwl/basic/integration/render/dto/worker/RenderWorkerV2WithConfigListResponse.java new file mode 100644 index 0000000..e326742 --- /dev/null +++ b/src/main/java/com/ycwl/basic/integration/render/dto/worker/RenderWorkerV2WithConfigListResponse.java @@ -0,0 +1,33 @@ +package com.ycwl.basic.integration.render.dto.worker; + +import lombok.Data; + +import java.util.List; + +/** + * 带配置的渲染工作器列表响应DTO + */ +@Data +public class RenderWorkerV2WithConfigListResponse { + + /** + * 工作器列表 + */ + private List list; + + /** + * 总数 + */ + private String total; + + /** + * 当前页 + */ + private Integer page; + + /** + * 页大小 + */ + @SuppressWarnings("unused") + private Integer pageSize; +} \ No newline at end of file diff --git a/src/main/java/com/ycwl/basic/integration/render/dto/worker/UpdateRenderWorkerRequest.java b/src/main/java/com/ycwl/basic/integration/render/dto/worker/UpdateRenderWorkerRequest.java new file mode 100644 index 0000000..6c879b1 --- /dev/null +++ b/src/main/java/com/ycwl/basic/integration/render/dto/worker/UpdateRenderWorkerRequest.java @@ -0,0 +1,27 @@ +package com.ycwl.basic.integration.render.dto.worker; + +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Data; + +/** + * 更新渲染工作器请求DTO + */ +@Data +public class UpdateRenderWorkerRequest { + + /** + * 工作器名称 + */ + private String name; + + /** + * 工作器标识 + */ + private String key; + + /** + * 是否启用 (0-禁用,1-启用) + */ + @JsonProperty("is_active") + private Integer isActive; +} \ No newline at end of file diff --git a/src/main/java/com/ycwl/basic/integration/render/service/RenderWorkerConfigIntegrationService.java b/src/main/java/com/ycwl/basic/integration/render/service/RenderWorkerConfigIntegrationService.java new file mode 100644 index 0000000..0fbe084 --- /dev/null +++ b/src/main/java/com/ycwl/basic/integration/render/service/RenderWorkerConfigIntegrationService.java @@ -0,0 +1,287 @@ +package com.ycwl.basic.integration.render.service; + +import com.ycwl.basic.integration.common.exception.IntegrationException; +import com.ycwl.basic.integration.common.response.CommonResponse; +import com.ycwl.basic.integration.common.service.IntegrationFallbackService; +import com.ycwl.basic.integration.render.client.RenderWorkerConfigV2Client; +import com.ycwl.basic.integration.render.dto.config.BatchRenderWorkerConfigRequest; +import com.ycwl.basic.integration.render.dto.config.RenderWorkerConfigV2DTO; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * 渲染工作器配置集成服务 + */ +@Slf4j +@Service +@RequiredArgsConstructor +public class RenderWorkerConfigIntegrationService { + + private final RenderWorkerConfigV2Client renderWorkerConfigV2Client; + private final IntegrationFallbackService fallbackService; + + private static final String SERVICE_NAME = "zt-render-worker"; + + /** + * 获取工作器所有配置(带降级) + */ + public List getWorkerConfigs(Long workerId) { + log.info("获取渲染工作器配置列表, workerId: {}", workerId); + return fallbackService.executeWithFallback( + SERVICE_NAME, + "worker:configs:" + workerId, + () -> { + CommonResponse> response = + renderWorkerConfigV2Client.getWorkerConfigs(workerId); + List configs = handleResponse(response, "获取渲染工作器配置列表失败"); + return configs != null ? configs : Collections.emptyList(); + }, + List.class + ); + } + + /** + * 根据配置键获取特定配置(带降级) + */ + public RenderWorkerConfigV2DTO getWorkerConfigByKey(Long workerId, String configKey) { + log.info("根据配置键获取渲染工作器配置, workerId: {}, configKey: {}", workerId, configKey); + return fallbackService.executeWithFallback( + SERVICE_NAME, + "worker:config:" + workerId + ":" + configKey, + () -> { + CommonResponse response = + renderWorkerConfigV2Client.getWorkerConfigByKey(workerId, configKey); + return handleResponse(response, "根据配置键获取渲染工作器配置失败"); + }, + RenderWorkerConfigV2DTO.class + ); + } + + /** + * 获取工作器平铺配置(带降级) + */ + public Map getWorkerFlatConfig(Long workerId) { + log.info("获取渲染工作器平铺配置, workerId: {}", workerId); + return fallbackService.executeWithFallback( + SERVICE_NAME, + "worker:flat:config:" + workerId, + () -> { + List configs = getWorkerConfigsInternal(workerId); + return flattenConfigs(configs); + }, + Map.class + ); + } + + /** + * 创建配置(直接调用,不降级) + */ + public RenderWorkerConfigV2DTO createWorkerConfig(Long workerId, RenderWorkerConfigV2DTO config) { + log.info("创建渲染工作器配置, workerId: {}, configKey: {}", workerId, config.getConfigKey()); + CommonResponse response = + renderWorkerConfigV2Client.createWorkerConfig(workerId, config); + return handleResponse(response, "创建渲染工作器配置失败"); + } + + /** + * 更新配置(直接调用,不降级) + */ + public void updateWorkerConfig(Long workerId, Long configId, Map updates) { + log.info("更新渲染工作器配置, workerId: {}, configId: {}", workerId, configId); + CommonResponse response = + renderWorkerConfigV2Client.updateWorkerConfig(workerId, configId, updates); + handleVoidResponse(response, "更新渲染工作器配置失败"); + } + + /** + * 删除配置(直接调用,不降级) + */ + public void deleteWorkerConfig(Long workerId, Long configId) { + log.info("删除渲染工作器配置, workerId: {}, configId: {}", workerId, configId); + CommonResponse response = + renderWorkerConfigV2Client.deleteWorkerConfig(workerId, configId); + handleVoidResponse(response, "删除渲染工作器配置失败"); + } + + /** + * 批量更新配置(直接调用,不降级) + */ + public void batchUpdateWorkerConfigs(Long workerId, BatchRenderWorkerConfigRequest request) { + log.info("批量更新渲染工作器配置, workerId: {}, configCount: {}", + workerId, request.getConfigs() != null ? request.getConfigs().size() : 0); + CommonResponse response = + renderWorkerConfigV2Client.batchUpdateWorkerConfigs(workerId, request); + handleVoidResponse(response, "批量更新渲染工作器配置失败"); + } + + /** + * 批量平铺更新配置(直接调用,不降级) + */ + public void batchFlatUpdateWorkerConfigs(Long workerId, Map flatConfigs) { + log.info("批量平铺更新渲染工作器配置, workerId: {}, configCount: {}", + workerId, flatConfigs.size()); + + BatchRenderWorkerConfigRequest request = new BatchRenderWorkerConfigRequest(); + List configs = flatConfigs.entrySet().stream() + .map(entry -> { + RenderWorkerConfigV2DTO config = new RenderWorkerConfigV2DTO(); + config.setConfigKey(entry.getKey()); + config.setConfigValue(String.valueOf(entry.getValue())); + config.setConfigType(determineConfigType(entry.getValue())); + config.setIsActive(1); + return config; + }) + .toList(); + + request.setConfigs(configs); + batchUpdateWorkerConfigs(workerId, request); + } + + /** + * 创建批量配置构建器 + */ + public BatchConfigBuilder createBatchConfigBuilder() { + return new BatchConfigBuilder(); + } + + /** + * 内部获取配置方法(不使用降级) + */ + private List getWorkerConfigsInternal(Long workerId) { + CommonResponse> response = + renderWorkerConfigV2Client.getWorkerConfigs(workerId); + List configs = handleResponse(response, "获取渲染工作器配置列表失败"); + return configs != null ? configs : Collections.emptyList(); + } + + /** + * 将配置列表转换为平铺Map + */ + private Map flattenConfigs(List configs) { + Map flatConfig = new HashMap<>(); + for (RenderWorkerConfigV2DTO config : configs) { + if (config.getIsActive() == 1) { + Object value = convertConfigValue(config.getConfigValue(), config.getConfigType()); + flatConfig.put(config.getConfigKey(), value); + } + } + return flatConfig; + } + + /** + * 根据配置类型转换配置值 + */ + private Object convertConfigValue(String configValue, String configType) { + if (configValue == null) return null; + + return switch (configType) { + case "int" -> Integer.parseInt(configValue); + case "float" -> Double.parseDouble(configValue); + case "bool" -> Boolean.parseBoolean(configValue); + case "json" -> configValue; // 保持JSON字符串格式 + default -> configValue; // string类型或其他 + }; + } + + /** + * 自动判断配置类型 + */ + private String determineConfigType(Object value) { + if (value instanceof Integer) return "int"; + if (value instanceof Double || value instanceof Float) return "float"; + if (value instanceof Boolean) return "bool"; + return "string"; + } + + /** + * 处理通用响应 + */ + private T handleResponse(CommonResponse response, String errorMessage) { + if (response == null || !response.getSuccess()) { + String msg = response != null && response.getMessage() != null ? + response.getMessage() : errorMessage; + Integer code = response != null ? response.getCode() : 5000; + throw new IntegrationException(code, msg, SERVICE_NAME); + } + return response.getData(); + } + + /** + * 处理空响应 + */ + private void handleVoidResponse(CommonResponse response, String errorMessage) { + if (response == null || !response.getSuccess()) { + String msg = response != null && response.getMessage() != null ? + response.getMessage() : errorMessage; + Integer code = response != null ? response.getCode() : 5000; + throw new IntegrationException(code, msg, SERVICE_NAME); + } + } + + /** + * 批量配置构建器 + */ + public static class BatchConfigBuilder { + private final List configs = new java.util.ArrayList<>(); + + /** + * 添加配置项 + */ + public BatchConfigBuilder addConfig(String key, String value) { + return addConfig(key, value, "string", null); + } + + /** + * 添加配置项(指定类型) + */ + public BatchConfigBuilder addConfig(String key, String value, String type) { + return addConfig(key, value, type, null); + } + + /** + * 添加配置项(完整) + */ + public BatchConfigBuilder addConfig(String key, String value, String type, String description) { + RenderWorkerConfigV2DTO config = new RenderWorkerConfigV2DTO(); + config.setConfigKey(key); + config.setConfigValue(value); + config.setConfigType(type); + config.setDescription(description); + config.setIsActive(1); + configs.add(config); + return this; + } + + /** + * 添加渲染配置 + */ + public BatchConfigBuilder addRenderConfig(String quality, String format, String resolution) { + return addConfig("render_quality", quality, "string", "渲染质量") + .addConfig("render_format", format, "string", "渲染格式") + .addConfig("render_resolution", resolution, "string", "渲染分辨率"); + } + + /** + * 添加性能配置 + */ + public BatchConfigBuilder addPerformanceConfig(Integer maxTasks, Integer timeout) { + return addConfig("max_concurrent_tasks", String.valueOf(maxTasks), "int", "最大并发任务数") + .addConfig("task_timeout", String.valueOf(timeout), "int", "任务超时时间(秒)"); + } + + /** + * 构建批量配置请求 + */ + public BatchRenderWorkerConfigRequest build() { + BatchRenderWorkerConfigRequest request = new BatchRenderWorkerConfigRequest(); + request.setConfigs(configs); + return request; + } + } +} \ No newline at end of file diff --git a/src/main/java/com/ycwl/basic/integration/render/service/RenderWorkerIntegrationService.java b/src/main/java/com/ycwl/basic/integration/render/service/RenderWorkerIntegrationService.java new file mode 100644 index 0000000..e33920a --- /dev/null +++ b/src/main/java/com/ycwl/basic/integration/render/service/RenderWorkerIntegrationService.java @@ -0,0 +1,195 @@ +package com.ycwl.basic.integration.render.service; + +import com.ycwl.basic.integration.common.exception.IntegrationException; +import com.ycwl.basic.integration.common.response.CommonResponse; +import com.ycwl.basic.integration.common.response.PageResponse; +import com.ycwl.basic.integration.common.service.IntegrationFallbackService; +import com.ycwl.basic.integration.render.client.RenderWorkerV2Client; +import com.ycwl.basic.integration.render.dto.worker.*; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +import java.util.Collections; +import java.util.List; + +/** + * 渲染工作器集成服务 + */ +@Slf4j +@Service +@RequiredArgsConstructor +public class RenderWorkerIntegrationService { + + private final RenderWorkerV2Client renderWorkerV2Client; + private final IntegrationFallbackService fallbackService; + + private static final String SERVICE_NAME = "zt-render-worker"; + + /** + * 获取工作器核心信息(带降级) + */ + public RenderWorkerV2DTO getWorker(Long id) { + log.info("获取渲染工作器信息, id: {}", id); + return fallbackService.executeWithFallback( + SERVICE_NAME, + "worker:" + id, + () -> { + CommonResponse response = renderWorkerV2Client.getWorker(id); + return handleResponse(response, "获取渲染工作器信息失败"); + }, + RenderWorkerV2DTO.class + ); + } + + /** + * 获取工作器详细信息(含配置)(带降级) + */ + public RenderWorkerV2WithConfigDTO getWorkerWithConfig(Long id) { + log.info("获取渲染工作器详细信息, id: {}", id); + return fallbackService.executeWithFallback( + SERVICE_NAME, + "worker:config:" + id, + () -> { + CommonResponse response = renderWorkerV2Client.getWorkerWithConfig(id); + return handleResponse(response, "获取渲染工作器详细信息失败"); + }, + RenderWorkerV2WithConfigDTO.class + ); + } + + /** + * 创建工作器(直接调用,不降级) + */ + public RenderWorkerV2DTO createWorker(CreateRenderWorkerRequest request) { + log.info("创建渲染工作器, name: {}, key: {}", request.getName(), request.getKey()); + CommonResponse response = renderWorkerV2Client.createWorker(request); + return handleResponse(response, "创建渲染工作器失败"); + } + + /** + * 更新工作器(直接调用,不降级) + */ + public void updateWorker(Long id, UpdateRenderWorkerRequest request) { + log.info("更新渲染工作器, id: {}, name: {}", id, request.getName()); + CommonResponse response = renderWorkerV2Client.updateWorker(id, request); + handleVoidResponse(response, "更新渲染工作器失败"); + } + + /** + * 删除工作器(直接调用,不降级) + */ + public void deleteWorker(Long id) { + log.info("删除渲染工作器, id: {}", id); + CommonResponse response = renderWorkerV2Client.deleteWorker(id); + handleVoidResponse(response, "删除渲染工作器失败"); + } + + /** + * 分页查询工作器列表(核心信息)(不降级) + */ + public List listWorkers(Integer page, Integer pageSize, Integer isEnabled, String name) { + log.info("分页查询渲染工作器列表, page: {}, pageSize: {}, isEnabled: {}, name: {}", + page, pageSize, isEnabled, name); + try { + PageResponse response = + renderWorkerV2Client.listWorkers(page, pageSize, isEnabled, name); + RenderWorkerV2ListResponse listResponse = handlePageResponse(response, "查询渲染工作器列表失败"); + return listResponse != null && listResponse.getList() != null ? + listResponse.getList() : Collections.emptyList(); + } catch (Exception e) { + log.error("查询渲染工作器列表异常", e); + return Collections.emptyList(); + } + } + + /** + * 分页查询工作器列表(含配置信息)(不降级) + */ + public List listWorkersWithConfig(Integer page, Integer pageSize, + Integer isEnabled, String name) { + log.info("分页查询渲染工作器列表(含配置), page: {}, pageSize: {}, isEnabled: {}, name: {}", + page, pageSize, isEnabled, name); + try { + PageResponse response = + renderWorkerV2Client.listWorkersWithConfig(page, pageSize, isEnabled, name); + RenderWorkerV2WithConfigListResponse listResponse = + handlePageResponse(response, "查询渲染工作器列表(含配置)失败"); + return listResponse != null && listResponse.getList() != null ? + listResponse.getList() : Collections.emptyList(); + } catch (Exception e) { + log.error("查询渲染工作器列表(含配置)异常", e); + return Collections.emptyList(); + } + } + + /** + * 根据key获取工作器核心信息(带降级) + */ + public RenderWorkerV2DTO getWorkerByKey(String key) { + log.info("根据key获取渲染工作器信息, key: {}", key); + return fallbackService.executeWithFallback( + SERVICE_NAME, + "worker:key:" + key, + () -> { + CommonResponse response = renderWorkerV2Client.getWorkerByKey(key); + return handleResponse(response, "根据key获取渲染工作器信息失败"); + }, + RenderWorkerV2DTO.class + ); + } + + /** + * 根据key获取工作器详细信息(含配置)(带降级) + */ + public RenderWorkerV2WithConfigDTO getWorkerWithConfigByKey(String key) { + log.info("根据key获取渲染工作器详细信息, key: {}", key); + return fallbackService.executeWithFallback( + SERVICE_NAME, + "worker:key:config:" + key, + () -> { + CommonResponse response = renderWorkerV2Client.getWorkerWithConfigByKey(key); + return handleResponse(response, "根据key获取渲染工作器详细信息失败"); + }, + RenderWorkerV2WithConfigDTO.class + ); + } + + /** + * 处理通用响应 + */ + private T handleResponse(CommonResponse response, String errorMessage) { + if (response == null || !response.getSuccess()) { + String msg = response != null && response.getMessage() != null ? + response.getMessage() : errorMessage; + Integer code = response != null ? response.getCode() : 5000; + throw new IntegrationException(code, msg, SERVICE_NAME); + } + return response.getData(); + } + + /** + * 处理空响应 + */ + private void handleVoidResponse(CommonResponse response, String errorMessage) { + if (response == null || !response.getSuccess()) { + String msg = response != null && response.getMessage() != null ? + response.getMessage() : errorMessage; + Integer code = response != null ? response.getCode() : 5000; + throw new IntegrationException(code, msg, SERVICE_NAME); + } + } + + /** + * 处理分页响应 + */ + private T handlePageResponse(PageResponse response, String errorMessage) { + if (response == null || !response.getSuccess()) { + String msg = response != null && response.getMessage() != null ? + response.getMessage() : errorMessage; + Integer code = response != null ? response.getCode() : 5000; + throw new IntegrationException(code, msg, SERVICE_NAME); + } + return response.getData(); + } +} \ No newline at end of file From aa4a6c29c66ff521f501bb8d1179ecbd358406ce Mon Sep 17 00:00:00 2001 From: Jerry Yan <792602257@qq.com> Date: Fri, 5 Sep 2025 12:17:15 +0800 Subject: [PATCH 02/16] =?UTF-8?q?refactor(device):=20=E9=87=8D=E6=9E=84?= =?UTF-8?q?=E8=AE=BE=E5=A4=87=E5=88=97=E8=A1=A8=E6=8E=A5=E5=8F=A3=E8=BF=94?= =?UTF-8?q?=E5=9B=9E=E7=B1=BB=E5=9E=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 将 DeviceV2ListResponse 和 DeviceV2WithConfigListResponse 替换为通用的 PageResponse 类 - 更新相关控制器、服务和客户端接口以使用新的返回类型 - 删除冗余的 DeviceV2ListResponse 和 DeviceV2WithConfigListResponse 类 - 调整 FilterDevicesByConfigsResponse 中的 total 字段类型 --- .../controller/pc/DeviceV2Controller.java | 21 ++++++++++--------- .../controller/pc/ScenicV2Controller.java | 15 +++++++------ .../device/client/DeviceV2Client.java | 5 +++-- .../dto/device/DeviceV2ListResponse.java | 13 ------------ .../DeviceV2WithConfigListResponse.java | 13 ------------ .../FilterDevicesByConfigsResponse.java | 2 +- .../example/DeviceIntegrationExample.java | 7 ++++--- .../service/DeviceIntegrationService.java | 13 ++++++------ .../scenic/client/ScenicV2Client.java | 7 +++---- .../dto/scenic/ScenicV2ListResponse.java | 21 ------------------- .../ScenicV2WithConfigListResponse.java | 21 ------------------- .../service/ScenicIntegrationService.java | 11 +++++----- .../basic/repository/ScenicRepository.java | 4 ++-- .../mobile/impl/AppScenicServiceImpl.java | 9 ++++---- .../ycwl/basic/task/VideoPieceCleaner.java | 7 +++---- 15 files changed, 51 insertions(+), 118 deletions(-) delete mode 100644 src/main/java/com/ycwl/basic/integration/device/dto/device/DeviceV2ListResponse.java delete mode 100644 src/main/java/com/ycwl/basic/integration/device/dto/device/DeviceV2WithConfigListResponse.java delete mode 100644 src/main/java/com/ycwl/basic/integration/scenic/dto/scenic/ScenicV2ListResponse.java delete mode 100644 src/main/java/com/ycwl/basic/integration/scenic/dto/scenic/ScenicV2WithConfigListResponse.java diff --git a/src/main/java/com/ycwl/basic/controller/pc/DeviceV2Controller.java b/src/main/java/com/ycwl/basic/controller/pc/DeviceV2Controller.java index 7649fdb..d97ecf7 100644 --- a/src/main/java/com/ycwl/basic/controller/pc/DeviceV2Controller.java +++ b/src/main/java/com/ycwl/basic/controller/pc/DeviceV2Controller.java @@ -1,6 +1,7 @@ package com.ycwl.basic.controller.pc; import com.ycwl.basic.integration.device.dto.config.*; +import com.ycwl.basic.integration.common.response.PageResponse; import com.ycwl.basic.integration.device.dto.device.*; import com.ycwl.basic.integration.device.service.DeviceConfigIntegrationService; import com.ycwl.basic.integration.device.service.DeviceIntegrationService; @@ -35,7 +36,7 @@ public class DeviceV2Controller { * 设备V2核心信息分页列表 */ @GetMapping("/") - public ApiResponse listDevices(@RequestParam(defaultValue = "1") Integer page, + public ApiResponse> listDevices(@RequestParam(defaultValue = "1") Integer page, @RequestParam(defaultValue = "10") Integer pageSize, @RequestParam(required = false) String name, @RequestParam(required = false) String no, @@ -51,7 +52,7 @@ public class DeviceV2Controller { } try { - DeviceV2ListResponse response = deviceIntegrationService.listDevices(page, pageSize, name, no, type, isActive, scenicId); + PageResponse response = deviceIntegrationService.listDevices(page, pageSize, name, no, type, isActive, scenicId); return ApiResponse.success(response); } catch (Exception e) { log.error("分页查询设备核心信息列表失败", e); @@ -63,7 +64,7 @@ public class DeviceV2Controller { * 设备V2带配置信息分页列表 */ @GetMapping("/with-config") - public ApiResponse listDevicesWithConfig(@RequestParam(defaultValue = "1") Integer page, + public ApiResponse> listDevicesWithConfig(@RequestParam(defaultValue = "1") Integer page, @RequestParam(defaultValue = "10") Integer pageSize, @RequestParam(required = false) String name, @RequestParam(required = false) String no, @@ -79,7 +80,7 @@ public class DeviceV2Controller { } try { - DeviceV2WithConfigListResponse response = deviceIntegrationService.listDevicesWithConfig(page, pageSize, name, no, type, isActive, scenicId); + PageResponse response = deviceIntegrationService.listDevicesWithConfig(page, pageSize, name, no, type, isActive, scenicId); return ApiResponse.success(response); } catch (Exception e) { log.error("分页查询设备带配置信息列表失败", e); @@ -431,12 +432,12 @@ public class DeviceV2Controller { * 获取景区IPC设备列表 */ @GetMapping("/scenic/{scenicId}/ipc") - public ApiResponse getScenicIpcDevices(@PathVariable Long scenicId, + public ApiResponse> getScenicIpcDevices(@PathVariable Long scenicId, @RequestParam(defaultValue = "1") Integer page, @RequestParam(defaultValue = "10") Integer pageSize) { log.info("获取景区IPC设备列表, scenicId: {}, page: {}, pageSize: {}", scenicId, page, pageSize); try { - DeviceV2ListResponse response = deviceIntegrationService.getScenicIpcDevices(scenicId, page, pageSize); + PageResponse response = deviceIntegrationService.getScenicIpcDevices(scenicId, page, pageSize); return ApiResponse.success(response); } catch (Exception e) { log.error("获取景区IPC设备列表失败, scenicId: {}", scenicId, e); @@ -448,12 +449,12 @@ public class DeviceV2Controller { * 获取景区激活设备列表 */ @GetMapping("/scenic/{scenicId}/active") - public ApiResponse getScenicActiveDevices(@PathVariable Long scenicId, + public ApiResponse> getScenicActiveDevices(@PathVariable Long scenicId, @RequestParam(defaultValue = "1") Integer page, @RequestParam(defaultValue = "10") Integer pageSize) { log.info("获取景区激活设备列表, scenicId: {}, page: {}, pageSize: {}", scenicId, page, pageSize); try { - DeviceV2ListResponse response = deviceIntegrationService.getScenicActiveDevices(scenicId, page, pageSize); + PageResponse response = deviceIntegrationService.getScenicActiveDevices(scenicId, page, pageSize); return ApiResponse.success(response); } catch (Exception e) { log.error("获取景区激活设备列表失败, scenicId: {}", scenicId, e); @@ -465,12 +466,12 @@ public class DeviceV2Controller { * 获取景区所有设备列表 */ @GetMapping("/scenic/{scenicId}/all") - public ApiResponse getScenicAllDevices(@PathVariable Long scenicId, + public ApiResponse> getScenicAllDevices(@PathVariable Long scenicId, @RequestParam(defaultValue = "1") Integer page, @RequestParam(defaultValue = "10") Integer pageSize) { log.info("获取景区所有设备列表, scenicId: {}, page: {}, pageSize: {}", scenicId, page, pageSize); try { - DeviceV2ListResponse response = deviceIntegrationService.listDevices(page, pageSize, null, null, null, null, scenicId); + PageResponse response = deviceIntegrationService.listDevices(page, pageSize, null, null, null, null, scenicId); return ApiResponse.success(response); } catch (Exception e) { log.error("获取景区所有设备列表失败, scenicId: {}", scenicId, e); diff --git a/src/main/java/com/ycwl/basic/controller/pc/ScenicV2Controller.java b/src/main/java/com/ycwl/basic/controller/pc/ScenicV2Controller.java index 52b7f8b..15a3e42 100644 --- a/src/main/java/com/ycwl/basic/controller/pc/ScenicV2Controller.java +++ b/src/main/java/com/ycwl/basic/controller/pc/ScenicV2Controller.java @@ -9,9 +9,8 @@ import com.ycwl.basic.integration.scenic.dto.filter.ScenicFilterPageResponse; import com.ycwl.basic.integration.scenic.dto.filter.ScenicFilterRequest; import com.ycwl.basic.integration.scenic.dto.scenic.CreateScenicRequest; import com.ycwl.basic.integration.scenic.dto.scenic.ScenicV2DTO; -import com.ycwl.basic.integration.scenic.dto.scenic.ScenicV2ListResponse; +import com.ycwl.basic.integration.common.response.PageResponse; import com.ycwl.basic.integration.scenic.dto.scenic.ScenicV2WithConfigDTO; -import com.ycwl.basic.integration.scenic.dto.scenic.ScenicV2WithConfigListResponse; import com.ycwl.basic.integration.scenic.dto.scenic.UpdateScenicRequest; import com.ycwl.basic.integration.scenic.service.ScenicConfigIntegrationService; import com.ycwl.basic.integration.scenic.service.ScenicIntegrationService; @@ -52,7 +51,7 @@ public class ScenicV2Controller { * 景区V2核心信息分页列表 */ @GetMapping("/") - public ApiResponse listScenics(@RequestParam(defaultValue = "1") Integer page, + public ApiResponse> listScenics(@RequestParam(defaultValue = "1") Integer page, @RequestParam(defaultValue = "10") Integer pageSize, @RequestParam(required = false) Integer status, @RequestParam(required = false) String name) { @@ -64,7 +63,7 @@ public class ScenicV2Controller { } try { - ScenicV2ListResponse response = scenicIntegrationService.listScenics(page, pageSize, status, name); + PageResponse response = scenicIntegrationService.listScenics(page, pageSize, status, name); return ApiResponse.success(response); } catch (Exception e) { log.error("分页查询景区核心信息列表失败", e); @@ -76,7 +75,7 @@ public class ScenicV2Controller { * 景区V2带配置信息分页列表 */ @GetMapping("/with-config") - public ApiResponse listScenicsWithConfig(@RequestParam(defaultValue = "1") Integer page, + public ApiResponse> listScenicsWithConfig(@RequestParam(defaultValue = "1") Integer page, @RequestParam(defaultValue = "10") Integer pageSize, @RequestParam(required = false) Integer status, @RequestParam(required = false) String name) { @@ -88,7 +87,7 @@ public class ScenicV2Controller { } try { - ScenicV2WithConfigListResponse response = scenicIntegrationService.listScenicsWithConfig(page, pageSize, status, name); + PageResponse response = scenicIntegrationService.listScenicsWithConfig(page, pageSize, status, name); return ApiResponse.success(response); } catch (Exception e) { log.error("分页查询景区带配置信息列表失败", e); @@ -178,11 +177,11 @@ public class ScenicV2Controller { * 只支持根据状态筛选 */ @GetMapping("/list") - public ApiResponse listScenicsByStatus(@RequestParam(required = false) Integer status) { + public ApiResponse> listScenicsByStatus(@RequestParam(required = false) Integer status) { log.info("查询景区列表, status: {}", status); try { // 默认查询1000条数据,第1页 - ScenicV2ListResponse scenics = scenicIntegrationService.listScenics(1, 1000, status, null); + PageResponse scenics = scenicIntegrationService.listScenics(1, 1000, status, null); return ApiResponse.success(scenics); } catch (Exception e) { log.error("查询景区列表失败, status: {}", status, e); diff --git a/src/main/java/com/ycwl/basic/integration/device/client/DeviceV2Client.java b/src/main/java/com/ycwl/basic/integration/device/client/DeviceV2Client.java index 0e13675..694cc52 100644 --- a/src/main/java/com/ycwl/basic/integration/device/client/DeviceV2Client.java +++ b/src/main/java/com/ycwl/basic/integration/device/client/DeviceV2Client.java @@ -1,6 +1,7 @@ package com.ycwl.basic.integration.device.client; import com.ycwl.basic.integration.common.response.CommonResponse; +import com.ycwl.basic.integration.common.response.PageResponse; import com.ycwl.basic.integration.device.dto.device.*; import org.springframework.cloud.openfeign.FeignClient; import org.springframework.web.bind.annotation.*; @@ -55,7 +56,7 @@ public interface DeviceV2Client { * 分页获取设备列表(核心信息) */ @GetMapping("/") - CommonResponse listDevices( + CommonResponse> listDevices( @RequestParam(value = "page", defaultValue = "1") Integer page, @RequestParam(value = "pageSize", defaultValue = "10") Integer pageSize, @RequestParam(value = "name", required = false) String name, @@ -68,7 +69,7 @@ public interface DeviceV2Client { * 分页获取设备列表(含配置) */ @GetMapping("/with-config") - CommonResponse listDevicesWithConfig( + CommonResponse> listDevicesWithConfig( @RequestParam(value = "page", defaultValue = "1") Integer page, @RequestParam(value = "pageSize", defaultValue = "10") Integer pageSize, @RequestParam(value = "name", required = false) String name, diff --git a/src/main/java/com/ycwl/basic/integration/device/dto/device/DeviceV2ListResponse.java b/src/main/java/com/ycwl/basic/integration/device/dto/device/DeviceV2ListResponse.java deleted file mode 100644 index d32b247..0000000 --- a/src/main/java/com/ycwl/basic/integration/device/dto/device/DeviceV2ListResponse.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.ycwl.basic.integration.device.dto.device; - -import lombok.Data; - -import java.util.List; - -@Data -public class DeviceV2ListResponse { - private List list; - private Integer total; - private Integer page; - private Integer pageSize; -} \ No newline at end of file diff --git a/src/main/java/com/ycwl/basic/integration/device/dto/device/DeviceV2WithConfigListResponse.java b/src/main/java/com/ycwl/basic/integration/device/dto/device/DeviceV2WithConfigListResponse.java deleted file mode 100644 index d5c7c44..0000000 --- a/src/main/java/com/ycwl/basic/integration/device/dto/device/DeviceV2WithConfigListResponse.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.ycwl.basic.integration.device.dto.device; - -import lombok.Data; - -import java.util.List; - -@Data -public class DeviceV2WithConfigListResponse { - private List list; - private Integer total; - private Integer page; - private Integer pageSize; -} \ No newline at end of file diff --git a/src/main/java/com/ycwl/basic/integration/device/dto/device/FilterDevicesByConfigsResponse.java b/src/main/java/com/ycwl/basic/integration/device/dto/device/FilterDevicesByConfigsResponse.java index cd957a4..f60fdeb 100644 --- a/src/main/java/com/ycwl/basic/integration/device/dto/device/FilterDevicesByConfigsResponse.java +++ b/src/main/java/com/ycwl/basic/integration/device/dto/device/FilterDevicesByConfigsResponse.java @@ -17,7 +17,7 @@ public class FilterDevicesByConfigsResponse { /** * 总数 */ - private String total; + private Integer total; /** * 页码 diff --git a/src/main/java/com/ycwl/basic/integration/device/example/DeviceIntegrationExample.java b/src/main/java/com/ycwl/basic/integration/device/example/DeviceIntegrationExample.java index 388c93d..638a7ee 100644 --- a/src/main/java/com/ycwl/basic/integration/device/example/DeviceIntegrationExample.java +++ b/src/main/java/com/ycwl/basic/integration/device/example/DeviceIntegrationExample.java @@ -1,5 +1,6 @@ package com.ycwl.basic.integration.device.example; +import com.ycwl.basic.integration.common.response.PageResponse; import com.ycwl.basic.integration.device.dto.device.*; import com.ycwl.basic.integration.device.dto.config.*; import com.ycwl.basic.integration.device.service.DeviceConfigIntegrationService; @@ -46,7 +47,7 @@ public class DeviceIntegrationExample { log.info("获取设备配置: {}", deviceWithConfig.getName()); // 分页查询景区设备列表 - DeviceV2ListResponse deviceList = deviceService.getScenicIpcDevices(1001L, 1, 10); + PageResponse deviceList = deviceService.getScenicIpcDevices(1001L, 1, 10); log.info("景区设备列表: 总数={}", deviceList.getTotal()); // 启用设备 @@ -80,7 +81,7 @@ public class DeviceIntegrationExample { log.info("更新摄像头1排序为1(置顶)"); // 获取排序后的设备列表 - DeviceV2ListResponse sortedList = deviceService.listDevices(1, 10, null, null, null, 1, scenicId); + PageResponse sortedList = deviceService.listDevices(1, 10, null, null, null, 1, scenicId); log.info("排序后的设备列表:"); for (DeviceV2DTO device : sortedList.getList()) { log.info(" - {}: 排序={}, 类型={}", device.getName(), device.getSort(), device.getType()); @@ -147,7 +148,7 @@ public class DeviceIntegrationExample { log.info("将普通摄像头置顶(排序值: 1)"); // 查看最终排序结果 - DeviceV2ListResponse finalList = deviceService.listDevices(1, 10, null, null, null, 1, scenicId); + PageResponse finalList = deviceService.listDevices(1, 10, null, null, null, 1, scenicId); log.info("最终排序结果:"); for (DeviceV2DTO device : finalList.getList()) { log.info(" - {}: 排序={}", device.getName(), device.getSort()); diff --git a/src/main/java/com/ycwl/basic/integration/device/service/DeviceIntegrationService.java b/src/main/java/com/ycwl/basic/integration/device/service/DeviceIntegrationService.java index 8e49e71..740ef87 100644 --- a/src/main/java/com/ycwl/basic/integration/device/service/DeviceIntegrationService.java +++ b/src/main/java/com/ycwl/basic/integration/device/service/DeviceIntegrationService.java @@ -4,6 +4,7 @@ import com.ycwl.basic.integration.common.exception.IntegrationException; import com.ycwl.basic.integration.common.response.CommonResponse; import com.ycwl.basic.integration.common.service.IntegrationFallbackService; import com.ycwl.basic.integration.device.client.DeviceV2Client; +import com.ycwl.basic.integration.common.response.PageResponse; import com.ycwl.basic.integration.device.dto.device.*; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -91,20 +92,20 @@ public class DeviceIntegrationService { handleResponse(response, "删除设备失败"); } - public DeviceV2ListResponse listDevices(Integer page, Integer pageSize, String name, String no, + public PageResponse listDevices(Integer page, Integer pageSize, String name, String no, String type, Integer isActive, Long scenicId) { log.info("分页查询设备列表, page: {}, pageSize: {}, name: {}, no: {}, type: {}, isActive: {}, scenicId: {}", page, pageSize, name, no, type, isActive, scenicId); - CommonResponse response = deviceV2Client.listDevices( + CommonResponse> response = deviceV2Client.listDevices( page, pageSize, name, no, type, isActive, scenicId); return handleResponse(response, "分页查询设备列表失败"); } - public DeviceV2WithConfigListResponse listDevicesWithConfig(Integer page, Integer pageSize, String name, String no, + public PageResponse listDevicesWithConfig(Integer page, Integer pageSize, String name, String no, String type, Integer isActive, Long scenicId) { log.info("分页查询设备带配置列表, page: {}, pageSize: {}, name: {}, no: {}, type: {}, isActive: {}, scenicId: {}", page, pageSize, name, no, type, isActive, scenicId); - CommonResponse response = deviceV2Client.listDevicesWithConfig( + CommonResponse> response = deviceV2Client.listDevicesWithConfig( page, pageSize, name, no, type, isActive, scenicId); return handleResponse(response, "分页查询设备带配置列表失败"); } @@ -196,14 +197,14 @@ public class DeviceIntegrationService { /** * 获取景区的IPC设备列表 */ - public DeviceV2ListResponse getScenicIpcDevices(Long scenicId, Integer page, Integer pageSize) { + public PageResponse getScenicIpcDevices(Long scenicId, Integer page, Integer pageSize) { return listDevices(page, pageSize, null, null, "IPC", 1, scenicId); } /** * 获取景区的所有激活设备 */ - public DeviceV2ListResponse getScenicActiveDevices(Long scenicId, Integer page, Integer pageSize) { + public PageResponse getScenicActiveDevices(Long scenicId, Integer page, Integer pageSize) { return listDevices(page, pageSize, null, null, null, 1, scenicId); } diff --git a/src/main/java/com/ycwl/basic/integration/scenic/client/ScenicV2Client.java b/src/main/java/com/ycwl/basic/integration/scenic/client/ScenicV2Client.java index 0405fcf..f2c2d35 100644 --- a/src/main/java/com/ycwl/basic/integration/scenic/client/ScenicV2Client.java +++ b/src/main/java/com/ycwl/basic/integration/scenic/client/ScenicV2Client.java @@ -6,8 +6,7 @@ import com.ycwl.basic.integration.scenic.dto.filter.ScenicFilterRequest; import com.ycwl.basic.integration.scenic.dto.scenic.CreateScenicRequest; import com.ycwl.basic.integration.scenic.dto.scenic.ScenicV2DTO; import com.ycwl.basic.integration.scenic.dto.scenic.ScenicV2WithConfigDTO; -import com.ycwl.basic.integration.scenic.dto.scenic.ScenicV2ListResponse; -import com.ycwl.basic.integration.scenic.dto.scenic.ScenicV2WithConfigListResponse; +import com.ycwl.basic.integration.common.response.PageResponse; import com.ycwl.basic.integration.scenic.dto.scenic.UpdateScenicRequest; import org.springframework.cloud.openfeign.FeignClient; import org.springframework.web.bind.annotation.*; @@ -38,13 +37,13 @@ public interface ScenicV2Client { CommonResponse filterScenics(@RequestBody ScenicFilterRequest request); @GetMapping("/") - CommonResponse listScenics(@RequestParam(defaultValue = "1") Integer page, + CommonResponse> listScenics(@RequestParam(defaultValue = "1") Integer page, @RequestParam(defaultValue = "10") Integer pageSize, @RequestParam(required = false) Integer status, @RequestParam(required = false) String name); @GetMapping("/with-config") - CommonResponse listScenicsWithConfig(@RequestParam(defaultValue = "1") Integer page, + CommonResponse> listScenicsWithConfig(@RequestParam(defaultValue = "1") Integer page, @RequestParam(defaultValue = "10") Integer pageSize, @RequestParam(required = false) Integer status, @RequestParam(required = false) String name); diff --git a/src/main/java/com/ycwl/basic/integration/scenic/dto/scenic/ScenicV2ListResponse.java b/src/main/java/com/ycwl/basic/integration/scenic/dto/scenic/ScenicV2ListResponse.java deleted file mode 100644 index c660579..0000000 --- a/src/main/java/com/ycwl/basic/integration/scenic/dto/scenic/ScenicV2ListResponse.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.ycwl.basic.integration.scenic.dto.scenic; - -import com.fasterxml.jackson.annotation.JsonProperty; -import lombok.Data; - -import java.util.List; - -@Data -public class ScenicV2ListResponse { - @JsonProperty("list") - private List list; - - @JsonProperty("total") - private Integer total; - - @JsonProperty("page") - private Integer page; - - @JsonProperty("pageSize") - private Integer pageSize; -} \ No newline at end of file diff --git a/src/main/java/com/ycwl/basic/integration/scenic/dto/scenic/ScenicV2WithConfigListResponse.java b/src/main/java/com/ycwl/basic/integration/scenic/dto/scenic/ScenicV2WithConfigListResponse.java deleted file mode 100644 index 4540036..0000000 --- a/src/main/java/com/ycwl/basic/integration/scenic/dto/scenic/ScenicV2WithConfigListResponse.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.ycwl.basic.integration.scenic.dto.scenic; - -import com.fasterxml.jackson.annotation.JsonProperty; -import lombok.Data; - -import java.util.List; - -@Data -public class ScenicV2WithConfigListResponse { - @JsonProperty("list") - private List list; - - @JsonProperty("total") - private Integer total; - - @JsonProperty("page") - private Integer page; - - @JsonProperty("pageSize") - private Integer pageSize; -} \ No newline at end of file diff --git a/src/main/java/com/ycwl/basic/integration/scenic/service/ScenicIntegrationService.java b/src/main/java/com/ycwl/basic/integration/scenic/service/ScenicIntegrationService.java index fba59c2..c9b258f 100644 --- a/src/main/java/com/ycwl/basic/integration/scenic/service/ScenicIntegrationService.java +++ b/src/main/java/com/ycwl/basic/integration/scenic/service/ScenicIntegrationService.java @@ -10,8 +10,7 @@ import com.ycwl.basic.integration.scenic.dto.filter.ScenicFilterRequest; import com.ycwl.basic.integration.scenic.dto.scenic.CreateScenicRequest; import com.ycwl.basic.integration.scenic.dto.scenic.ScenicV2DTO; import com.ycwl.basic.integration.scenic.dto.scenic.ScenicV2WithConfigDTO; -import com.ycwl.basic.integration.scenic.dto.scenic.ScenicV2ListResponse; -import com.ycwl.basic.integration.scenic.dto.scenic.ScenicV2WithConfigListResponse; +import com.ycwl.basic.integration.common.response.PageResponse; import com.ycwl.basic.integration.scenic.dto.scenic.UpdateScenicRequest; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -93,15 +92,15 @@ public class ScenicIntegrationService { return handleResponse(response, "筛选景区失败"); } - public ScenicV2ListResponse listScenics(Integer page, Integer pageSize, Integer status, String name) { + public PageResponse listScenics(Integer page, Integer pageSize, Integer status, String name) { log.info("分页查询景区列表, page: {}, pageSize: {}, status: {}, name: {}", page, pageSize, status, name); - CommonResponse response = scenicV2Client.listScenics(page, pageSize, status, name); + CommonResponse> response = scenicV2Client.listScenics(page, pageSize, status, name); return handleResponse(response, "分页查询景区列表失败"); } - public ScenicV2WithConfigListResponse listScenicsWithConfig(Integer page, Integer pageSize, Integer status, String name) { + public PageResponse listScenicsWithConfig(Integer page, Integer pageSize, Integer status, String name) { log.info("分页查询景区带配置列表, page: {}, pageSize: {}, status: {}, name: {}", page, pageSize, status, name); - CommonResponse response = scenicV2Client.listScenicsWithConfig(page, pageSize, status, name); + CommonResponse> response = scenicV2Client.listScenicsWithConfig(page, pageSize, status, name); return handleResponse(response, "分页查询景区带配置列表失败"); } diff --git a/src/main/java/com/ycwl/basic/repository/ScenicRepository.java b/src/main/java/com/ycwl/basic/repository/ScenicRepository.java index 4125a96..cdfa9bf 100644 --- a/src/main/java/com/ycwl/basic/repository/ScenicRepository.java +++ b/src/main/java/com/ycwl/basic/repository/ScenicRepository.java @@ -3,7 +3,7 @@ package com.ycwl.basic.repository; import com.ycwl.basic.facebody.enums.FaceBodyAdapterType; import com.ycwl.basic.integration.common.util.ConfigValueUtil; import com.ycwl.basic.integration.scenic.dto.scenic.ScenicV2DTO; -import com.ycwl.basic.integration.scenic.dto.scenic.ScenicV2ListResponse; +import com.ycwl.basic.integration.common.response.PageResponse; import com.ycwl.basic.integration.scenic.dto.scenic.ScenicV2WithConfigDTO; import com.ycwl.basic.integration.scenic.service.ScenicIntegrationService; import com.ycwl.basic.integration.scenic.service.ScenicConfigIntegrationService; @@ -209,7 +209,7 @@ public class ScenicRepository { String name = scenicReqQuery.getName(); // 调用 zt-scenic 服务的 list 方法 - ScenicV2ListResponse response = scenicIntegrationService.listScenics(page, pageSize, status, name); + PageResponse response = scenicIntegrationService.listScenics(page, pageSize, status, name); // 将 ScenicV2DTO 列表转换为 ScenicEntity 列表 if (response != null && response.getList() != null) { diff --git a/src/main/java/com/ycwl/basic/service/mobile/impl/AppScenicServiceImpl.java b/src/main/java/com/ycwl/basic/service/mobile/impl/AppScenicServiceImpl.java index c608723..450ff6b 100644 --- a/src/main/java/com/ycwl/basic/service/mobile/impl/AppScenicServiceImpl.java +++ b/src/main/java/com/ycwl/basic/service/mobile/impl/AppScenicServiceImpl.java @@ -5,7 +5,8 @@ import com.github.pagehelper.PageInfo; import com.ycwl.basic.integration.common.manager.DeviceConfigManager; import com.ycwl.basic.integration.scenic.dto.scenic.ScenicV2DTO; import com.ycwl.basic.integration.device.service.DeviceIntegrationService; -import com.ycwl.basic.integration.device.dto.device.DeviceV2ListResponse; +import com.ycwl.basic.integration.device.dto.device.DeviceV2DTO; +import com.ycwl.basic.integration.common.response.PageResponse; import com.ycwl.basic.mapper.ExtraDeviceMapper; import com.ycwl.basic.mapper.ScenicAccountMapper; import com.ycwl.basic.model.jwt.JwtInfo; @@ -86,7 +87,7 @@ public class AppScenicServiceImpl implements AppScenicService { public ApiResponse deviceCountByScenicId(Long scenicId) { JwtInfo worker = JwtTokenUtil.getWorker(); // 通过zt-device服务获取设备统计 - DeviceV2ListResponse deviceListResponse = deviceIntegrationService.getScenicActiveDevices(scenicId, 1, 1000); + PageResponse deviceListResponse = deviceIntegrationService.getScenicActiveDevices(scenicId, 1, 1000); ScenicDeviceCountVO scenicDeviceCountVO = new ScenicDeviceCountVO(); if (deviceListResponse != null && deviceListResponse.getList() != null) { scenicDeviceCountVO.setTotalDeviceCount(deviceListResponse.getList().size()); @@ -120,7 +121,7 @@ public class AppScenicServiceImpl implements AppScenicService { } // 通过zt-device服务获取设备统计 - DeviceV2ListResponse deviceListResponse = deviceIntegrationService.getScenicActiveDevices(id, 1, 1000); + PageResponse deviceListResponse = deviceIntegrationService.getScenicActiveDevices(id, 1, 1000); ScenicDeviceCountVO scenicDeviceCountVO = new ScenicDeviceCountVO(); if (deviceListResponse != null && deviceListResponse.getList() != null) { scenicDeviceCountVO.setTotalDeviceCount(deviceListResponse.getList().size()); @@ -276,7 +277,7 @@ public class AppScenicServiceImpl implements AppScenicService { @Override public ApiResponse> getDevices(Long scenicId) { - DeviceV2ListResponse deviceV2ListResponse = deviceIntegrationService.listDevices(1, 1000, null, null, null, 1, scenicId); + PageResponse deviceV2ListResponse = deviceIntegrationService.listDevices(1, 1000, null, null, null, 1, scenicId); List deviceRespVOList = deviceV2ListResponse.getList().stream().map(device -> { DeviceRespVO deviceRespVO = new DeviceRespVO(); deviceRespVO.setId(device.getId()); diff --git a/src/main/java/com/ycwl/basic/task/VideoPieceCleaner.java b/src/main/java/com/ycwl/basic/task/VideoPieceCleaner.java index 243d5be..4b73243 100644 --- a/src/main/java/com/ycwl/basic/task/VideoPieceCleaner.java +++ b/src/main/java/com/ycwl/basic/task/VideoPieceCleaner.java @@ -5,7 +5,7 @@ import com.ycwl.basic.device.DeviceFactory; import com.ycwl.basic.device.operator.IDeviceStorageOperator; import com.ycwl.basic.integration.common.manager.DeviceConfigManager; import com.ycwl.basic.integration.device.service.DeviceIntegrationService; -import com.ycwl.basic.integration.device.dto.device.DeviceV2ListResponse; +import com.ycwl.basic.integration.common.response.PageResponse; import com.ycwl.basic.integration.device.dto.device.DeviceV2DTO; import java.util.stream.Collectors; import com.ycwl.basic.model.pc.device.entity.DeviceConfigEntity; @@ -37,9 +37,8 @@ public class VideoPieceCleaner { public void clean() { log.info("开始删除视频文件"); // 通过zt-device服务获取所有激活设备 - DeviceV2ListResponse deviceListResponse = deviceIntegrationService.listDevices(1, 10000, null, null, null, 1, null); - List deviceList; - if (deviceListResponse == null) { + PageResponse deviceListResponse = deviceIntegrationService.listDevices(1, 10000, null, null, null, 1, null); + if (deviceListResponse == null || deviceListResponse.getList() == null) { return; } for (DeviceV2DTO device : deviceListResponse.getList()) { From 933a1209e7bfe4dea817a0a06eb52a2c8df466ee Mon Sep 17 00:00:00 2001 From: Jerry Yan <792602257@qq.com> Date: Fri, 5 Sep 2025 12:17:44 +0800 Subject: [PATCH 03/16] =?UTF-8?q?refactor(render):=20=E9=87=8D=E6=9E=84?= =?UTF-8?q?=E6=B8=B2=E6=9F=93=E5=B7=A5=E4=BD=9C=E5=99=A8=E5=88=97=E8=A1=A8?= =?UTF-8?q?=E6=8E=A5=E5=8F=A3=E5=92=8C=20DTO?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 更新 RenderWorkerV2Client 中的 listWorkers 和 listWorkersWithConfig 方法返回类型 - 删除 RenderWorkerV2ListResponse 和 RenderWorkerV2WithConfigListResponse 类 - 更新 CreateRenderWorkerRequest 中的导入路径- 重构 RenderWorkerIntegrationService 中的 listWorkers 和 listWorkersWithConfig 方法 --- .../render/client/RenderWorkerV2Client.java | 4 +- .../dto/worker/CreateRenderWorkerRequest.java | 2 +- .../worker/RenderWorkerV2ListResponse.java | 33 -------------- .../RenderWorkerV2WithConfigListResponse.java | 33 -------------- .../RenderWorkerIntegrationService.java | 43 ++++--------------- 5 files changed, 11 insertions(+), 104 deletions(-) delete mode 100644 src/main/java/com/ycwl/basic/integration/render/dto/worker/RenderWorkerV2ListResponse.java delete mode 100644 src/main/java/com/ycwl/basic/integration/render/dto/worker/RenderWorkerV2WithConfigListResponse.java diff --git a/src/main/java/com/ycwl/basic/integration/render/client/RenderWorkerV2Client.java b/src/main/java/com/ycwl/basic/integration/render/client/RenderWorkerV2Client.java index b73df45..c6c923c 100644 --- a/src/main/java/com/ycwl/basic/integration/render/client/RenderWorkerV2Client.java +++ b/src/main/java/com/ycwl/basic/integration/render/client/RenderWorkerV2Client.java @@ -47,7 +47,7 @@ public interface RenderWorkerV2Client { * 分页查询工作器列表(核心信息) */ @GetMapping - PageResponse listWorkers(@RequestParam(defaultValue = "1") Integer page, + CommonResponse> listWorkers(@RequestParam(defaultValue = "1") Integer page, @RequestParam(defaultValue = "10") Integer pageSize, @RequestParam(required = false) Integer isEnabled, @RequestParam(required = false) String name); @@ -56,7 +56,7 @@ public interface RenderWorkerV2Client { * 分页查询工作器列表(含配置信息) */ @GetMapping("/with-config") - PageResponse listWorkersWithConfig( + CommonResponse> listWorkersWithConfig( @RequestParam(defaultValue = "1") Integer page, @RequestParam(defaultValue = "10") Integer pageSize, @RequestParam(required = false) Integer isEnabled, diff --git a/src/main/java/com/ycwl/basic/integration/render/dto/worker/CreateRenderWorkerRequest.java b/src/main/java/com/ycwl/basic/integration/render/dto/worker/CreateRenderWorkerRequest.java index d7d3493..7947d8c 100644 --- a/src/main/java/com/ycwl/basic/integration/render/dto/worker/CreateRenderWorkerRequest.java +++ b/src/main/java/com/ycwl/basic/integration/render/dto/worker/CreateRenderWorkerRequest.java @@ -3,7 +3,7 @@ package com.ycwl.basic.integration.render.dto.worker; import com.fasterxml.jackson.annotation.JsonProperty; import lombok.Data; -import javax.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotBlank; /** * 创建渲染工作器请求DTO diff --git a/src/main/java/com/ycwl/basic/integration/render/dto/worker/RenderWorkerV2ListResponse.java b/src/main/java/com/ycwl/basic/integration/render/dto/worker/RenderWorkerV2ListResponse.java deleted file mode 100644 index a70d365..0000000 --- a/src/main/java/com/ycwl/basic/integration/render/dto/worker/RenderWorkerV2ListResponse.java +++ /dev/null @@ -1,33 +0,0 @@ -package com.ycwl.basic.integration.render.dto.worker; - -import lombok.Data; - -import java.util.List; - -/** - * 渲染工作器列表响应DTO - */ -@Data -public class RenderWorkerV2ListResponse { - - /** - * 工作器列表 - */ - private List list; - - /** - * 总数 - */ - private String total; - - /** - * 当前页 - */ - private Integer page; - - /** - * 页大小 - */ - @SuppressWarnings("unused") - private Integer pageSize; -} \ No newline at end of file diff --git a/src/main/java/com/ycwl/basic/integration/render/dto/worker/RenderWorkerV2WithConfigListResponse.java b/src/main/java/com/ycwl/basic/integration/render/dto/worker/RenderWorkerV2WithConfigListResponse.java deleted file mode 100644 index e326742..0000000 --- a/src/main/java/com/ycwl/basic/integration/render/dto/worker/RenderWorkerV2WithConfigListResponse.java +++ /dev/null @@ -1,33 +0,0 @@ -package com.ycwl.basic.integration.render.dto.worker; - -import lombok.Data; - -import java.util.List; - -/** - * 带配置的渲染工作器列表响应DTO - */ -@Data -public class RenderWorkerV2WithConfigListResponse { - - /** - * 工作器列表 - */ - private List list; - - /** - * 总数 - */ - private String total; - - /** - * 当前页 - */ - private Integer page; - - /** - * 页大小 - */ - @SuppressWarnings("unused") - private Integer pageSize; -} \ No newline at end of file diff --git a/src/main/java/com/ycwl/basic/integration/render/service/RenderWorkerIntegrationService.java b/src/main/java/com/ycwl/basic/integration/render/service/RenderWorkerIntegrationService.java index e33920a..5bd1700 100644 --- a/src/main/java/com/ycwl/basic/integration/render/service/RenderWorkerIntegrationService.java +++ b/src/main/java/com/ycwl/basic/integration/render/service/RenderWorkerIntegrationService.java @@ -88,39 +88,24 @@ public class RenderWorkerIntegrationService { /** * 分页查询工作器列表(核心信息)(不降级) */ - public List listWorkers(Integer page, Integer pageSize, Integer isEnabled, String name) { + public PageResponse listWorkers(Integer page, Integer pageSize, Integer isEnabled, String name) { log.info("分页查询渲染工作器列表, page: {}, pageSize: {}, isEnabled: {}, name: {}", page, pageSize, isEnabled, name); - try { - PageResponse response = - renderWorkerV2Client.listWorkers(page, pageSize, isEnabled, name); - RenderWorkerV2ListResponse listResponse = handlePageResponse(response, "查询渲染工作器列表失败"); - return listResponse != null && listResponse.getList() != null ? - listResponse.getList() : Collections.emptyList(); - } catch (Exception e) { - log.error("查询渲染工作器列表异常", e); - return Collections.emptyList(); - } + CommonResponse> response = + renderWorkerV2Client.listWorkers(page, pageSize, isEnabled, name); + return handleResponse(response, "查询渲染工作器列表失败"); } /** * 分页查询工作器列表(含配置信息)(不降级) */ - public List listWorkersWithConfig(Integer page, Integer pageSize, + public PageResponse listWorkersWithConfig(Integer page, Integer pageSize, Integer isEnabled, String name) { log.info("分页查询渲染工作器列表(含配置), page: {}, pageSize: {}, isEnabled: {}, name: {}", page, pageSize, isEnabled, name); - try { - PageResponse response = - renderWorkerV2Client.listWorkersWithConfig(page, pageSize, isEnabled, name); - RenderWorkerV2WithConfigListResponse listResponse = - handlePageResponse(response, "查询渲染工作器列表(含配置)失败"); - return listResponse != null && listResponse.getList() != null ? - listResponse.getList() : Collections.emptyList(); - } catch (Exception e) { - log.error("查询渲染工作器列表(含配置)异常", e); - return Collections.emptyList(); - } + CommonResponse> response = + renderWorkerV2Client.listWorkersWithConfig(page, pageSize, isEnabled, name); + return handleResponse(response, "查询渲染工作器列表(含配置)失败"); } /** @@ -180,16 +165,4 @@ public class RenderWorkerIntegrationService { } } - /** - * 处理分页响应 - */ - private T handlePageResponse(PageResponse response, String errorMessage) { - if (response == null || !response.getSuccess()) { - String msg = response != null && response.getMessage() != null ? - response.getMessage() : errorMessage; - Integer code = response != null ? response.getCode() : 5000; - throw new IntegrationException(code, msg, SERVICE_NAME); - } - return response.getData(); - } } \ No newline at end of file From 933818d458be7e023814acab466f2a8021fb9cb2 Mon Sep 17 00:00:00 2001 From: Jerry Yan <792602257@qq.com> Date: Fri, 5 Sep 2025 14:49:06 +0800 Subject: [PATCH 04/16] =?UTF-8?q?feat(device):=20=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?=E9=BB=98=E8=AE=A4=E9=85=8D=E7=BD=AE=E7=AE=A1=E7=90=86=E5=8A=9F?= =?UTF-8?q?=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增 DefaultConfigClient接口,用于与设备微服务进行默认配置相关的操作 - 实现 DefaultConfigIntegrationService 类,提供默认配置管理的高阶服务- 添加批量配置请求构建器 BatchDefaultConfigRequestBuilder,简化批量操作 - 新增 DefaultConfigIntegrationExample 示例类,演示默认配置管理的使用方法 - 更新 CLAUDE.md 文档,增加默认配置管理的详细使用说明和示例代码 --- .../java/com/ycwl/basic/integration/CLAUDE.md | 368 ++++++++++++++++++ .../device/client/DefaultConfigClient.java | 54 +++ .../defaults/BatchDefaultConfigRequest.java | 18 + .../defaults/BatchDefaultConfigResponse.java | 23 ++ .../dto/defaults/DefaultConfigConflict.java | 24 ++ .../dto/defaults/DefaultConfigRequest.java | 26 ++ .../dto/defaults/DefaultConfigResponse.java | 28 ++ .../DefaultConfigIntegrationExample.java | 275 +++++++++++++ .../DefaultConfigIntegrationService.java | 230 +++++++++++ 9 files changed, 1046 insertions(+) create mode 100644 src/main/java/com/ycwl/basic/integration/device/client/DefaultConfigClient.java create mode 100644 src/main/java/com/ycwl/basic/integration/device/dto/defaults/BatchDefaultConfigRequest.java create mode 100644 src/main/java/com/ycwl/basic/integration/device/dto/defaults/BatchDefaultConfigResponse.java create mode 100644 src/main/java/com/ycwl/basic/integration/device/dto/defaults/DefaultConfigConflict.java create mode 100644 src/main/java/com/ycwl/basic/integration/device/dto/defaults/DefaultConfigRequest.java create mode 100644 src/main/java/com/ycwl/basic/integration/device/dto/defaults/DefaultConfigResponse.java create mode 100644 src/main/java/com/ycwl/basic/integration/device/example/DefaultConfigIntegrationExample.java create mode 100644 src/main/java/com/ycwl/basic/integration/device/service/DefaultConfigIntegrationService.java diff --git a/src/main/java/com/ycwl/basic/integration/CLAUDE.md b/src/main/java/com/ycwl/basic/integration/CLAUDE.md index 32f8db0..0047ced 100644 --- a/src/main/java/com/ycwl/basic/integration/CLAUDE.md +++ b/src/main/java/com/ycwl/basic/integration/CLAUDE.md @@ -227,10 +227,12 @@ fallbackService.clearAllFallbackCache("zt-scenic"); #### Feign Clients - **DeviceV2Client**: Main device operations (CRUD, filtering, listing) - **DeviceConfigV2Client**: Device configuration management +- **DefaultConfigClient**: Default configuration management #### Services - **DeviceIntegrationService**: High-level device operations (with automatic fallback) - **DeviceConfigIntegrationService**: Device configuration management (with automatic fallback) +- **DefaultConfigIntegrationService**: Default configuration management (with automatic fallback) #### Configuration ```yaml @@ -377,6 +379,355 @@ fallbackService.clearFallbackCache("zt-device", "device:1001"); fallbackService.clearAllFallbackCache("zt-device"); ``` +## Default Configuration Management (ZT-Device Microservice) + +### Key Components + +#### Default Configuration API +The zt-device microservice provides a comprehensive default configuration management API at `/api/device/config/v2/defaults` that allows: +- Creating and managing default configuration templates +- Batch operations with conflict detection +- Configuration type validation and enforcement +- Usage tracking and analytics + +#### Feign Client +- **DefaultConfigClient**: Default configuration management operations + +#### Service +- **DefaultConfigIntegrationService**: High-level default configuration operations (with automatic fallback for queries) + +### Usage Examples + +#### Basic Default Configuration Operations (with Automatic Fallback) +```java +@Autowired +private DefaultConfigIntegrationService defaultConfigService; + +// Get default configuration list (automatically falls back to cache on failure) +PageResponse configList = defaultConfigService.listDefaultConfigs(1, 10); +log.info("Default configs: total={}, current page={}", + configList.getData().getTotal(), configList.getData().getList().size()); + +// Get specific default configuration (automatically falls back to cache on failure) +DefaultConfigResponse config = defaultConfigService.getDefaultConfig("resolution"); +if (config != null) { + log.info("Default resolution: {}", config.getConfigValue()); +} + +// Create new default configuration (direct operation, fails immediately on error) +DefaultConfigRequest newConfig = new DefaultConfigRequest(); +newConfig.setConfigKey("bitrate"); +newConfig.setConfigValue("2000000"); +newConfig.setConfigType("int"); +newConfig.setDescription("Default video bitrate in bps"); +boolean created = defaultConfigService.createDefaultConfig(newConfig); + +// Update default configuration with conflict detection (direct operation) +Map updates = new HashMap<>(); +updates.put("configValue", "4000000"); +updates.put("description", "Updated default bitrate - high quality"); +DefaultConfigConflict conflict = defaultConfigService.updateDefaultConfig("bitrate", updates); + +if (conflict != null) { + log.warn("Configuration update conflict detected:"); + log.warn(" Key: {}, Type: {}, Affected devices: {}", + conflict.getConfigKey(), conflict.getConflictType(), conflict.getDeviceCount()); + log.warn(" Current type: {}, Proposed type: {}", + conflict.getCurrentType(), conflict.getProposedType()); + + // Handle conflict - show affected device IDs + if (conflict.getConflictDevices() != null) { + log.warn(" Conflicted device IDs: {}", conflict.getConflictDevices()); + } +} else { + log.info("Configuration updated successfully without conflicts"); +} + +// Delete default configuration (direct operation, fails immediately on error) +boolean deleted = defaultConfigService.deleteDefaultConfig("bitrate"); +``` + +#### Batch Default Configuration Operations +```java +// Using Builder Pattern for batch operations +BatchDefaultConfigRequest batchRequest = defaultConfigService.createBatchConfigBuilder() + .addVideoConfig("1920x1080", 30, "H265") // Add video configuration group + .addNetworkConfig("192.168.1.100", 554, "RTSP") // Add network configuration group + .addConfig("recording_enabled", "true", "bool", "Enable recording by default") + .addConfig("storage_retention", "30", "int", "Storage retention in days") + .addConfig("quality_profile", "high", "string", "Default video quality profile") + .build(); + +// Execute batch update (direct operation, no fallback) +BatchDefaultConfigResponse result = defaultConfigService.batchUpdateDefaultConfigs(batchRequest); + +// Process batch results +log.info("Batch operation completed: {} success, {} failed", result.getSuccess(), result.getFailed()); + +// Handle conflicts +if (result.getConflicts() != null && !result.getConflicts().isEmpty()) { + log.warn("Configuration conflicts detected:"); + for (DefaultConfigConflict conflict : result.getConflicts()) { + log.warn(" Key: {}, Type: {}, Devices affected: {}", + conflict.getConfigKey(), conflict.getConflictType(), conflict.getDeviceCount()); + } +} + +// Review processed items +if (result.getProcessedItems() != null) { + result.getProcessedItems().forEach(item -> { + if ("success".equals(item.getStatus())) { + log.info("✅ {} {} successfully (type: {})", + item.getConfigKey(), item.getAction(), item.getFinalType()); + } else { + log.warn("❌ {} failed: {}", item.getConfigKey(), item.getMessage()); + } + }); +} + +// Handle errors +if (result.getErrors() != null && !result.getErrors().isEmpty()) { + result.getErrors().forEach(error -> log.error("Batch operation error: {}", error)); +} +``` + +#### Device Type Specific Default Configuration Patterns +```java +// Create IPC camera default configurations +BatchDefaultConfigRequest ipcDefaults = defaultConfigService.createBatchConfigBuilder() + .addVideoConfig("1920x1080", 25, "H264") // Standard HD resolution + .addConfig("night_vision", "true", "bool", "Enable night vision") + .addConfig("motion_detection", "true", "bool", "Enable motion detection") + .addConfig("stream_profile", "main", "string", "Default stream profile") + .addConfig("ptz_enabled", "false", "bool", "PTZ control enabled") + .addConfig("audio_enabled", "true", "bool", "Audio recording enabled") + .build(); + +// Create NVR default configurations +BatchDefaultConfigRequest nvrDefaults = defaultConfigService.createBatchConfigBuilder() + .addConfig("max_channels", "16", "int", "Maximum supported channels") + .addConfig("storage_mode", "continuous", "string", "Recording storage mode") + .addConfig("backup_enabled", "true", "bool", "Enable automatic backup") + .addConfig("raid_level", "5", "int", "Default RAID level") + .addConfig("disk_quota", "80", "int", "Disk usage quota percentage") + .build(); + +// Apply device-type-specific defaults +BatchDefaultConfigResponse ipcResult = defaultConfigService.batchUpdateDefaultConfigs(ipcDefaults); +BatchDefaultConfigResponse nvrResult = defaultConfigService.batchUpdateDefaultConfigs(nvrDefaults); + +log.info("IPC defaults: {} success, {} failed", ipcResult.getSuccess(), ipcResult.getFailed()); +log.info("NVR defaults: {} success, {} failed", nvrResult.getSuccess(), nvrResult.getFailed()); +``` + +#### Configuration Validation and Management Patterns +```java +// Validate system configuration completeness +PageResponse allDefaults = defaultConfigService.listDefaultConfigs(1, 100); + +// Check for required default configurations +String[] requiredDefaults = { + "resolution", "frameRate", "codec", "bitrate", + "protocol", "port", "username", "password" +}; + +Map configStatus = new HashMap<>(); +for (String required : requiredDefaults) { + boolean exists = allDefaults.getData().getList().stream() + .anyMatch(config -> required.equals(config.getConfigKey())); + configStatus.put(required, exists); + + if (!exists) { + log.warn("Missing required default configuration: {}", required); + } +} + +// Generate configuration completeness report +long totalConfigs = allDefaults.getData().getTotal(); +long completeConfigs = configStatus.values().stream().mapToLong(exists -> exists ? 1 : 0).sum(); +double completeness = (double) completeConfigs / requiredDefaults.length * 100; + +log.info("Configuration completeness: {:.1f}% ({}/{} required configs present)", + completeness, completeConfigs, requiredDefaults.length); +log.info("Total default configurations in system: {}", totalConfigs); + +// Analyze configuration type distribution +Map typeDistribution = allDefaults.getData().getList().stream() + .collect(Collectors.groupingBy( + DefaultConfigResponse::getConfigType, + Collectors.counting() + )); + +log.info("Configuration type distribution: {}", typeDistribution); + +// Find most and least used configurations +DefaultConfigResponse mostUsed = allDefaults.getData().getList().stream() + .max(Comparator.comparing(DefaultConfigResponse::getUsageCount)) + .orElse(null); + +DefaultConfigResponse leastUsed = allDefaults.getData().getList().stream() + .min(Comparator.comparing(DefaultConfigResponse::getUsageCount)) + .orElse(null); + +if (mostUsed != null) { + log.info("Most used default config: {} (used {} times)", + mostUsed.getConfigKey(), mostUsed.getUsageCount()); +} +if (leastUsed != null) { + log.info("Least used default config: {} (used {} times)", + leastUsed.getConfigKey(), leastUsed.getUsageCount()); +} +``` + +#### Advanced Batch Configuration with Error Handling +```java +// Complex batch operation with comprehensive error handling +try { + BatchDefaultConfigRequest complexBatch = defaultConfigService.createBatchConfigBuilder() + .addVideoConfig("3840x2160", 60, "H265") // 4K configuration + .addConfig("hdr_enabled", "true", "bool", "HDR video support") + .addConfig("ai_analysis", "enabled", "string", "AI analysis features") + .addConfig("edge_processing", "true", "bool", "Edge computing enabled") + .addConfig("cloud_sync", "auto", "string", "Cloud synchronization mode") + .build(); + + BatchDefaultConfigResponse result = defaultConfigService.batchUpdateDefaultConfigs(complexBatch); + + // Detailed result analysis + if (result.getSuccess() == complexBatch.getConfigs().size()) { + log.info("✅ All {} configurations processed successfully", result.getSuccess()); + } else if (result.getSuccess() > 0) { + log.warn("⚠️ Partial success: {} succeeded, {} failed", result.getSuccess(), result.getFailed()); + + // Analyze what succeeded vs failed + if (result.getProcessedItems() != null) { + Map statusCounts = result.getProcessedItems().stream() + .collect(Collectors.groupingBy( + ProcessedConfigItem::getStatus, + Collectors.counting() + )); + log.info("Processing breakdown: {}", statusCounts); + } + } else { + log.error("❌ All configurations failed to process"); + } + + // Handle different types of conflicts + if (result.getConflicts() != null) { + Map> conflictsByType = result.getConflicts().stream() + .collect(Collectors.groupingBy(DefaultConfigConflict::getConflictType)); + + conflictsByType.forEach((conflictType, conflicts) -> { + log.warn("Conflict type '{}' affects {} configurations:", conflictType, conflicts.size()); + conflicts.forEach(conflict -> + log.warn(" {} affects {} devices", conflict.getConfigKey(), conflict.getDeviceCount()) + ); + }); + } + +} catch (Exception e) { + log.error("Batch default configuration operation failed", e); + // Implement retry logic or fallback behavior as needed +} +``` + +#### Fallback Cache Management for Default Configurations +```java +@Autowired +private IntegrationFallbackService fallbackService; + +// Check fallback cache status for default configurations +boolean hasDefaultListCache = fallbackService.hasFallbackCache("zt-device", "defaults:list:1:10"); +boolean hasSpecificConfigCache = fallbackService.hasFallbackCache("zt-device", "defaults:config:resolution"); + +// Get cache statistics +IntegrationFallbackService.FallbackCacheStats stats = fallbackService.getFallbackCacheStats("zt-device"); +log.info("Default config fallback cache: {} items, TTL: {} days", + stats.getTotalCacheCount(), stats.getFallbackTtlDays()); + +// Clear specific default configuration cache +fallbackService.clearFallbackCache("zt-device", "defaults:config:resolution"); + +// Clear all default configuration caches +fallbackService.clearAllFallbackCache("zt-device"); +``` + +### Default Configuration Types and Common Keys + +#### Video Configuration Defaults +- `resolution`: Video resolution ("1920x1080", "3840x2160", "1280x720") +- `frameRate`: Video frame rate (integer: 15, 25, 30, 60) +- `codec`: Video codec ("H264", "H265", "MJPEG") +- `bitrate`: Video bitrate in bps (integer) +- `quality`: Video quality level ("low", "medium", "high", "ultra") + +#### Network Configuration Defaults +- `protocol`: Network protocol ("RTSP", "HTTP", "ONVIF") +- `port`: Network port (integer: 554, 80, 8080) +- `timeout`: Connection timeout in seconds (integer) +- `retry_count`: Maximum retry attempts (integer) + +#### Authentication Defaults +- `username`: Default username (string) +- `password`: Default password (string) +- `auth_method`: Authentication method ("basic", "digest", "none") + +#### Storage and Recording Defaults +- `storage_path`: Default storage path (string) +- `recording_enabled`: Enable recording (boolean) +- `retention_days`: Storage retention period (integer) +- `max_file_size`: Maximum file size in MB (integer) + +#### Feature Control Defaults +- `motion_detection`: Enable motion detection (boolean) +- `night_vision`: Enable night vision (boolean) +- `audio_enabled`: Enable audio recording (boolean) +- `ptz_enabled`: Enable PTZ control (boolean) +- `ai_analysis`: AI analysis features ("enabled", "disabled", "auto") + +### Error Handling and Responses + +#### HTTP Status Codes +- **200 OK**: Configuration retrieved/updated successfully +- **201 Created**: New configuration created successfully +- **202 Accepted**: Operation completed with conflicts (check response for details) +- **400 Bad Request**: Invalid request parameters or validation errors +- **404 Not Found**: Configuration key not found +- **409 Conflict**: Configuration conflicts prevent operation (includes conflict details) + +#### Conflict Resolution +When updating default configurations that are actively used by devices, the API performs conflict detection: + +1. **Type Conflicts**: Changing configuration type when devices use different types +2. **Value Validation**: Ensuring new values are compatible with existing device configurations +3. **Dependency Conflicts**: Checking for configuration dependencies and relationships + +The response includes detailed conflict information to help resolve issues: +```java +// Example conflict handling +DefaultConfigConflict conflict = updateResult; +if (conflict != null) { + switch (conflict.getConflictType()) { + case "TYPE_MISMATCH": + log.warn("Type conflict: {} devices using '{}' type, proposed '{}'type", + conflict.getDeviceCount(), conflict.getCurrentType(), conflict.getProposedType()); + // Handle type conversion or device updates + break; + + case "VALUE_RANGE": + log.warn("Value range conflict for key '{}' affects {} devices", + conflict.getConfigKey(), conflict.getDeviceCount()); + // Handle value range adjustments + break; + + case "DEPENDENCY": + log.warn("Dependency conflict detected for '{}'", conflict.getConfigKey()); + // Handle dependency resolution + break; + } +} +``` + ### Enhanced Batch Configuration API Device Integration now supports an enhanced batch configuration API that provides detailed processing results and supports default configuration rules. @@ -432,6 +783,23 @@ Each processed item includes: - **IPC**: IP Camera devices for video monitoring - **CUSTOM**: Custom device types for sensors, controllers, etc. +### Testing Default Configuration Integration + +```bash +# Run default configuration integration tests +mvn test -Dtest=DefaultConfigIntegrationServiceTest + +# Run all device integration tests (including default configs) +mvn test -Dtest="com.ycwl.basic.integration.device.*Test" + +# Enable example runner in application-dev.yml +integration: + device: + example: + default-config: + enabled: true +``` + ### Common Configuration Keys - `ip_address`: Device IP address - `resolution`: Video resolution (e.g., "1920x1080", "3840x2160") diff --git a/src/main/java/com/ycwl/basic/integration/device/client/DefaultConfigClient.java b/src/main/java/com/ycwl/basic/integration/device/client/DefaultConfigClient.java new file mode 100644 index 0000000..f1571c1 --- /dev/null +++ b/src/main/java/com/ycwl/basic/integration/device/client/DefaultConfigClient.java @@ -0,0 +1,54 @@ +package com.ycwl.basic.integration.device.client; + +import com.ycwl.basic.integration.common.response.CommonResponse; +import com.ycwl.basic.integration.common.response.PageResponse; +import com.ycwl.basic.integration.device.dto.defaults.*; +import org.springframework.cloud.openfeign.FeignClient; +import org.springframework.web.bind.annotation.*; + +import java.util.Map; + +/** + * 默认配置管理 Feign 客户端 + */ +@FeignClient(name = "zt-device", contextId = "device-default-config", path = "/api/device/config/v2/defaults") +public interface DefaultConfigClient { + + /** + * 获取默认配置列表 + */ + @GetMapping + PageResponse listDefaultConfigs(@RequestParam(value = "page", defaultValue = "1") int page, + @RequestParam(value = "pageSize", defaultValue = "10") int pageSize); + + /** + * 根据配置键获取默认配置 + */ + @GetMapping("/{configKey}") + CommonResponse getDefaultConfig(@PathVariable("configKey") String configKey); + + /** + * 创建默认配置 + */ + @PostMapping + CommonResponse createDefaultConfig(@RequestBody DefaultConfigRequest request); + + /** + * 更新默认配置 + */ + @PutMapping("/{configKey}") + CommonResponse> updateDefaultConfig(@PathVariable("configKey") String configKey, + @RequestBody Map updates); + + /** + * 删除默认配置 + */ + @DeleteMapping("/{configKey}") + CommonResponse deleteDefaultConfig(@PathVariable("configKey") String configKey); + + /** + * 批量更新默认配置 + */ + @PostMapping("/batch") + CommonResponse batchUpdateDefaultConfigs(@RequestBody BatchDefaultConfigRequest request); +} \ No newline at end of file diff --git a/src/main/java/com/ycwl/basic/integration/device/dto/defaults/BatchDefaultConfigRequest.java b/src/main/java/com/ycwl/basic/integration/device/dto/defaults/BatchDefaultConfigRequest.java new file mode 100644 index 0000000..081e88e --- /dev/null +++ b/src/main/java/com/ycwl/basic/integration/device/dto/defaults/BatchDefaultConfigRequest.java @@ -0,0 +1,18 @@ +package com.ycwl.basic.integration.device.dto.defaults; + +import lombok.Data; + +import javax.validation.Valid; +import javax.validation.constraints.NotEmpty; +import java.util.List; + +/** + * 批量默认配置操作请求模型 + */ +@Data +public class BatchDefaultConfigRequest { + + @NotEmpty(message = "配置列表不能为空") + @Valid + private List configs; +} \ No newline at end of file diff --git a/src/main/java/com/ycwl/basic/integration/device/dto/defaults/BatchDefaultConfigResponse.java b/src/main/java/com/ycwl/basic/integration/device/dto/defaults/BatchDefaultConfigResponse.java new file mode 100644 index 0000000..39ac042 --- /dev/null +++ b/src/main/java/com/ycwl/basic/integration/device/dto/defaults/BatchDefaultConfigResponse.java @@ -0,0 +1,23 @@ +package com.ycwl.basic.integration.device.dto.defaults; + +import com.ycwl.basic.integration.device.dto.config.ProcessedConfigItem; +import lombok.Data; + +import java.util.List; + +/** + * 批量默认配置操作响应模型 + */ +@Data +public class BatchDefaultConfigResponse { + + private Integer success; + + private Integer failed; + + private List conflicts; + + private List processedItems; + + private List errors; +} \ No newline at end of file diff --git a/src/main/java/com/ycwl/basic/integration/device/dto/defaults/DefaultConfigConflict.java b/src/main/java/com/ycwl/basic/integration/device/dto/defaults/DefaultConfigConflict.java new file mode 100644 index 0000000..7178b45 --- /dev/null +++ b/src/main/java/com/ycwl/basic/integration/device/dto/defaults/DefaultConfigConflict.java @@ -0,0 +1,24 @@ +package com.ycwl.basic.integration.device.dto.defaults; + +import lombok.Data; + +import java.util.List; + +/** + * 冲突信息模型 + */ +@Data +public class DefaultConfigConflict { + + private String configKey; + + private String conflictType; + + private Integer deviceCount; + + private String currentType; + + private String proposedType; + + private List conflictDevices; +} \ No newline at end of file diff --git a/src/main/java/com/ycwl/basic/integration/device/dto/defaults/DefaultConfigRequest.java b/src/main/java/com/ycwl/basic/integration/device/dto/defaults/DefaultConfigRequest.java new file mode 100644 index 0000000..59e49c5 --- /dev/null +++ b/src/main/java/com/ycwl/basic/integration/device/dto/defaults/DefaultConfigRequest.java @@ -0,0 +1,26 @@ +package com.ycwl.basic.integration.device.dto.defaults; + +import com.fasterxml.jackson.annotation.JsonInclude; +import lombok.Data; + +import javax.validation.constraints.NotBlank; + +/** + * 默认配置请求模型 + */ +@Data +@JsonInclude(JsonInclude.Include.NON_NULL) +public class DefaultConfigRequest { + + @NotBlank(message = "配置键不能为空") + private String configKey; + + @NotBlank(message = "配置值不能为空") + private String configValue; + + @NotBlank(message = "配置类型不能为空") + private String configType; + + @NotBlank(message = "配置描述不能为空") + private String description; +} \ No newline at end of file diff --git a/src/main/java/com/ycwl/basic/integration/device/dto/defaults/DefaultConfigResponse.java b/src/main/java/com/ycwl/basic/integration/device/dto/defaults/DefaultConfigResponse.java new file mode 100644 index 0000000..586c8ac --- /dev/null +++ b/src/main/java/com/ycwl/basic/integration/device/dto/defaults/DefaultConfigResponse.java @@ -0,0 +1,28 @@ +package com.ycwl.basic.integration.device.dto.defaults; + +import lombok.Data; + +/** + * 默认配置响应模型 + */ +@Data +public class DefaultConfigResponse { + + private String id; + + private String configKey; + + private String configValue; + + private String configType; + + private String description; + + private Integer isActive; + + private String createTime; + + private String updateTime; + + private Integer usageCount; +} \ No newline at end of file diff --git a/src/main/java/com/ycwl/basic/integration/device/example/DefaultConfigIntegrationExample.java b/src/main/java/com/ycwl/basic/integration/device/example/DefaultConfigIntegrationExample.java new file mode 100644 index 0000000..c39b2b9 --- /dev/null +++ b/src/main/java/com/ycwl/basic/integration/device/example/DefaultConfigIntegrationExample.java @@ -0,0 +1,275 @@ +package com.ycwl.basic.integration.device.example; + +import com.ycwl.basic.integration.common.response.PageResponse; +import com.ycwl.basic.integration.device.dto.defaults.*; +import com.ycwl.basic.integration.device.service.DefaultConfigIntegrationService; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.boot.CommandLineRunner; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.Map; + +/** + * 默认配置集成服务使用示例 + * + * 通过在 application.yml 中设置 integration.device.example.default-config.enabled=true 来启用 + */ +@Slf4j +@Component +@RequiredArgsConstructor +@ConditionalOnProperty(name = "integration.device.example.default-config.enabled", havingValue = "true") +public class DefaultConfigIntegrationExample implements CommandLineRunner { + + private final DefaultConfigIntegrationService defaultConfigService; + + @Override + public void run(String... args) throws Exception { + log.info("=== 默认配置集成服务使用示例 ==="); + + try { + // 1. 基础查询操作示例(支持自动 Fallback) + basicQueryExamples(); + + // 2. 配置管理操作示例(直接操作) + configManagementExamples(); + + // 3. 批量操作示例 + batchOperationExamples(); + + // 4. 高级使用模式示例 + advancedUsageExamples(); + + } catch (Exception e) { + log.error("默认配置集成示例执行失败", e); + } + } + + /** + * 基础查询操作示例(支持自动 Fallback) + */ + private void basicQueryExamples() { + log.info("--- 基础查询操作示例(支持自动 Fallback)---"); + + try { + // 获取默认配置列表(自动缓存,服务不可用时返回缓存数据) + PageResponse configList = defaultConfigService.listDefaultConfigs(1, 10); + log.info("默认配置列表: 总数={}, 当前页配置数={}", + configList.getData().getTotal(), configList.getData().getList().size()); + + // 显示配置详情 + for (DefaultConfigResponse config : configList.getData().getList()) { + log.info("配置详情: key={}, value={}, type={}, description={}", + config.getConfigKey(), config.getConfigValue(), + config.getConfigType(), config.getDescription()); + + // 获取单个配置详情(自动缓存,服务不可用时返回缓存数据) + DefaultConfigResponse detailConfig = defaultConfigService.getDefaultConfig(config.getConfigKey()); + if (detailConfig != null) { + log.info("配置详情获取成功: usageCount={}, isActive={}", + detailConfig.getUsageCount(), detailConfig.getIsActive()); + } + break; // 只展示第一个 + } + + } catch (Exception e) { + log.error("基础查询操作失败", e); + } + } + + /** + * 配置管理操作示例(直接操作) + */ + private void configManagementExamples() { + log.info("--- 配置管理操作示例(直接操作)---"); + + String testConfigKey = "example_test_config"; + + try { + // 1. 创建默认配置(直接操作,失败时立即报错) + DefaultConfigRequest createRequest = new DefaultConfigRequest(); + createRequest.setConfigKey(testConfigKey); + createRequest.setConfigValue("1920x1080"); + createRequest.setConfigType("string"); + createRequest.setDescription("示例测试配置 - 默认分辨率"); + + boolean createResult = defaultConfigService.createDefaultConfig(createRequest); + log.info("创建默认配置结果: {}", createResult ? "成功" : "失败"); + + // 2. 更新默认配置(直接操作,可能返回冲突信息) + Map updates = new HashMap<>(); + updates.put("configValue", "3840x2160"); + updates.put("description", "更新后的默认分辨率 - 4K"); + + DefaultConfigConflict conflict = defaultConfigService.updateDefaultConfig(testConfigKey, updates); + if (conflict != null) { + log.warn("更新配置存在冲突: configKey={}, conflictType={}, deviceCount={}", + conflict.getConfigKey(), conflict.getConflictType(), conflict.getDeviceCount()); + } else { + log.info("配置更新成功,无冲突"); + } + + // 3. 验证更新结果 + DefaultConfigResponse updatedConfig = defaultConfigService.getDefaultConfig(testConfigKey); + if (updatedConfig != null) { + log.info("更新后配置值: {}", updatedConfig.getConfigValue()); + } + + // 4. 删除测试配置(直接操作) + boolean deleteResult = defaultConfigService.deleteDefaultConfig(testConfigKey); + log.info("删除默认配置结果: {}", deleteResult ? "成功" : "失败"); + + } catch (Exception e) { + log.error("配置管理操作失败", e); + } + } + + /** + * 批量操作示例 + */ + private void batchOperationExamples() { + log.info("--- 批量操作示例 ---"); + + try { + // 1. 使用构建器模式创建批量配置 + BatchDefaultConfigRequest batchRequest = defaultConfigService.createBatchConfigBuilder() + .addVideoConfig("1920x1080", 30, "H264") // 添加视频配置组 + .addNetworkConfig("192.168.1.100", 554, "RTSP") // 添加网络配置组 + .addConfig("recording_enabled", "true", "bool", "是否启用录制") + .addConfig("storage_path", "/data/recordings", "string", "录制存储路径") + .addConfig("max_file_size", "1024", "int", "最大文件大小(MB)") + .build(); + + log.info("准备批量创建 {} 个默认配置", batchRequest.getConfigs().size()); + + // 2. 执行批量更新(直接操作) + BatchDefaultConfigResponse batchResult = defaultConfigService.batchUpdateDefaultConfigs(batchRequest); + + // 3. 处理批量结果 + log.info("批量操作结果: 成功={}, 失败={}", batchResult.getSuccess(), batchResult.getFailed()); + + if (batchResult.getConflicts() != null && !batchResult.getConflicts().isEmpty()) { + log.warn("发现 {} 个配置冲突:", batchResult.getConflicts().size()); + for (DefaultConfigConflict conflict : batchResult.getConflicts()) { + log.warn("冲突配置: key={}, type={}, deviceCount={}", + conflict.getConfigKey(), conflict.getConflictType(), conflict.getDeviceCount()); + } + } + + if (batchResult.getProcessedItems() != null) { + log.info("处理详情:"); + batchResult.getProcessedItems().forEach(item -> + log.info(" 配置 {}: status={}, action={}, finalType={}", + item.getConfigKey(), item.getStatus(), item.getAction(), item.getFinalType()) + ); + } + + if (batchResult.getErrors() != null && !batchResult.getErrors().isEmpty()) { + log.error("批量操作错误:"); + batchResult.getErrors().forEach(error -> log.error(" {}", error)); + } + + } catch (Exception e) { + log.error("批量操作失败", e); + } + } + + /** + * 高级使用模式示例 + */ + private void advancedUsageExamples() { + log.info("--- 高级使用模式示例 ---"); + + try { + // 1. 设备类型特定的默认配置模式 + createDeviceTypeSpecificConfigs(); + + // 2. 配置验证和完整性检查模式 + validateConfigCompleteness(); + + // 3. 配置迁移和批量更新模式 + configMigrationPattern(); + + } catch (Exception e) { + log.error("高级使用模式示例失败", e); + } + } + + /** + * 创建设备类型特定的默认配置 + */ + private void createDeviceTypeSpecificConfigs() { + log.info("创建设备类型特定的默认配置..."); + + // IPC摄像头默认配置 + BatchDefaultConfigRequest ipcDefaults = defaultConfigService.createBatchConfigBuilder() + .addVideoConfig("1920x1080", 25, "H264") + .addConfig("night_vision", "true", "bool", "夜视功能") + .addConfig("motion_detection", "true", "bool", "移动检测") + .addConfig("stream_profile", "main", "string", "码流类型") + .build(); + + // NVR设备默认配置 + BatchDefaultConfigRequest nvrDefaults = defaultConfigService.createBatchConfigBuilder() + .addConfig("max_channels", "16", "int", "最大通道数") + .addConfig("storage_mode", "continuous", "string", "存储模式") + .addConfig("backup_enabled", "true", "bool", "备份启用") + .build(); + + log.info("IPC默认配置项数: {}, NVR默认配置项数: {}", + ipcDefaults.getConfigs().size(), nvrDefaults.getConfigs().size()); + } + + /** + * 配置验证和完整性检查 + */ + private void validateConfigCompleteness() { + log.info("验证配置完整性..."); + + // 获取所有默认配置 + PageResponse allConfigs = defaultConfigService.listDefaultConfigs(1, 100); + + // 检查必需的基础配置是否存在 + String[] requiredConfigs = {"resolution", "frameRate", "codec", "protocol"}; + for (String requiredConfig : requiredConfigs) { + boolean exists = allConfigs.getData().getList().stream() + .anyMatch(config -> requiredConfig.equals(config.getConfigKey())); + log.info("必需配置 {} 存在: {}", requiredConfig, exists ? "✓" : "✗"); + } + + // 统计配置类型分布 + Map typeDistribution = new HashMap<>(); + allConfigs.getData().getList().forEach(config -> + typeDistribution.merge(config.getConfigType(), 1L, Long::sum) + ); + + log.info("配置类型分布: {}", typeDistribution); + } + + /** + * 配置迁移和批量更新模式 + */ + private void configMigrationPattern() { + log.info("配置迁移模式示例..."); + + try { + // 1. 获取需要升级的配置 + PageResponse oldConfigs = defaultConfigService.listDefaultConfigs(1, 50); + + // 2. 创建升级配置批次 + BatchDefaultConfigRequest upgradeRequest = defaultConfigService.createBatchConfigBuilder() + .addConfig("api_version", "v2", "string", "API版本") + .addConfig("security_mode", "enhanced", "string", "安全模式") + .build(); + + // 3. 执行批量升级 + BatchDefaultConfigResponse upgradeResult = defaultConfigService.batchUpdateDefaultConfigs(upgradeRequest); + log.info("配置升级结果: 成功={}, 失败={}", upgradeResult.getSuccess(), upgradeResult.getFailed()); + + } catch (Exception e) { + log.warn("配置迁移示例执行失败(这是正常的,因为是示例代码)", e); + } + } +} \ No newline at end of file diff --git a/src/main/java/com/ycwl/basic/integration/device/service/DefaultConfigIntegrationService.java b/src/main/java/com/ycwl/basic/integration/device/service/DefaultConfigIntegrationService.java new file mode 100644 index 0000000..3a996e7 --- /dev/null +++ b/src/main/java/com/ycwl/basic/integration/device/service/DefaultConfigIntegrationService.java @@ -0,0 +1,230 @@ +package com.ycwl.basic.integration.device.service; + +import com.ycwl.basic.integration.common.exception.IntegrationException; +import com.ycwl.basic.integration.common.response.CommonResponse; +import com.ycwl.basic.integration.common.response.PageResponse; +import com.ycwl.basic.integration.common.service.IntegrationFallbackService; +import com.ycwl.basic.integration.device.client.DefaultConfigClient; +import com.ycwl.basic.integration.device.dto.defaults.*; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map; + +/** + * 默认配置集成服务 + */ +@Slf4j +@Service +@RequiredArgsConstructor +public class DefaultConfigIntegrationService { + + private final DefaultConfigClient defaultConfigClient; + private final IntegrationFallbackService fallbackService; + + private static final String SERVICE_NAME = "zt-device"; + + /** + * 获取默认配置列表(支持 Fallback) + */ + public PageResponse listDefaultConfigs(int page, int pageSize) { + return fallbackService.executeWithFallback( + SERVICE_NAME, + "defaults:list:" + page + ":" + pageSize, + () -> { + PageResponse response = defaultConfigClient.listDefaultConfigs(page, pageSize); + return handlePageResponse(response, "获取默认配置列表失败"); + }, + PageResponse.class + ); + } + + /** + * 根据配置键获取默认配置(支持 Fallback) + */ + public DefaultConfigResponse getDefaultConfig(String configKey) { + return fallbackService.executeWithFallback( + SERVICE_NAME, + "defaults:config:" + configKey, + () -> { + log.info("获取默认配置, configKey: {}", configKey); + CommonResponse response = defaultConfigClient.getDefaultConfig(configKey); + return handleResponse(response, "获取默认配置失败"); + }, + DefaultConfigResponse.class + ); + } + + /** + * 创建默认配置(直接操作,不支持 Fallback) + */ + public boolean createDefaultConfig(DefaultConfigRequest request) { + log.info("创建默认配置, configKey: {}", request.getConfigKey()); + CommonResponse response = defaultConfigClient.createDefaultConfig(request); + String result = handleResponse(response, "创建默认配置失败"); + return result != null; + } + + /** + * 更新默认配置(直接操作,不支持 Fallback) + */ + public DefaultConfigConflict updateDefaultConfig(String configKey, Map updates) { + log.info("更新默认配置, configKey: {}, updates: {}", configKey, updates); + CommonResponse> response = defaultConfigClient.updateDefaultConfig(configKey, updates); + Map result = handleResponse(response, "更新默认配置失败"); + + // 检查是否有冲突信息 + if (result != null && result.containsKey("conflict")) { + Object conflictObj = result.get("conflict"); + if (conflictObj instanceof Map) { + // 将Map转换为DefaultConfigConflict对象 + return mapToDefaultConfigConflict((Map) conflictObj); + } + } + + return null; + } + + /** + * 删除默认配置(直接操作,不支持 Fallback) + */ + public boolean deleteDefaultConfig(String configKey) { + log.info("删除默认配置, configKey: {}", configKey); + CommonResponse response = defaultConfigClient.deleteDefaultConfig(configKey); + String result = handleResponse(response, "删除默认配置失败"); + return result != null; + } + + /** + * 批量更新默认配置(直接操作,不支持 Fallback) + */ + public BatchDefaultConfigResponse batchUpdateDefaultConfigs(BatchDefaultConfigRequest request) { + log.info("批量更新默认配置, configs count: {}", request.getConfigs().size()); + CommonResponse response = defaultConfigClient.batchUpdateDefaultConfigs(request); + return handleResponse(response, "批量更新默认配置失败"); + } + + /** + * 创建批量配置请求构建器 + */ + public BatchDefaultConfigRequestBuilder createBatchConfigBuilder() { + return new BatchDefaultConfigRequestBuilder(); + } + + /** + * 批量配置请求构建器 + */ + public static class BatchDefaultConfigRequestBuilder { + private final BatchDefaultConfigRequest request = new BatchDefaultConfigRequest(); + + public BatchDefaultConfigRequestBuilder() { + request.setConfigs(new ArrayList<>()); + } + + /** + * 添加配置项 + */ + public BatchDefaultConfigRequestBuilder addConfig(String configKey, String configValue, + String configType, String description) { + DefaultConfigRequest item = new DefaultConfigRequest(); + item.setConfigKey(configKey); + item.setConfigValue(configValue); + item.setConfigType(configType); + item.setDescription(description); + request.getConfigs().add(item); + return this; + } + + /** + * 添加视频配置 + */ + public BatchDefaultConfigRequestBuilder addVideoConfig(String resolution, Integer frameRate, String codec) { + addConfig("resolution", resolution, "string", "视频分辨率"); + addConfig("frameRate", frameRate.toString(), "int", "视频帧率"); + addConfig("codec", codec, "string", "视频编码格式"); + return this; + } + + /** + * 添加网络配置 + */ + public BatchDefaultConfigRequestBuilder addNetworkConfig(String ipAddress, Integer port, String protocol) { + addConfig("ipAddress", ipAddress, "string", "IP地址"); + addConfig("port", port.toString(), "int", "端口号"); + addConfig("protocol", protocol, "string", "网络协议"); + return this; + } + + /** + * 构建请求对象 + */ + public BatchDefaultConfigRequest build() { + return request; + } + } + + /** + * 将Map转换为DefaultConfigConflict对象 + */ + @SuppressWarnings("unchecked") + private DefaultConfigConflict mapToDefaultConfigConflict(Map map) { + DefaultConfigConflict conflict = new DefaultConfigConflict(); + + if (map.containsKey("configKey")) { + conflict.setConfigKey((String) map.get("configKey")); + } + if (map.containsKey("conflictType")) { + conflict.setConflictType((String) map.get("conflictType")); + } + if (map.containsKey("deviceCount")) { + Object deviceCount = map.get("deviceCount"); + if (deviceCount instanceof Number) { + conflict.setDeviceCount(((Number) deviceCount).intValue()); + } + } + if (map.containsKey("currentType")) { + conflict.setCurrentType((String) map.get("currentType")); + } + if (map.containsKey("proposedType")) { + conflict.setProposedType((String) map.get("proposedType")); + } + if (map.containsKey("conflictDevices")) { + Object conflictDevices = map.get("conflictDevices"); + if (conflictDevices instanceof Iterable) { + conflict.setConflictDevices(new ArrayList<>()); + for (Object deviceId : (Iterable) conflictDevices) { + if (deviceId instanceof Number) { + conflict.getConflictDevices().add(((Number) deviceId).longValue()); + } + } + } + } + + return conflict; + } + + private T handleResponse(CommonResponse response, String errorMessage) { + if (response == null || !response.isSuccess()) { + String msg = response != null && response.getMessage() != null + ? response.getMessage() + : errorMessage; + Integer code = response != null ? response.getCode() : 5000; + throw new IntegrationException(code, msg, SERVICE_NAME); + } + return response.getData(); + } + + private PageResponse handlePageResponse(PageResponse response, String errorMessage) { + if (response == null || !response.isSuccess()) { + String msg = response != null && response.getMessage() != null + ? response.getMessage() + : errorMessage; + Integer code = response != null ? response.getCode() : 5000; + throw new IntegrationException(code, msg, SERVICE_NAME); + } + return response; + } +} \ No newline at end of file From b2a95ed862513eb849e97218a28e2ba6bfc73d6b Mon Sep 17 00:00:00 2001 From: Jerry Yan <792602257@qq.com> Date: Fri, 5 Sep 2025 14:49:19 +0800 Subject: [PATCH 05/16] =?UTF-8?q?feat(integration):=20=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?=E6=B8=B2=E6=9F=93=E5=B7=A5=E4=BD=9C=E5=99=A8=E9=85=8D=E7=BD=AE?= =?UTF-8?q?=E7=AE=A1=E7=90=86=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增 RenderWorkerConfigManager 类实现渲染工作器配置的管理功能 - 在 RenderWorkerRepository 中集成 RenderWorkerConfigManager - 添加方法 getWorkerConfigManager 获取渲染工作器配置管理器实例 - 优化 getWorkerByAccessKey 和 getWorker 方法,使用集成服务获取工作器信息 --- .../manager/RenderWorkerConfigManager.java | 82 +++++++++++++++++++ .../repository/RenderWorkerRepository.java | 70 ++++++++++++---- 2 files changed, 136 insertions(+), 16 deletions(-) create mode 100644 src/main/java/com/ycwl/basic/integration/common/manager/RenderWorkerConfigManager.java diff --git a/src/main/java/com/ycwl/basic/integration/common/manager/RenderWorkerConfigManager.java b/src/main/java/com/ycwl/basic/integration/common/manager/RenderWorkerConfigManager.java new file mode 100644 index 0000000..4e0b7f8 --- /dev/null +++ b/src/main/java/com/ycwl/basic/integration/common/manager/RenderWorkerConfigManager.java @@ -0,0 +1,82 @@ +package com.ycwl.basic.integration.common.manager; + +import com.ycwl.basic.integration.render.dto.config.RenderWorkerConfigV2DTO; + +import java.util.List; + +/** + * 渲染工作器配置管理器 + * 基于通用ConfigManager实现渲染工作器配置的管理功能 + */ +public class RenderWorkerConfigManager extends ConfigManager { + + public RenderWorkerConfigManager(List configs) { + super(configs); + } + + @Override + protected String getConfigKey(RenderWorkerConfigV2DTO config) { + return config != null ? config.getConfigKey() : null; + } + + @Override + protected Object getConfigValue(RenderWorkerConfigV2DTO config) { + return config != null ? config.getConfigValue() : null; + } + + /** + * 获取渲染工作器配置类型 + */ + public String getConfigType(String key) { + RenderWorkerConfigV2DTO config = findConfigByKey(key); + return config != null ? config.getConfigType() : null; + } + + /** + * 获取渲染工作器配置描述 + */ + public String getConfigDescription(String key) { + RenderWorkerConfigV2DTO config = findConfigByKey(key); + return config != null ? config.getDescription() : null; + } + + /** + * 获取渲染工作器配置ID + */ + public Long getConfigId(String key) { + RenderWorkerConfigV2DTO config = findConfigByKey(key); + return config != null ? config.getId() : null; + } + + /** + * 获取工作器ID + */ + public Long getWorkerId(String key) { + RenderWorkerConfigV2DTO config = findConfigByKey(key); + return config != null ? config.getWorkerId() : null; + } + + /** + * 检查配置是否启用 + */ + public boolean isActive(String key) { + RenderWorkerConfigV2DTO config = findConfigByKey(key); + return config != null && config.getIsActive() != null && config.getIsActive() == 1; + } + + /** + * 获取配置的创建时间 + */ + public String getCreateTime(String key) { + RenderWorkerConfigV2DTO config = findConfigByKey(key); + return config != null ? config.getCreateTime() : null; + } + + /** + * 获取配置的更新时间 + */ + public String getUpdateTime(String key) { + RenderWorkerConfigV2DTO config = findConfigByKey(key); + return config != null ? config.getUpdateTime() : null; + } +} \ No newline at end of file diff --git a/src/main/java/com/ycwl/basic/repository/RenderWorkerRepository.java b/src/main/java/com/ycwl/basic/repository/RenderWorkerRepository.java index f58dff5..0155207 100644 --- a/src/main/java/com/ycwl/basic/repository/RenderWorkerRepository.java +++ b/src/main/java/com/ycwl/basic/repository/RenderWorkerRepository.java @@ -4,6 +4,12 @@ import com.ycwl.basic.utils.JacksonUtil; import com.ycwl.basic.mapper.RenderWorkerMapper; import com.ycwl.basic.model.pc.renderWorker.entity.RenderWorkerEntity; import com.ycwl.basic.model.task.req.ClientStatusReqVo; +import com.ycwl.basic.integration.render.dto.worker.RenderWorkerV2DTO; +import com.ycwl.basic.integration.render.service.RenderWorkerIntegrationService; +import com.ycwl.basic.integration.render.service.RenderWorkerConfigIntegrationService; +import com.ycwl.basic.integration.render.dto.config.RenderWorkerConfigV2DTO; +import com.ycwl.basic.integration.common.manager.RenderWorkerConfigManager; +import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.stereotype.Component; @@ -11,40 +17,41 @@ import org.springframework.stereotype.Component; import java.math.BigDecimal; import java.math.RoundingMode; import java.util.Date; +import java.util.List; import java.util.concurrent.TimeUnit; +@Slf4j @Component public class RenderWorkerRepository { @Autowired private RedisTemplate redisTemplate; public static final String RENDER_WORKER_CACHE_KEY = "render_worker:%s"; public static final String RENDER_WORKER_STATUS_CACHE_KEY = "render_worker:host_status:%s"; + public static final String RENDER_WORKER_CONFIG_CACHE_KEY = "render_worker:%s:config"; @Autowired private RenderWorkerMapper mapper; + + @Autowired + private RenderWorkerIntegrationService renderWorkerIntegrationService; + + @Autowired + private RenderWorkerConfigIntegrationService renderWorkerConfigIntegrationService; public RenderWorkerEntity getWorkerByAccessKey(String accessKey) { - String key = String.format(RENDER_WORKER_CACHE_KEY, accessKey); - if (redisTemplate.hasKey(key)) { - return JacksonUtil.parseObject(redisTemplate.opsForValue().get(key), RenderWorkerEntity.class); - } - RenderWorkerEntity renderWorker = mapper.findByAccessKey(accessKey); - if (renderWorker != null) { - redisTemplate.opsForValue().set(key, JacksonUtil.toJSONString(renderWorker), 1, TimeUnit.HOURS); - redisTemplate.opsForValue().set(String.format(RENDER_WORKER_CACHE_KEY, renderWorker.getId()), JacksonUtil.toJSONString(renderWorker), 1, TimeUnit.HOURS); + RenderWorkerV2DTO workerDTO = renderWorkerIntegrationService.getWorkerByKey(accessKey); + if (workerDTO == null) { + return null; } + RenderWorkerEntity renderWorker = convertToEntity(workerDTO); return renderWorker; } public RenderWorkerEntity getWorker(Long id) { - String key = String.format(RENDER_WORKER_CACHE_KEY, id); - if (redisTemplate.hasKey(key)) { - return JacksonUtil.parseObject(redisTemplate.opsForValue().get(key), RenderWorkerEntity.class); - } - RenderWorkerEntity renderWorker = mapper.getById(id); - if (renderWorker != null) { - redisTemplate.opsForValue().set(key, JacksonUtil.toJSONString(renderWorker), 1, TimeUnit.HOURS); - redisTemplate.opsForValue().set(String.format(RENDER_WORKER_CACHE_KEY, renderWorker.getAccessKey()), JacksonUtil.toJSONString(renderWorker), 1, TimeUnit.HOURS); + RenderWorkerV2DTO workerDTO = renderWorkerIntegrationService.getWorker(id); + if (workerDTO == null) { + return null; } + RenderWorkerEntity renderWorker = convertToEntity(workerDTO); return renderWorker; } @@ -89,4 +96,35 @@ public class RenderWorkerRepository { } redisTemplate.delete(String.format(RENDER_WORKER_STATUS_CACHE_KEY, id)); } + + private RenderWorkerEntity convertToEntity(RenderWorkerV2DTO dto) { + if (dto == null) { + return null; + } + RenderWorkerEntity entity = new RenderWorkerEntity(); + entity.setId(dto.getId()); + entity.setName(dto.getName()); + entity.setAccessKey(dto.getKey()); + entity.setStatus(dto.getIsActive()); + entity.setCreateAt(dto.getCreateTime()); + entity.setUpdateAt(dto.getUpdateTime()); + return entity; + } + + /** + * 获取渲染工作器配置管理器 + * + * @param workerId 工作器ID + * @return RenderWorkerConfigManager实例,如果获取失败返回null + */ + public RenderWorkerConfigManager getWorkerConfigManager(Long workerId) { + try { + List configList = renderWorkerConfigIntegrationService.getWorkerConfigs(workerId); + return new RenderWorkerConfigManager(configList); + } catch (Exception e) { + log.error("获取渲染工作器配置管理器失败, workerId: {}", workerId, e); + return null; + } + } + } From 7b22baeb66db42f9823e9da374c01a40ea1b42dc Mon Sep 17 00:00:00 2001 From: Jerry Yan <792602257@qq.com> Date: Fri, 5 Sep 2025 15:47:14 +0800 Subject: [PATCH 06/16] =?UTF-8?q?refactor(device):=20=E6=9B=B4=E6=96=B0?= =?UTF-8?q?=E9=AA=8C=E8=AF=81=E6=B3=A8=E8=A7=A3=E5=AF=BC=E5=85=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 将 javax.validation相关的导入语句替换为 jakarta.validation - 此更改是为了适应 Jakarta EE 规范的最新版本 --- .../device/dto/defaults/BatchDefaultConfigRequest.java | 4 ++-- .../integration/device/dto/defaults/DefaultConfigRequest.java | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/ycwl/basic/integration/device/dto/defaults/BatchDefaultConfigRequest.java b/src/main/java/com/ycwl/basic/integration/device/dto/defaults/BatchDefaultConfigRequest.java index 081e88e..7b47691 100644 --- a/src/main/java/com/ycwl/basic/integration/device/dto/defaults/BatchDefaultConfigRequest.java +++ b/src/main/java/com/ycwl/basic/integration/device/dto/defaults/BatchDefaultConfigRequest.java @@ -2,8 +2,8 @@ package com.ycwl.basic.integration.device.dto.defaults; import lombok.Data; -import javax.validation.Valid; -import javax.validation.constraints.NotEmpty; +import jakarta.validation.Valid; +import jakarta.validation.constraints.NotEmpty; import java.util.List; /** diff --git a/src/main/java/com/ycwl/basic/integration/device/dto/defaults/DefaultConfigRequest.java b/src/main/java/com/ycwl/basic/integration/device/dto/defaults/DefaultConfigRequest.java index 59e49c5..98843a8 100644 --- a/src/main/java/com/ycwl/basic/integration/device/dto/defaults/DefaultConfigRequest.java +++ b/src/main/java/com/ycwl/basic/integration/device/dto/defaults/DefaultConfigRequest.java @@ -3,7 +3,7 @@ package com.ycwl.basic.integration.device.dto.defaults; import com.fasterxml.jackson.annotation.JsonInclude; import lombok.Data; -import javax.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotBlank; /** * 默认配置请求模型 From c9f70806159861f2736d6eb4657704474eae6173 Mon Sep 17 00:00:00 2001 From: Jerry Yan <792602257@qq.com> Date: Fri, 5 Sep 2025 15:48:54 +0800 Subject: [PATCH 07/16] =?UTF-8?q?refactor(device):=20=E4=BC=98=E5=8C=96?= =?UTF-8?q?=E9=BB=98=E8=AE=A4=E9=85=8D=E7=BD=AE=E7=A4=BA=E4=BE=8B=E4=BB=A3?= =?UTF-8?q?=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 移除了不必要的 getData() 调用,直接使用 getList() 和 getTotal() 方法 - 使用 Java 8 Stream API 简化了部分代码,提高了可读性 - 优化了配置类型分布统计逻辑,使用更简洁的方式 --- .../device/example/DefaultConfigIntegrationExample.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/ycwl/basic/integration/device/example/DefaultConfigIntegrationExample.java b/src/main/java/com/ycwl/basic/integration/device/example/DefaultConfigIntegrationExample.java index c39b2b9..b17410e 100644 --- a/src/main/java/com/ycwl/basic/integration/device/example/DefaultConfigIntegrationExample.java +++ b/src/main/java/com/ycwl/basic/integration/device/example/DefaultConfigIntegrationExample.java @@ -57,10 +57,10 @@ public class DefaultConfigIntegrationExample implements CommandLineRunner { // 获取默认配置列表(自动缓存,服务不可用时返回缓存数据) PageResponse configList = defaultConfigService.listDefaultConfigs(1, 10); log.info("默认配置列表: 总数={}, 当前页配置数={}", - configList.getData().getTotal(), configList.getData().getList().size()); + configList.getTotal(), configList.getList().size()); // 显示配置详情 - for (DefaultConfigResponse config : configList.getData().getList()) { + for (DefaultConfigResponse config : configList.getList()) { log.info("配置详情: key={}, value={}, type={}, description={}", config.getConfigKey(), config.getConfigValue(), config.getConfigType(), config.getDescription()); @@ -234,14 +234,14 @@ public class DefaultConfigIntegrationExample implements CommandLineRunner { // 检查必需的基础配置是否存在 String[] requiredConfigs = {"resolution", "frameRate", "codec", "protocol"}; for (String requiredConfig : requiredConfigs) { - boolean exists = allConfigs.getData().getList().stream() + boolean exists = allConfigs.getList().stream() .anyMatch(config -> requiredConfig.equals(config.getConfigKey())); log.info("必需配置 {} 存在: {}", requiredConfig, exists ? "✓" : "✗"); } // 统计配置类型分布 Map typeDistribution = new HashMap<>(); - allConfigs.getData().getList().forEach(config -> + allConfigs.getList().forEach(config -> typeDistribution.merge(config.getConfigType(), 1L, Long::sum) ); From ffad1c9f59e0132ef560ffed79bda48cc2c87f91 Mon Sep 17 00:00:00 2001 From: Jerry Yan <792602257@qq.com> Date: Fri, 5 Sep 2025 16:51:47 +0800 Subject: [PATCH 08/16] =?UTF-8?q?refactor(device):=20=E9=87=8D=E6=9E=84?= =?UTF-8?q?=E9=BB=98=E8=AE=A4=E9=85=8D=E7=BD=AE=E6=8E=A5=E5=8F=A3=E8=BF=94?= =?UTF-8?q?=E5=9B=9E=E7=B1=BB=E5=9E=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 将 DefaultConfigClient 中的 listDefaultConfigs 方法返回类型由 PageResponse 改为 CommonResponse - 更新 DefaultConfigIntegrationService 中的调用方式 - 移除 handlePageResponse 方法,改为使用 handleResponse 方法处理响应 --- .../device/client/DefaultConfigClient.java | 4 ++-- .../service/DefaultConfigIntegrationService.java | 15 ++------------- 2 files changed, 4 insertions(+), 15 deletions(-) diff --git a/src/main/java/com/ycwl/basic/integration/device/client/DefaultConfigClient.java b/src/main/java/com/ycwl/basic/integration/device/client/DefaultConfigClient.java index f1571c1..2163c67 100644 --- a/src/main/java/com/ycwl/basic/integration/device/client/DefaultConfigClient.java +++ b/src/main/java/com/ycwl/basic/integration/device/client/DefaultConfigClient.java @@ -18,8 +18,8 @@ public interface DefaultConfigClient { * 获取默认配置列表 */ @GetMapping - PageResponse listDefaultConfigs(@RequestParam(value = "page", defaultValue = "1") int page, - @RequestParam(value = "pageSize", defaultValue = "10") int pageSize); + CommonResponse> listDefaultConfigs(@RequestParam(value = "page", defaultValue = "1") int page, + @RequestParam(value = "pageSize", defaultValue = "10") int pageSize); /** * 根据配置键获取默认配置 diff --git a/src/main/java/com/ycwl/basic/integration/device/service/DefaultConfigIntegrationService.java b/src/main/java/com/ycwl/basic/integration/device/service/DefaultConfigIntegrationService.java index 3a996e7..dbe702a 100644 --- a/src/main/java/com/ycwl/basic/integration/device/service/DefaultConfigIntegrationService.java +++ b/src/main/java/com/ycwl/basic/integration/device/service/DefaultConfigIntegrationService.java @@ -35,8 +35,8 @@ public class DefaultConfigIntegrationService { SERVICE_NAME, "defaults:list:" + page + ":" + pageSize, () -> { - PageResponse response = defaultConfigClient.listDefaultConfigs(page, pageSize); - return handlePageResponse(response, "获取默认配置列表失败"); + CommonResponse> response = defaultConfigClient.listDefaultConfigs(page, pageSize); + return handleResponse(response, "获取默认配置列表失败"); }, PageResponse.class ); @@ -216,15 +216,4 @@ public class DefaultConfigIntegrationService { } return response.getData(); } - - private PageResponse handlePageResponse(PageResponse response, String errorMessage) { - if (response == null || !response.isSuccess()) { - String msg = response != null && response.getMessage() != null - ? response.getMessage() - : errorMessage; - Integer code = response != null ? response.getCode() : 5000; - throw new IntegrationException(code, msg, SERVICE_NAME); - } - return response; - } } \ No newline at end of file From d7c6ce9f402085d784509a38a5523c472907bf50 Mon Sep 17 00:00:00 2001 From: Jerry Yan <792602257@qq.com> Date: Sat, 6 Sep 2025 00:18:39 +0800 Subject: [PATCH 09/16] =?UTF-8?q?refactor(basic):=20=E9=87=8D=E6=9E=84?= =?UTF-8?q?=E6=B8=B2=E6=9F=93=E6=9C=BA=E7=9B=B8=E5=85=B3=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 移除了 RenderWorkerMapper 中的未使用的接口 - 精简了 RenderWorkerEntity 中的字段 -重构了 RenderWorkerRepository 中的缓存逻辑 - 更新了 RenderWorkerService 接口和实现类,使用新的 RenderWorkerRespVO 响应对象 - 调整了 TaskTaskServiceImpl 中的渲染机相关代码,使用新的配置管理方式 --- .../pc/RenderWorkerV2Controller.java | 302 ++++++++++++++++++ .../ycwl/basic/mapper/RenderWorkerMapper.java | 4 - .../entity/RenderWorkerEntity.java | 46 --- .../repository/RenderWorkerRepository.java | 29 -- .../basic/service/pc/RenderWorkerService.java | 7 +- .../pc/impl/RenderWorkerServiceImpl.java | 108 ++++--- .../task/impl/TaskTaskServiceImpl.java | 9 +- 7 files changed, 375 insertions(+), 130 deletions(-) create mode 100644 src/main/java/com/ycwl/basic/controller/pc/RenderWorkerV2Controller.java diff --git a/src/main/java/com/ycwl/basic/controller/pc/RenderWorkerV2Controller.java b/src/main/java/com/ycwl/basic/controller/pc/RenderWorkerV2Controller.java new file mode 100644 index 0000000..808b0b4 --- /dev/null +++ b/src/main/java/com/ycwl/basic/controller/pc/RenderWorkerV2Controller.java @@ -0,0 +1,302 @@ +package com.ycwl.basic.controller.pc; + +import com.github.pagehelper.PageInfo; +import com.ycwl.basic.model.pc.renderWorker.entity.RenderWorkerEntity; +import com.ycwl.basic.model.pc.renderWorker.req.RenderWorkerReqQuery; +import com.ycwl.basic.model.pc.renderWorker.resp.RenderWorkerRespVO; +import com.ycwl.basic.service.pc.RenderWorkerService; +import com.ycwl.basic.utils.ApiResponse; +import jakarta.validation.Valid; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.web.bind.annotation.*; + +import java.util.List; +import java.util.Map; + +/** + * 渲染机管理 V2 版本控制器 + * + * @author Claude Code + * @date 2025-09-05 + */ +@Slf4j +@RestController +@RequestMapping("/api/renderWorker/v2") +@RequiredArgsConstructor +public class RenderWorkerV2Controller { + + private final RenderWorkerService renderWorkerService; + + // ========== 渲染机基础 CRUD 操作 ========== + + /** + * 渲染机分页列表查询 + */ + @GetMapping("/") + public ApiResponse> listRenderWorkers(@RequestParam(defaultValue = "1") Integer page, + @RequestParam(defaultValue = "10") Integer pageSize, + @RequestParam(required = false) String name, + @RequestParam(required = false) String platform, + @RequestParam(required = false) Long scenicOnly, + @RequestParam(required = false) Integer testOnly, + @RequestParam(required = false) Integer online, + @RequestParam(required = false) Integer status) { + log.info("分页查询渲染机列表, page: {}, pageSize: {}, name: {}, platform: {}, scenicOnly: {}, testOnly: {}, online: {}, status: {}", + page, pageSize, name, platform, scenicOnly, testOnly, online, status); + + // 参数验证:限制pageSize最大值为100 + if (pageSize > 100) { + pageSize = 100; + } + + try { + RenderWorkerReqQuery queryReq = new RenderWorkerReqQuery(); + queryReq.setPageNum(page); + queryReq.setPageSize(pageSize); + queryReq.setName(name); + queryReq.setPlatform(platform); + queryReq.setScenicOnly(scenicOnly); + queryReq.setTestOnly(testOnly); + queryReq.setOnline(online); + queryReq.setStatus(status); + + return renderWorkerService.pageQuery(queryReq); + } catch (Exception e) { + log.error("分页查询渲染机列表失败", e); + return ApiResponse.fail("分页查询渲染机列表失败: " + e.getMessage()); + } + } + + /** + * 根据ID获取渲染机详情 + */ + @GetMapping("/{id}") + public ApiResponse getRenderWorker(@PathVariable Long id) { + try { + return renderWorkerService.detail(id); + } catch (Exception e) { + log.error("获取渲染机详情失败, id: {}", id, e); + return ApiResponse.fail("获取渲染机详情失败: " + e.getMessage()); + } + } + + /** + * 创建渲染机 + */ + @PostMapping("/") + public ApiResponse createRenderWorker(@Valid @RequestBody RenderWorkerEntity renderWorker) { + log.info("创建渲染机, name: {}, accessKey: {}, scenicOnly: {}, testOnly: {}", + renderWorker.getName(), renderWorker.getAccessKey(), renderWorker.getScenicOnly(), renderWorker.getTestOnly()); + try { + return renderWorkerService.add(renderWorker); + } catch (Exception e) { + log.error("创建渲染机失败", e); + return ApiResponse.fail("创建渲染机失败: " + e.getMessage()); + } + } + + /** + * 更新渲染机信息 + */ + @PutMapping("/{id}") + public ApiResponse updateRenderWorker(@PathVariable Long id, @Valid @RequestBody RenderWorkerEntity renderWorker) { + log.info("更新渲染机信息, id: {}", id); + try { + renderWorker.setId(id); + return renderWorkerService.update(renderWorker); + } catch (Exception e) { + log.error("更新渲染机信息失败, id: {}", id, e); + return ApiResponse.fail("更新渲染机信息失败: " + e.getMessage()); + } + } + + /** + * 删除渲染机 + */ + @DeleteMapping("/{id}") + public ApiResponse deleteRenderWorker(@PathVariable Long id) { + log.info("删除渲染机, id: {}", id); + try { + return renderWorkerService.deleteById(id); + } catch (Exception e) { + log.error("删除渲染机失败, id: {}", id, e); + return ApiResponse.fail("删除渲染机失败: " + e.getMessage()); + } + } + + // ========== 状态管理操作 ========== + + /** + * 启用渲染机 + */ + @PutMapping("/{id}/enable") + public ApiResponse enableRenderWorker(@PathVariable Long id) { + log.info("启用渲染机, id: {}", id); + try { + // 获取渲染机信息 + ApiResponse detailResponse = renderWorkerService.detail(id); + if (!detailResponse.isSuccess()) { + return ApiResponse.fail("渲染机不存在"); + } + + // 更新状态 + RenderWorkerEntity entity = new RenderWorkerEntity(); + entity.setId(id); + entity.setStatus(1); // 1表示启用 + + ApiResponse updateResponse = renderWorkerService.update(entity); + if (updateResponse.isSuccess()) { + return ApiResponse.success("渲染机启用成功"); + } else { + return ApiResponse.fail("渲染机启用失败"); + } + } catch (Exception e) { + log.error("启用渲染机失败, id: {}", id, e); + return ApiResponse.fail("启用渲染机失败: " + e.getMessage()); + } + } + + /** + * 禁用渲染机 + */ + @PutMapping("/{id}/disable") + public ApiResponse disableRenderWorker(@PathVariable Long id) { + log.info("禁用渲染机, id: {}", id); + try { + // 获取渲染机信息 + ApiResponse detailResponse = renderWorkerService.detail(id); + if (!detailResponse.isSuccess()) { + return ApiResponse.fail("渲染机不存在"); + } + + // 更新状态 + RenderWorkerEntity entity = new RenderWorkerEntity(); + entity.setId(id); + entity.setStatus(0); // 0表示禁用 + + ApiResponse updateResponse = renderWorkerService.update(entity); + if (updateResponse.isSuccess()) { + return ApiResponse.success("渲染机禁用成功"); + } else { + return ApiResponse.fail("渲染机禁用失败"); + } + } catch (Exception e) { + log.error("禁用渲染机失败, id: {}", id, e); + return ApiResponse.fail("禁用渲染机失败: " + e.getMessage()); + } + } + + // ========== 配置管理操作 ========== + // 注意:以下配置管理方法需要根据实际的RenderWorker配置服务进行调整 + // 目前暂时保留接口结构,等待配置相关服务的具体实现 + + /** + * 获取渲染机配置列表 + */ + @GetMapping("/{id}/config") + public ApiResponse>> getRenderWorkerConfigs(@PathVariable Long id) { + log.info("获取渲染机配置列表, renderWorkerId: {}", id); + try { + // TODO: 需要实现RenderWorker配置服务 + return ApiResponse.fail("配置管理功能待实现"); + } catch (Exception e) { + log.error("获取渲染机配置列表失败, renderWorkerId: {}", id, e); + return ApiResponse.fail("获取渲染机配置列表失败: " + e.getMessage()); + } + } + + /** + * 获取渲染机扁平化配置 + */ + @GetMapping("/{id}/flat-config") + public ApiResponse> getRenderWorkerFlatConfig(@PathVariable Long id) { + log.info("获取渲染机扁平化配置, renderWorkerId: {}", id); + try { + // TODO: 需要实现RenderWorker配置服务 + return ApiResponse.fail("配置管理功能待实现"); + } catch (Exception e) { + log.error("获取渲染机扁平化配置失败, renderWorkerId: {}", id, e); + return ApiResponse.fail("获取渲染机扁平化配置失败: " + e.getMessage()); + } + } + + /** + * 根据配置键获取配置 + */ + @GetMapping("/{id}/config/{configKey}") + public ApiResponse> getRenderWorkerConfigByKey(@PathVariable Long id, + @PathVariable String configKey) { + log.info("根据键获取渲染机配置, renderWorkerId: {}, configKey: {}", id, configKey); + try { + // TODO: 需要实现RenderWorker配置服务 + return ApiResponse.fail("配置管理功能待实现"); + } catch (Exception e) { + log.error("根据键获取渲染机配置失败, renderWorkerId: {}, configKey: {}", id, configKey, e); + return ApiResponse.fail("根据键获取渲染机配置失败: " + e.getMessage()); + } + } + + /** + * 创建渲染机配置 + */ + @PostMapping("/{id}/config") + public ApiResponse> createRenderWorkerConfig(@PathVariable Long id, + @Valid @RequestBody Map request) { + log.info("创建渲染机配置, renderWorkerId: {}", id); + try { + // TODO: 需要实现RenderWorker配置服务 + return ApiResponse.fail("配置管理功能待实现"); + } catch (Exception e) { + log.error("创建渲染机配置失败, renderWorkerId: {}", id, e); + return ApiResponse.fail("创建渲染机配置失败: " + e.getMessage()); + } + } + + /** + * 批量创建/更新渲染机配置 + */ + @PostMapping("/{id}/config/batch") + public ApiResponse> batchUpdateRenderWorkerConfig(@PathVariable Long id, + @Valid @RequestBody Map request) { + log.info("批量更新渲染机配置, renderWorkerId: {}", id); + try { + // TODO: 需要实现RenderWorker配置服务 + return ApiResponse.fail("配置管理功能待实现"); + } catch (Exception e) { + log.error("批量更新渲染机配置失败, renderWorkerId: {}", id, e); + return ApiResponse.fail("批量更新渲染机配置失败: " + e.getMessage()); + } + } + + /** + * 更新渲染机配置 + */ + @PutMapping("/{id}/config/{configId}") + public ApiResponse updateRenderWorkerConfig(@PathVariable Long id, @PathVariable Long configId, + @Valid @RequestBody Map request) { + log.info("更新渲染机配置, renderWorkerId: {}, configId: {}", id, configId); + try { + // TODO: 需要实现RenderWorker配置服务 + return ApiResponse.fail("配置管理功能待实现"); + } catch (Exception e) { + log.error("更新渲染机配置失败, renderWorkerId: {}, configId: {}", id, configId, e); + return ApiResponse.fail("更新渲染机配置失败: " + e.getMessage()); + } + } + + /** + * 删除渲染机配置 + */ + @DeleteMapping("/{id}/config/{configId}") + public ApiResponse deleteRenderWorkerConfig(@PathVariable Long id, @PathVariable Long configId) { + log.info("删除渲染机配置, renderWorkerId: {}, configId: {}", id, configId); + try { + // TODO: 需要实现RenderWorker配置服务 + return ApiResponse.fail("配置管理功能待实现"); + } catch (Exception e) { + log.error("删除渲染机配置失败, renderWorkerId: {}, configId: {}", id, configId, e); + return ApiResponse.fail("删除渲染机配置失败: " + e.getMessage()); + } + } +} \ No newline at end of file diff --git a/src/main/java/com/ycwl/basic/mapper/RenderWorkerMapper.java b/src/main/java/com/ycwl/basic/mapper/RenderWorkerMapper.java index d27ea7a..b74da68 100644 --- a/src/main/java/com/ycwl/basic/mapper/RenderWorkerMapper.java +++ b/src/main/java/com/ycwl/basic/mapper/RenderWorkerMapper.java @@ -14,13 +14,9 @@ import java.util.List; @Mapper public interface RenderWorkerMapper { List list(RenderWorkerReqQuery renderWorkerReqQuery); - RenderWorkerEntity getById(Long id); int add(RenderWorkerEntity renderWorker); int deleteById(Long id); int update(RenderWorkerEntity renderWorker); int updateStatus(Long id); - RenderWorkerEntity findByAccessKey(String accessKey); - - int updateHost(Long id, RenderWorkerEntity status); } diff --git a/src/main/java/com/ycwl/basic/model/pc/renderWorker/entity/RenderWorkerEntity.java b/src/main/java/com/ycwl/basic/model/pc/renderWorker/entity/RenderWorkerEntity.java index 627ff63..d9917ae 100644 --- a/src/main/java/com/ycwl/basic/model/pc/renderWorker/entity/RenderWorkerEntity.java +++ b/src/main/java/com/ycwl/basic/model/pc/renderWorker/entity/RenderWorkerEntity.java @@ -22,42 +22,10 @@ public class RenderWorkerEntity { * 渲染机名称 */ private String name; - /** - * 系统 - */ - private String platform; - /** - * 运行环境 - */ - private String runtimeVersion; - /** - * 版本 - */ - private String version; /** * 访问秘钥 */ private String accessKey; - /** - * cpu数量 - */ - private Integer cpuCount; - /** - * cpu使用率 - */ - private BigDecimal cpuUsage; - /** - * 内存总量,MB - */ - private BigDecimal memoryTotal; - /** - * 内存余量,MB - */ - private BigDecimal memoryAvailable; - /** - * 支持的功能,逗号隔开 - */ - private String supportFeature; /** * 是否仅用于指定景区,空或0不适用,否则为景区ID */ @@ -66,24 +34,10 @@ public class RenderWorkerEntity { * 是否仅用于测试,0不是,1是 */ private Integer testOnly; - /** - * 是否在线,0不在,1在 - */ - private Integer online; /** * 状态,0禁用,1启用 */ private Integer status; private Date createAt; private Date updateAt; - - - /** - * 存储类型 - */ - private StorageType storeType; - /** - * 存储配置 - */ - private String storeConfigJson; } diff --git a/src/main/java/com/ycwl/basic/repository/RenderWorkerRepository.java b/src/main/java/com/ycwl/basic/repository/RenderWorkerRepository.java index 0155207..5f6661c 100644 --- a/src/main/java/com/ycwl/basic/repository/RenderWorkerRepository.java +++ b/src/main/java/com/ycwl/basic/repository/RenderWorkerRepository.java @@ -1,7 +1,6 @@ package com.ycwl.basic.repository; import com.ycwl.basic.utils.JacksonUtil; -import com.ycwl.basic.mapper.RenderWorkerMapper; import com.ycwl.basic.model.pc.renderWorker.entity.RenderWorkerEntity; import com.ycwl.basic.model.task.req.ClientStatusReqVo; import com.ycwl.basic.integration.render.dto.worker.RenderWorkerV2DTO; @@ -25,11 +24,7 @@ import java.util.concurrent.TimeUnit; public class RenderWorkerRepository { @Autowired private RedisTemplate redisTemplate; - public static final String RENDER_WORKER_CACHE_KEY = "render_worker:%s"; public static final String RENDER_WORKER_STATUS_CACHE_KEY = "render_worker:host_status:%s"; - public static final String RENDER_WORKER_CONFIG_CACHE_KEY = "render_worker:%s:config"; - @Autowired - private RenderWorkerMapper mapper; @Autowired private RenderWorkerIntegrationService renderWorkerIntegrationService; @@ -61,21 +56,6 @@ public class RenderWorkerRepository { return; } status.setUpdateAt(new Date()); - RenderWorkerEntity worker = new RenderWorkerEntity(); - worker.setCpuCount(status.getCpu_count()); - worker.setCpuUsage(status.getCpu_usage()); - // 上报的是字节,存储的是兆 - worker.setMemoryAvailable(status.getMemory_available().divide(BigDecimal.valueOf(1024 * 1024), RoundingMode.CEILING)); - worker.setMemoryTotal(status.getMemory_total().divide(BigDecimal.valueOf(1024 * 1024), RoundingMode.CEILING)); - - worker.setPlatform(status.getPlatform()); - worker.setRuntimeVersion(status.getRuntime_version()); - worker.setSupportFeature(String.join(",", status.getSupport_feature())); - worker.setVersion(status.getVersion()); - worker.setUpdateAt(status.getUpdateAt()); - if (!redisTemplate.hasKey(key)) { - mapper.updateHost(id, worker); - } redisTemplate.opsForValue().set(key, JacksonUtil.toJSONString(status), 1, TimeUnit.HOURS); } @@ -88,15 +68,6 @@ public class RenderWorkerRepository { return null; } - public void clearCache(Long id) { - RenderWorkerEntity worker = getWorker(id); - redisTemplate.delete(String.format(RENDER_WORKER_CACHE_KEY, id)); - if (worker != null) { - redisTemplate.delete(String.format(RENDER_WORKER_CACHE_KEY, worker.getAccessKey())); - } - redisTemplate.delete(String.format(RENDER_WORKER_STATUS_CACHE_KEY, id)); - } - private RenderWorkerEntity convertToEntity(RenderWorkerV2DTO dto) { if (dto == null) { return null; diff --git a/src/main/java/com/ycwl/basic/service/pc/RenderWorkerService.java b/src/main/java/com/ycwl/basic/service/pc/RenderWorkerService.java index ffd6c13..21f03fa 100644 --- a/src/main/java/com/ycwl/basic/service/pc/RenderWorkerService.java +++ b/src/main/java/com/ycwl/basic/service/pc/RenderWorkerService.java @@ -3,6 +3,7 @@ package com.ycwl.basic.service.pc; import com.github.pagehelper.PageInfo; import com.ycwl.basic.model.pc.renderWorker.entity.RenderWorkerEntity; import com.ycwl.basic.model.pc.renderWorker.req.RenderWorkerReqQuery; +import com.ycwl.basic.model.pc.renderWorker.resp.RenderWorkerRespVO; import com.ycwl.basic.utils.ApiResponse; import java.util.List; @@ -12,9 +13,9 @@ import java.util.List; * @Date:2024/12/3 15:07 */ public interface RenderWorkerService { - ApiResponse> pageQuery(RenderWorkerReqQuery renderWorkerReqQuery); - ApiResponse> list(RenderWorkerReqQuery renderWorkerReqQuery); - ApiResponse detail(Long id); + ApiResponse> pageQuery(RenderWorkerReqQuery renderWorkerReqQuery); + ApiResponse> list(RenderWorkerReqQuery renderWorkerReqQuery); + ApiResponse detail(Long id); ApiResponse add(RenderWorkerEntity renderWorker); ApiResponse deleteById(Long id); ApiResponse update(RenderWorkerEntity renderWorker); diff --git a/src/main/java/com/ycwl/basic/service/pc/impl/RenderWorkerServiceImpl.java b/src/main/java/com/ycwl/basic/service/pc/impl/RenderWorkerServiceImpl.java index 322b948..aadcb24 100644 --- a/src/main/java/com/ycwl/basic/service/pc/impl/RenderWorkerServiceImpl.java +++ b/src/main/java/com/ycwl/basic/service/pc/impl/RenderWorkerServiceImpl.java @@ -5,6 +5,7 @@ import com.github.pagehelper.PageInfo; import com.ycwl.basic.mapper.RenderWorkerMapper; import com.ycwl.basic.model.pc.renderWorker.entity.RenderWorkerEntity; import com.ycwl.basic.model.pc.renderWorker.req.RenderWorkerReqQuery; +import com.ycwl.basic.model.pc.renderWorker.resp.RenderWorkerRespVO; import com.ycwl.basic.model.task.req.ClientStatusReqVo; import com.ycwl.basic.repository.RenderWorkerRepository; import com.ycwl.basic.service.pc.RenderWorkerService; @@ -31,72 +32,96 @@ public class RenderWorkerServiceImpl implements RenderWorkerService { private RenderWorkerRepository renderWorkerRepository; @Override - public ApiResponse> pageQuery(RenderWorkerReqQuery renderWorkerReqQuery) { + public ApiResponse> pageQuery(RenderWorkerReqQuery renderWorkerReqQuery) { PageHelper.startPage(renderWorkerReqQuery.getPageNum(), renderWorkerReqQuery.getPageSize()); List list = renderWorkerMapper.list(renderWorkerReqQuery); - list.forEach(worker -> { + List workerList = list.stream().map(worker -> { + RenderWorkerRespVO resp = new RenderWorkerRespVO(); + resp.setId(worker.getId()); + resp.setName(worker.getName()); + resp.setAccessKey(worker.getAccessKey()); + resp.setStatus(worker.getStatus()); + resp.setCreateAt(worker.getCreateAt()); + resp.setUpdateAt(worker.getUpdateAt()); ClientStatusReqVo clientStatus = renderWorkerRepository.getWorkerHostStatus(worker.getId()); if (clientStatus == null) { - return; + return resp; } - worker.setCpuCount(clientStatus.getCpu_count()); - worker.setCpuUsage(clientStatus.getCpu_usage()); + resp.setCpuCount(clientStatus.getCpu_count()); + resp.setCpuUsage(clientStatus.getCpu_usage()); // 上报的是字节,存储的是兆 - worker.setMemoryAvailable(clientStatus.getMemory_available().divide(BigDecimal.valueOf(1024 * 1024), RoundingMode.CEILING)); - worker.setMemoryTotal(clientStatus.getMemory_total().divide(BigDecimal.valueOf(1024 * 1024), RoundingMode.CEILING)); + resp.setMemoryAvailable(clientStatus.getMemory_available().divide(BigDecimal.valueOf(1024 * 1024), RoundingMode.CEILING)); + resp.setMemoryTotal(clientStatus.getMemory_total().divide(BigDecimal.valueOf(1024 * 1024), RoundingMode.CEILING)); - worker.setPlatform(clientStatus.getPlatform()); - worker.setRuntimeVersion(clientStatus.getRuntime_version()); - worker.setSupportFeature(String.join(",", clientStatus.getSupport_feature())); - worker.setVersion(clientStatus.getVersion()); - worker.setUpdateAt(clientStatus.getUpdateAt()); - }); - PageInfo pageInfo = new PageInfo<>(list); + resp.setPlatform(clientStatus.getPlatform()); + resp.setRuntimeVersion(clientStatus.getRuntime_version()); + resp.setSupportFeature(String.join(",", clientStatus.getSupport_feature())); + resp.setVersion(clientStatus.getVersion()); + resp.setUpdateAt(clientStatus.getUpdateAt()); + return resp; + }).toList(); + PageInfo pageInfo = new PageInfo<>(workerList); return ApiResponse.success(pageInfo); } @Override - public ApiResponse> list(RenderWorkerReqQuery renderWorkerReqQuery) { + public ApiResponse> list(RenderWorkerReqQuery renderWorkerReqQuery) { List list = renderWorkerMapper.list(renderWorkerReqQuery); - list.forEach(worker -> { + List workerList = list.stream().map(worker -> { + RenderWorkerRespVO resp = new RenderWorkerRespVO(); + resp.setId(worker.getId()); + resp.setName(worker.getName()); + resp.setAccessKey(worker.getAccessKey()); + resp.setStatus(worker.getStatus()); + resp.setCreateAt(worker.getCreateAt()); + resp.setUpdateAt(worker.getUpdateAt()); ClientStatusReqVo clientStatus = renderWorkerRepository.getWorkerHostStatus(worker.getId()); if (clientStatus == null) { - return; + return resp; } - worker.setCpuCount(clientStatus.getCpu_count()); - worker.setCpuUsage(clientStatus.getCpu_usage()); + resp.setCpuCount(clientStatus.getCpu_count()); + resp.setCpuUsage(clientStatus.getCpu_usage()); // 上报的是字节,存储的是兆 - worker.setMemoryAvailable(clientStatus.getMemory_available().divide(BigDecimal.valueOf(1024 * 1024), RoundingMode.CEILING)); - worker.setMemoryTotal(clientStatus.getMemory_total().divide(BigDecimal.valueOf(1024 * 1024), RoundingMode.CEILING)); + resp.setMemoryAvailable(clientStatus.getMemory_available().divide(BigDecimal.valueOf(1024 * 1024), RoundingMode.CEILING)); + resp.setMemoryTotal(clientStatus.getMemory_total().divide(BigDecimal.valueOf(1024 * 1024), RoundingMode.CEILING)); - worker.setPlatform(clientStatus.getPlatform()); - worker.setRuntimeVersion(clientStatus.getRuntime_version()); - worker.setSupportFeature(String.join(",", clientStatus.getSupport_feature())); - worker.setVersion(clientStatus.getVersion()); - worker.setUpdateAt(clientStatus.getUpdateAt()); - }); - return ApiResponse.success(list); + resp.setPlatform(clientStatus.getPlatform()); + resp.setRuntimeVersion(clientStatus.getRuntime_version()); + resp.setSupportFeature(String.join(",", clientStatus.getSupport_feature())); + resp.setVersion(clientStatus.getVersion()); + resp.setUpdateAt(clientStatus.getUpdateAt()); + return resp; + }).toList(); + return ApiResponse.success(workerList); } @Override - public ApiResponse detail(Long id) { - RenderWorkerEntity worker = renderWorkerMapper.getById(id); + public ApiResponse detail(Long id) { + RenderWorkerEntity worker = renderWorkerRepository.getWorker(id); + + RenderWorkerRespVO resp = new RenderWorkerRespVO(); + resp.setId(worker.getId()); + resp.setName(worker.getName()); + resp.setAccessKey(worker.getAccessKey()); + resp.setStatus(worker.getStatus()); + resp.setCreateAt(worker.getCreateAt()); + resp.setUpdateAt(worker.getUpdateAt()); ClientStatusReqVo clientStatus = renderWorkerRepository.getWorkerHostStatus(worker.getId()); if (clientStatus != null) { - worker.setCpuCount(clientStatus.getCpu_count()); - worker.setCpuUsage(clientStatus.getCpu_usage()); + resp.setCpuCount(clientStatus.getCpu_count()); + resp.setCpuUsage(clientStatus.getCpu_usage()); // 上报的是字节,存储的是兆 - worker.setMemoryAvailable(clientStatus.getMemory_available().divide(BigDecimal.valueOf(1024 * 1024), RoundingMode.CEILING)); - worker.setMemoryTotal(clientStatus.getMemory_total().divide(BigDecimal.valueOf(1024 * 1024), RoundingMode.CEILING)); + resp.setMemoryAvailable(clientStatus.getMemory_available().divide(BigDecimal.valueOf(1024 * 1024), RoundingMode.CEILING)); + resp.setMemoryTotal(clientStatus.getMemory_total().divide(BigDecimal.valueOf(1024 * 1024), RoundingMode.CEILING)); - worker.setPlatform(clientStatus.getPlatform()); - worker.setRuntimeVersion(clientStatus.getRuntime_version()); - worker.setSupportFeature(String.join(",", clientStatus.getSupport_feature())); - worker.setVersion(clientStatus.getVersion()); - worker.setUpdateAt(clientStatus.getUpdateAt()); + resp.setPlatform(clientStatus.getPlatform()); + resp.setRuntimeVersion(clientStatus.getRuntime_version()); + resp.setSupportFeature(String.join(",", clientStatus.getSupport_feature())); + resp.setVersion(clientStatus.getVersion()); + resp.setUpdateAt(clientStatus.getUpdateAt()); } - return ApiResponse.success(worker); + return ApiResponse.success(resp); } @Override @@ -116,13 +141,11 @@ public class RenderWorkerServiceImpl implements RenderWorkerService { @Override public ApiResponse deleteById(Long id) { - renderWorkerRepository.clearCache(id); return ApiResponse.success(renderWorkerMapper.deleteById(id)); } @Override public ApiResponse update(RenderWorkerEntity renderWorker) { - renderWorkerRepository.clearCache(renderWorker.getId()); int update = renderWorkerMapper.update(renderWorker); if (update == 0) { return ApiResponse.fail("渲染机修改失败"); @@ -133,7 +156,6 @@ public class RenderWorkerServiceImpl implements RenderWorkerService { @Override public ApiResponse updateStatus(Long id) { - renderWorkerRepository.clearCache(id); return ApiResponse.success(renderWorkerMapper.updateStatus(id)); } } diff --git a/src/main/java/com/ycwl/basic/service/task/impl/TaskTaskServiceImpl.java b/src/main/java/com/ycwl/basic/service/task/impl/TaskTaskServiceImpl.java index 4043564..024a8ff 100644 --- a/src/main/java/com/ycwl/basic/service/task/impl/TaskTaskServiceImpl.java +++ b/src/main/java/com/ycwl/basic/service/task/impl/TaskTaskServiceImpl.java @@ -1,6 +1,7 @@ package com.ycwl.basic.service.task.impl; import cn.hutool.core.date.DateUtil; +import com.ycwl.basic.integration.common.manager.RenderWorkerConfigManager; import com.ycwl.basic.utils.JacksonUtil; import com.ycwl.basic.biz.OrderBiz; import com.ycwl.basic.biz.TaskStatusBiz; @@ -10,7 +11,6 @@ import com.ycwl.basic.constant.TaskConstant; import com.ycwl.basic.mapper.FaceMapper; import com.ycwl.basic.mapper.FaceSampleMapper; import com.ycwl.basic.mapper.MemberMapper; -import com.ycwl.basic.mapper.RenderWorkerMapper; import com.ycwl.basic.mapper.SourceMapper; import com.ycwl.basic.mapper.TaskMapper; import com.ycwl.basic.mapper.TemplateMapper; @@ -134,7 +134,6 @@ public class TaskTaskServiceImpl implements TaskService { if (worker == null) { return null; } - worker.setOnline(1); worker.setName(null); worker.setStatus(null); // get status @@ -174,7 +173,6 @@ public class TaskTaskServiceImpl implements TaskService { taskList.forEach(task -> { taskMapper.assignToWorker(task.getId(), worker.getId()); videoTaskRepository.clearTaskCache(task.getId()); - repository.clearCache(worker.getId()); }); } finally { lock.unlock(); @@ -540,10 +538,11 @@ public class TaskTaskServiceImpl implements TaskService { if (worker == null) { return null; } + RenderWorkerConfigManager config = repository.getWorkerConfigManager(worker.getId()); IStorageAdapter adapter; try { - adapter = StorageFactory.get(worker.getStoreType()); - adapter.loadConfig(JacksonUtil.parseObject(worker.getStoreConfigJson(), Map.class)); + adapter = StorageFactory.get(config.getString("store_type")); + adapter.loadConfig(config.getObject("store_config_json", Map.class)); } catch (Exception e) { adapter = scenicService.getScenicStorageAdapter(task.getScenicId()); } From 7696c934b12ce6f5b0a69eb5a44d7c86398ccfb5 Mon Sep 17 00:00:00 2001 From: Jerry Yan <792602257@qq.com> Date: Sun, 7 Sep 2025 14:43:36 +0800 Subject: [PATCH 10/16] =?UTF-8?q?feat(pc):=20=E9=87=8D=E6=9E=84=E6=B8=B2?= =?UTF-8?q?=E6=9F=93=E5=B7=A5=E4=BD=9C=E5=99=A8=E7=AE=A1=E7=90=86=E6=8E=A5?= =?UTF-8?q?=E5=8F=A3=E5=B9=B6=E6=B7=BB=E5=8A=A0=E9=85=8D=E7=BD=AE=E7=AE=A1?= =?UTF-8?q?=E7=90=86=E5=8A=9F=E8=83=BD-=20=E9=87=8D=E6=96=B0=E8=AE=BE?= =?UTF-8?q?=E8=AE=A1=E4=BA=86=E6=B8=B2=E6=9F=93=E5=B7=A5=E4=BD=9C=E5=99=A8?= =?UTF-8?q?=E7=AE=A1=E7=90=86=E6=8E=A5=E5=8F=A3=EF=BC=8C=E7=AE=80=E5=8C=96?= =?UTF-8?q?=E4=BA=86=E6=93=8D=E4=BD=9C=E6=B5=81=E7=A8=8B-=20=E6=B7=BB?= =?UTF-8?q?=E5=8A=A0=E4=BA=86=E6=B8=B2=E6=9F=93=E5=B7=A5=E4=BD=9C=E5=99=A8?= =?UTF-8?q?=E9=85=8D=E7=BD=AE=E7=AE=A1=E7=90=86=E7=9B=B8=E5=85=B3=E6=8E=A5?= =?UTF-8?q?=E5=8F=A3=EF=BC=8C=E5=8C=85=E6=8B=AC=E5=88=9B=E5=BB=BA=E3=80=81?= =?UTF-8?q?=E6=9B=B4=E6=96=B0=E3=80=81=E5=88=A0=E9=99=A4=E7=AD=89=E6=93=8D?= =?UTF-8?q?=E4=BD=9C=20-=20=E4=BC=98=E5=8C=96=E4=BA=86=E4=BB=A3=E7=A0=81?= =?UTF-8?q?=E7=BB=93=E6=9E=84=EF=BC=8C=E6=8F=90=E9=AB=98=E4=BA=86=E5=8F=AF?= =?UTF-8?q?=E7=BB=B4=E6=8A=A4=E6=80=A7=E5=92=8C=E5=8F=AF=E6=89=A9=E5=B1=95?= =?UTF-8?q?=E6=80=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../pc/RenderWorkerConfigV2Controller.java | 196 +++++++++++ .../pc/RenderWorkerV2Controller.java | 320 +++++------------- .../repository/RenderWorkerRepository.java | 4 +- 3 files changed, 277 insertions(+), 243 deletions(-) create mode 100644 src/main/java/com/ycwl/basic/controller/pc/RenderWorkerConfigV2Controller.java diff --git a/src/main/java/com/ycwl/basic/controller/pc/RenderWorkerConfigV2Controller.java b/src/main/java/com/ycwl/basic/controller/pc/RenderWorkerConfigV2Controller.java new file mode 100644 index 0000000..334eda1 --- /dev/null +++ b/src/main/java/com/ycwl/basic/controller/pc/RenderWorkerConfigV2Controller.java @@ -0,0 +1,196 @@ +package com.ycwl.basic.controller.pc; + +import com.ycwl.basic.integration.render.dto.config.BatchRenderWorkerConfigRequest; +import com.ycwl.basic.integration.render.dto.config.RenderWorkerConfigV2DTO; +import com.ycwl.basic.integration.render.service.RenderWorkerConfigIntegrationService; +import com.ycwl.basic.utils.ApiResponse; +import jakarta.validation.Valid; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.web.bind.annotation.*; + +import java.util.List; +import java.util.Map; + +/** + * 渲染工作器配置管理 V2 版本控制器 + * 基于 zt-render-worker 微服务标准接口实现 + * + * @author Claude Code + * @date 2025-09-06 + */ +@Slf4j +@RestController +@RequestMapping("/api/render/worker/config/v2") +@RequiredArgsConstructor +public class RenderWorkerConfigV2Controller { + + private final RenderWorkerConfigIntegrationService configIntegrationService; + + /** + * 获取工作器所有配置 + * + * @param workerId 工作器ID + * @return 工作器配置列表 + */ + @GetMapping("/{workerId}") + public ApiResponse> getWorkerConfigs(@PathVariable Long workerId) { + log.info("获取渲染工作器配置列表, workerId: {}", workerId); + + try { + List configs = configIntegrationService.getWorkerConfigs(workerId); + return ApiResponse.success(configs); + } catch (Exception e) { + log.error("获取渲染工作器配置列表失败, workerId: {}", workerId, e); + return ApiResponse.fail("获取渲染工作器配置列表失败: " + e.getMessage()); + } + } + + /** + * 获取工作器平铺配置 + * + * @param workerId 工作器ID + * @return 平铺配置Map + */ + @GetMapping("/{workerId}/flat") + public ApiResponse> getWorkerFlatConfig(@PathVariable Long workerId) { + log.info("获取渲染工作器平铺配置, workerId: {}", workerId); + + try { + Map flatConfig = configIntegrationService.getWorkerFlatConfig(workerId); + return ApiResponse.success(flatConfig); + } catch (Exception e) { + log.error("获取渲染工作器平铺配置失败, workerId: {}", workerId, e); + return ApiResponse.fail("获取渲染工作器平铺配置失败: " + e.getMessage()); + } + } + + /** + * 根据配置键获取特定配置 + * + * @param workerId 工作器ID + * @param configKey 配置键 + * @return 配置信息 + */ + @GetMapping("/{workerId}/key/{configKey}") + public ApiResponse getWorkerConfigByKey(@PathVariable Long workerId, + @PathVariable String configKey) { + log.info("根据配置键获取渲染工作器配置, workerId: {}, configKey: {}", workerId, configKey); + + try { + RenderWorkerConfigV2DTO config = configIntegrationService.getWorkerConfigByKey(workerId, configKey); + return ApiResponse.success(config); + } catch (Exception e) { + log.error("根据配置键获取渲染工作器配置失败, workerId: {}, configKey: {}", workerId, configKey, e); + return ApiResponse.fail("根据配置键获取渲染工作器配置失败: " + e.getMessage()); + } + } + + /** + * 创建工作器配置 + * + * @param workerId 工作器ID + * @param config 配置信息 + * @return 创建的配置信息 + */ + @PostMapping("/{workerId}") + public ApiResponse createWorkerConfig(@PathVariable Long workerId, + @Valid @RequestBody RenderWorkerConfigV2DTO config) { + log.info("创建渲染工作器配置, workerId: {}, configKey: {}", workerId, config.getConfigKey()); + + try { + RenderWorkerConfigV2DTO result = configIntegrationService.createWorkerConfig(workerId, config); + return ApiResponse.success(result); + } catch (Exception e) { + log.error("创建渲染工作器配置失败, workerId: {}", workerId, e); + return ApiResponse.fail("创建渲染工作器配置失败: " + e.getMessage()); + } + } + + /** + * 更新工作器配置 + * + * @param workerId 工作器ID + * @param configId 配置ID + * @param updates 更新内容 + * @return 操作结果 + */ + @PutMapping("/{workerId}/{configId}") + public ApiResponse updateWorkerConfig(@PathVariable Long workerId, + @PathVariable Long configId, + @Valid @RequestBody Map updates) { + log.info("更新渲染工作器配置, workerId: {}, configId: {}", workerId, configId); + + try { + configIntegrationService.updateWorkerConfig(workerId, configId, updates); + return ApiResponse.success(null); + } catch (Exception e) { + log.error("更新渲染工作器配置失败, workerId: {}, configId: {}", workerId, configId, e); + return ApiResponse.fail("更新渲染工作器配置失败: " + e.getMessage()); + } + } + + /** + * 删除工作器配置 + * + * @param workerId 工作器ID + * @param configId 配置ID + * @return 操作结果 + */ + @DeleteMapping("/{workerId}/{configId}") + public ApiResponse deleteWorkerConfig(@PathVariable Long workerId, + @PathVariable Long configId) { + log.info("删除渲染工作器配置, workerId: {}, configId: {}", workerId, configId); + + try { + configIntegrationService.deleteWorkerConfig(workerId, configId); + return ApiResponse.success(null); + } catch (Exception e) { + log.error("删除渲染工作器配置失败, workerId: {}, configId: {}", workerId, configId, e); + return ApiResponse.fail("删除渲染工作器配置失败: " + e.getMessage()); + } + } + + /** + * 批量更新工作器配置 + * + * @param workerId 工作器ID + * @param request 批量配置请求 + * @return 操作结果 + */ + @PostMapping("/{workerId}/batch") + public ApiResponse batchUpdateWorkerConfigs(@PathVariable Long workerId, + @Valid @RequestBody BatchRenderWorkerConfigRequest request) { + log.info("批量更新渲染工作器配置, workerId: {}, configCount: {}", + workerId, request.getConfigs() != null ? request.getConfigs().size() : 0); + + try { + configIntegrationService.batchUpdateWorkerConfigs(workerId, request); + return ApiResponse.success(null); + } catch (Exception e) { + log.error("批量更新渲染工作器配置失败, workerId: {}", workerId, e); + return ApiResponse.fail("批量更新渲染工作器配置失败: " + e.getMessage()); + } + } + + /** + * 批量平铺更新工作器配置 + * + * @param workerId 工作器ID + * @param flatConfigs 平铺配置Map + * @return 操作结果 + */ + @PostMapping("/{workerId}/flat-batch") + public ApiResponse batchFlatUpdateWorkerConfigs(@PathVariable Long workerId, + @Valid @RequestBody Map flatConfigs) { + log.info("批量平铺更新渲染工作器配置, workerId: {}, configCount: {}", workerId, flatConfigs.size()); + + try { + configIntegrationService.batchFlatUpdateWorkerConfigs(workerId, flatConfigs); + return ApiResponse.success(null); + } catch (Exception e) { + log.error("批量平铺更新渲染工作器配置失败, workerId: {}", workerId, e); + return ApiResponse.fail("批量平铺更新渲染工作器配置失败: " + e.getMessage()); + } + } +} \ No newline at end of file diff --git a/src/main/java/com/ycwl/basic/controller/pc/RenderWorkerV2Controller.java b/src/main/java/com/ycwl/basic/controller/pc/RenderWorkerV2Controller.java index 808b0b4..910478b 100644 --- a/src/main/java/com/ycwl/basic/controller/pc/RenderWorkerV2Controller.java +++ b/src/main/java/com/ycwl/basic/controller/pc/RenderWorkerV2Controller.java @@ -1,49 +1,49 @@ package com.ycwl.basic.controller.pc; -import com.github.pagehelper.PageInfo; -import com.ycwl.basic.model.pc.renderWorker.entity.RenderWorkerEntity; -import com.ycwl.basic.model.pc.renderWorker.req.RenderWorkerReqQuery; -import com.ycwl.basic.model.pc.renderWorker.resp.RenderWorkerRespVO; -import com.ycwl.basic.service.pc.RenderWorkerService; +import com.ycwl.basic.integration.common.response.PageResponse; +import com.ycwl.basic.integration.render.dto.worker.CreateRenderWorkerRequest; +import com.ycwl.basic.integration.render.dto.worker.RenderWorkerV2DTO; +import com.ycwl.basic.integration.render.dto.worker.UpdateRenderWorkerRequest; +import com.ycwl.basic.integration.render.service.RenderWorkerIntegrationService; import com.ycwl.basic.utils.ApiResponse; import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.web.bind.annotation.*; -import java.util.List; -import java.util.Map; - /** - * 渲染机管理 V2 版本控制器 + * 渲染工作器管理 V2 版本控制器 + * 基于 zt-render-worker 微服务标准接口实现 * * @author Claude Code - * @date 2025-09-05 + * @date 2025-09-06 */ @Slf4j @RestController -@RequestMapping("/api/renderWorker/v2") +@RequestMapping("/api/render/worker/v2") @RequiredArgsConstructor public class RenderWorkerV2Controller { - private final RenderWorkerService renderWorkerService; - - // ========== 渲染机基础 CRUD 操作 ========== + private final RenderWorkerIntegrationService renderWorkerIntegrationService; /** - * 渲染机分页列表查询 + * 分页查询渲染工作器列表 + * + * @param page 页码,从1开始 + * @param pageSize 每页大小,默认10,最大100 + * @param isEnabled 是否启用(0-禁用,1-启用) + * @param name 工作器名称(模糊搜索) + * @return 分页查询结果 */ - @GetMapping("/") - public ApiResponse> listRenderWorkers(@RequestParam(defaultValue = "1") Integer page, - @RequestParam(defaultValue = "10") Integer pageSize, - @RequestParam(required = false) String name, - @RequestParam(required = false) String platform, - @RequestParam(required = false) Long scenicOnly, - @RequestParam(required = false) Integer testOnly, - @RequestParam(required = false) Integer online, - @RequestParam(required = false) Integer status) { - log.info("分页查询渲染机列表, page: {}, pageSize: {}, name: {}, platform: {}, scenicOnly: {}, testOnly: {}, online: {}, status: {}", - page, pageSize, name, platform, scenicOnly, testOnly, online, status); + @GetMapping + public ApiResponse> listWorkers( + @RequestParam(defaultValue = "1") Integer page, + @RequestParam(defaultValue = "10") Integer pageSize, + @RequestParam(required = false) Integer isEnabled, + @RequestParam(required = false) String name) { + + log.info("分页查询渲染工作器列表, page: {}, pageSize: {}, isEnabled: {}, name: {}", + page, pageSize, isEnabled, name); // 参数验证:限制pageSize最大值为100 if (pageSize > 100) { @@ -51,252 +51,92 @@ public class RenderWorkerV2Controller { } try { - RenderWorkerReqQuery queryReq = new RenderWorkerReqQuery(); - queryReq.setPageNum(page); - queryReq.setPageSize(pageSize); - queryReq.setName(name); - queryReq.setPlatform(platform); - queryReq.setScenicOnly(scenicOnly); - queryReq.setTestOnly(testOnly); - queryReq.setOnline(online); - queryReq.setStatus(status); - - return renderWorkerService.pageQuery(queryReq); + PageResponse result = renderWorkerIntegrationService.listWorkers( + page, pageSize, isEnabled, name); + return ApiResponse.success(result); } catch (Exception e) { - log.error("分页查询渲染机列表失败", e); - return ApiResponse.fail("分页查询渲染机列表失败: " + e.getMessage()); + log.error("分页查询渲染工作器列表失败", e); + return ApiResponse.fail("分页查询渲染工作器列表失败: " + e.getMessage()); } } /** - * 根据ID获取渲染机详情 + * 根据ID获取渲染工作器详情 + * + * @param id 工作器ID + * @return 工作器详情 */ @GetMapping("/{id}") - public ApiResponse getRenderWorker(@PathVariable Long id) { + public ApiResponse getWorker(@PathVariable Long id) { + log.info("获取渲染工作器详情, id: {}", id); + try { - return renderWorkerService.detail(id); + RenderWorkerV2DTO worker = renderWorkerIntegrationService.getWorker(id); + return ApiResponse.success(worker); } catch (Exception e) { - log.error("获取渲染机详情失败, id: {}", id, e); - return ApiResponse.fail("获取渲染机详情失败: " + e.getMessage()); + log.error("获取渲染工作器详情失败, id: {}", id, e); + return ApiResponse.fail("获取渲染工作器详情失败: " + e.getMessage()); } } /** - * 创建渲染机 + * 创建渲染工作器 + * + * @param request 创建请求 + * @return 创建的工作器信息 */ - @PostMapping("/") - public ApiResponse createRenderWorker(@Valid @RequestBody RenderWorkerEntity renderWorker) { - log.info("创建渲染机, name: {}, accessKey: {}, scenicOnly: {}, testOnly: {}", - renderWorker.getName(), renderWorker.getAccessKey(), renderWorker.getScenicOnly(), renderWorker.getTestOnly()); + @PostMapping + public ApiResponse createWorker(@Valid @RequestBody CreateRenderWorkerRequest request) { + log.info("创建渲染工作器, name: {}, key: {}, isActive: {}", + request.getName(), request.getKey(), request.getIsActive()); + try { - return renderWorkerService.add(renderWorker); + RenderWorkerV2DTO worker = renderWorkerIntegrationService.createWorker(request); + return ApiResponse.success(worker); } catch (Exception e) { - log.error("创建渲染机失败", e); - return ApiResponse.fail("创建渲染机失败: " + e.getMessage()); + log.error("创建渲染工作器失败", e); + return ApiResponse.fail("创建渲染工作器失败: " + e.getMessage()); } } /** - * 更新渲染机信息 + * 更新渲染工作器 + * + * @param id 工作器ID + * @param request 更新请求 + * @return 操作结果 */ @PutMapping("/{id}") - public ApiResponse updateRenderWorker(@PathVariable Long id, @Valid @RequestBody RenderWorkerEntity renderWorker) { - log.info("更新渲染机信息, id: {}", id); + public ApiResponse updateWorker(@PathVariable Long id, + @Valid @RequestBody UpdateRenderWorkerRequest request) { + log.info("更新渲染工作器, id: {}, name: {}, isActive: {}", + id, request.getName(), request.getIsActive()); + try { - renderWorker.setId(id); - return renderWorkerService.update(renderWorker); + renderWorkerIntegrationService.updateWorker(id, request); + return ApiResponse.success(null); } catch (Exception e) { - log.error("更新渲染机信息失败, id: {}", id, e); - return ApiResponse.fail("更新渲染机信息失败: " + e.getMessage()); + log.error("更新渲染工作器失败, id: {}", id, e); + return ApiResponse.fail("更新渲染工作器失败: " + e.getMessage()); } } /** - * 删除渲染机 + * 删除渲染工作器 + * + * @param id 工作器ID + * @return 操作结果 */ @DeleteMapping("/{id}") - public ApiResponse deleteRenderWorker(@PathVariable Long id) { - log.info("删除渲染机, id: {}", id); + public ApiResponse deleteWorker(@PathVariable Long id) { + log.info("删除渲染工作器, id: {}", id); + try { - return renderWorkerService.deleteById(id); + renderWorkerIntegrationService.deleteWorker(id); + return ApiResponse.success(null); } catch (Exception e) { - log.error("删除渲染机失败, id: {}", id, e); - return ApiResponse.fail("删除渲染机失败: " + e.getMessage()); - } - } - - // ========== 状态管理操作 ========== - - /** - * 启用渲染机 - */ - @PutMapping("/{id}/enable") - public ApiResponse enableRenderWorker(@PathVariable Long id) { - log.info("启用渲染机, id: {}", id); - try { - // 获取渲染机信息 - ApiResponse detailResponse = renderWorkerService.detail(id); - if (!detailResponse.isSuccess()) { - return ApiResponse.fail("渲染机不存在"); - } - - // 更新状态 - RenderWorkerEntity entity = new RenderWorkerEntity(); - entity.setId(id); - entity.setStatus(1); // 1表示启用 - - ApiResponse updateResponse = renderWorkerService.update(entity); - if (updateResponse.isSuccess()) { - return ApiResponse.success("渲染机启用成功"); - } else { - return ApiResponse.fail("渲染机启用失败"); - } - } catch (Exception e) { - log.error("启用渲染机失败, id: {}", id, e); - return ApiResponse.fail("启用渲染机失败: " + e.getMessage()); - } - } - - /** - * 禁用渲染机 - */ - @PutMapping("/{id}/disable") - public ApiResponse disableRenderWorker(@PathVariable Long id) { - log.info("禁用渲染机, id: {}", id); - try { - // 获取渲染机信息 - ApiResponse detailResponse = renderWorkerService.detail(id); - if (!detailResponse.isSuccess()) { - return ApiResponse.fail("渲染机不存在"); - } - - // 更新状态 - RenderWorkerEntity entity = new RenderWorkerEntity(); - entity.setId(id); - entity.setStatus(0); // 0表示禁用 - - ApiResponse updateResponse = renderWorkerService.update(entity); - if (updateResponse.isSuccess()) { - return ApiResponse.success("渲染机禁用成功"); - } else { - return ApiResponse.fail("渲染机禁用失败"); - } - } catch (Exception e) { - log.error("禁用渲染机失败, id: {}", id, e); - return ApiResponse.fail("禁用渲染机失败: " + e.getMessage()); - } - } - - // ========== 配置管理操作 ========== - // 注意:以下配置管理方法需要根据实际的RenderWorker配置服务进行调整 - // 目前暂时保留接口结构,等待配置相关服务的具体实现 - - /** - * 获取渲染机配置列表 - */ - @GetMapping("/{id}/config") - public ApiResponse>> getRenderWorkerConfigs(@PathVariable Long id) { - log.info("获取渲染机配置列表, renderWorkerId: {}", id); - try { - // TODO: 需要实现RenderWorker配置服务 - return ApiResponse.fail("配置管理功能待实现"); - } catch (Exception e) { - log.error("获取渲染机配置列表失败, renderWorkerId: {}", id, e); - return ApiResponse.fail("获取渲染机配置列表失败: " + e.getMessage()); - } - } - - /** - * 获取渲染机扁平化配置 - */ - @GetMapping("/{id}/flat-config") - public ApiResponse> getRenderWorkerFlatConfig(@PathVariable Long id) { - log.info("获取渲染机扁平化配置, renderWorkerId: {}", id); - try { - // TODO: 需要实现RenderWorker配置服务 - return ApiResponse.fail("配置管理功能待实现"); - } catch (Exception e) { - log.error("获取渲染机扁平化配置失败, renderWorkerId: {}", id, e); - return ApiResponse.fail("获取渲染机扁平化配置失败: " + e.getMessage()); - } - } - - /** - * 根据配置键获取配置 - */ - @GetMapping("/{id}/config/{configKey}") - public ApiResponse> getRenderWorkerConfigByKey(@PathVariable Long id, - @PathVariable String configKey) { - log.info("根据键获取渲染机配置, renderWorkerId: {}, configKey: {}", id, configKey); - try { - // TODO: 需要实现RenderWorker配置服务 - return ApiResponse.fail("配置管理功能待实现"); - } catch (Exception e) { - log.error("根据键获取渲染机配置失败, renderWorkerId: {}, configKey: {}", id, configKey, e); - return ApiResponse.fail("根据键获取渲染机配置失败: " + e.getMessage()); - } - } - - /** - * 创建渲染机配置 - */ - @PostMapping("/{id}/config") - public ApiResponse> createRenderWorkerConfig(@PathVariable Long id, - @Valid @RequestBody Map request) { - log.info("创建渲染机配置, renderWorkerId: {}", id); - try { - // TODO: 需要实现RenderWorker配置服务 - return ApiResponse.fail("配置管理功能待实现"); - } catch (Exception e) { - log.error("创建渲染机配置失败, renderWorkerId: {}", id, e); - return ApiResponse.fail("创建渲染机配置失败: " + e.getMessage()); - } - } - - /** - * 批量创建/更新渲染机配置 - */ - @PostMapping("/{id}/config/batch") - public ApiResponse> batchUpdateRenderWorkerConfig(@PathVariable Long id, - @Valid @RequestBody Map request) { - log.info("批量更新渲染机配置, renderWorkerId: {}", id); - try { - // TODO: 需要实现RenderWorker配置服务 - return ApiResponse.fail("配置管理功能待实现"); - } catch (Exception e) { - log.error("批量更新渲染机配置失败, renderWorkerId: {}", id, e); - return ApiResponse.fail("批量更新渲染机配置失败: " + e.getMessage()); - } - } - - /** - * 更新渲染机配置 - */ - @PutMapping("/{id}/config/{configId}") - public ApiResponse updateRenderWorkerConfig(@PathVariable Long id, @PathVariable Long configId, - @Valid @RequestBody Map request) { - log.info("更新渲染机配置, renderWorkerId: {}, configId: {}", id, configId); - try { - // TODO: 需要实现RenderWorker配置服务 - return ApiResponse.fail("配置管理功能待实现"); - } catch (Exception e) { - log.error("更新渲染机配置失败, renderWorkerId: {}, configId: {}", id, configId, e); - return ApiResponse.fail("更新渲染机配置失败: " + e.getMessage()); - } - } - - /** - * 删除渲染机配置 - */ - @DeleteMapping("/{id}/config/{configId}") - public ApiResponse deleteRenderWorkerConfig(@PathVariable Long id, @PathVariable Long configId) { - log.info("删除渲染机配置, renderWorkerId: {}, configId: {}", id, configId); - try { - // TODO: 需要实现RenderWorker配置服务 - return ApiResponse.fail("配置管理功能待实现"); - } catch (Exception e) { - log.error("删除渲染机配置失败, renderWorkerId: {}, configId: {}", id, configId, e); - return ApiResponse.fail("删除渲染机配置失败: " + e.getMessage()); + log.error("删除渲染工作器失败, id: {}", id, e); + return ApiResponse.fail("删除渲染工作器失败: " + e.getMessage()); } } } \ No newline at end of file diff --git a/src/main/java/com/ycwl/basic/repository/RenderWorkerRepository.java b/src/main/java/com/ycwl/basic/repository/RenderWorkerRepository.java index 5f6661c..d5ffe88 100644 --- a/src/main/java/com/ycwl/basic/repository/RenderWorkerRepository.java +++ b/src/main/java/com/ycwl/basic/repository/RenderWorkerRepository.java @@ -13,8 +13,6 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.stereotype.Component; -import java.math.BigDecimal; -import java.math.RoundingMode; import java.util.Date; import java.util.List; import java.util.concurrent.TimeUnit; @@ -25,7 +23,7 @@ public class RenderWorkerRepository { @Autowired private RedisTemplate redisTemplate; public static final String RENDER_WORKER_STATUS_CACHE_KEY = "render_worker:host_status:%s"; - + @Autowired private RenderWorkerIntegrationService renderWorkerIntegrationService; From e574f4917732f1d8498ae2eb348997a132f1e104 Mon Sep 17 00:00:00 2001 From: Jerry Yan <792602257@qq.com> Date: Sat, 6 Sep 2025 15:35:42 +0800 Subject: [PATCH 11/16] =?UTF-8?q?refactor(integration):=20=E9=87=8D?= =?UTF-8?q?=E6=9E=84=E8=AE=BE=E5=A4=87=E5=92=8C=E6=9C=8D=E5=8A=A1=E9=85=8D?= =?UTF-8?q?=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 修改 DefaultConfigIntegrationService 类名以更准确地反映其功能 - 移除不必要的导入和注解 - 统一命名规范 # Conflicts: # src/main/java/com/ycwl/basic/integration/questionnaire/config/QuestionnaireIntegrationConfig.java --- .../controller/pc/DefaultConfigController.java | 14 +++++++------- .../example/DefaultConfigIntegrationExample.java | 4 ++-- ... => DeviceDefaultConfigIntegrationService.java} | 3 +-- .../config/QuestionnaireIntegrationConfig.java | 0 .../config/RenderWorkerIntegrationConfig.java | 2 -- ... => ScenicDefaultConfigIntegrationService.java} | 2 +- 6 files changed, 11 insertions(+), 14 deletions(-) rename src/main/java/com/ycwl/basic/integration/device/service/{DefaultConfigIntegrationService.java => DeviceDefaultConfigIntegrationService.java} (99%) create mode 100644 src/main/java/com/ycwl/basic/integration/questionnaire/config/QuestionnaireIntegrationConfig.java rename src/main/java/com/ycwl/basic/integration/scenic/service/{DefaultConfigIntegrationService.java => ScenicDefaultConfigIntegrationService.java} (97%) diff --git a/src/main/java/com/ycwl/basic/controller/pc/DefaultConfigController.java b/src/main/java/com/ycwl/basic/controller/pc/DefaultConfigController.java index 8ddfe5c..f301993 100644 --- a/src/main/java/com/ycwl/basic/controller/pc/DefaultConfigController.java +++ b/src/main/java/com/ycwl/basic/controller/pc/DefaultConfigController.java @@ -1,7 +1,7 @@ package com.ycwl.basic.controller.pc; import com.ycwl.basic.integration.scenic.dto.config.DefaultConfigDTO; -import com.ycwl.basic.integration.scenic.service.DefaultConfigIntegrationService; +import com.ycwl.basic.integration.scenic.service.ScenicDefaultConfigIntegrationService; import com.ycwl.basic.utils.ApiConst; import com.ycwl.basic.utils.ApiResponse; import lombok.RequiredArgsConstructor; @@ -20,7 +20,7 @@ import java.util.List; @RequiredArgsConstructor public class DefaultConfigController { - private final DefaultConfigIntegrationService defaultConfigIntegrationService; + private final ScenicDefaultConfigIntegrationService scenicDefaultConfigIntegrationService; /** * 获取默认配置列表 @@ -29,7 +29,7 @@ public class DefaultConfigController { public ApiResponse> listDefaultConfigs() { log.info("获取默认配置列表"); try { - List configs = defaultConfigIntegrationService.listDefaultConfigs(); + List configs = scenicDefaultConfigIntegrationService.listDefaultConfigs(); return ApiResponse.success(configs); } catch (Exception e) { log.error("获取默认配置列表失败", e); @@ -44,7 +44,7 @@ public class DefaultConfigController { public ApiResponse getDefaultConfig(@PathVariable String configKey) { log.info("获取默认配置, configKey: {}", configKey); try { - DefaultConfigDTO config = defaultConfigIntegrationService.getDefaultConfig(configKey); + DefaultConfigDTO config = scenicDefaultConfigIntegrationService.getDefaultConfig(configKey); return ApiResponse.success(config); } catch (Exception e) { log.error("获取默认配置失败, configKey: {}", configKey, e); @@ -59,7 +59,7 @@ public class DefaultConfigController { public ApiResponse createDefaultConfig(@RequestBody DefaultConfigDTO request) { log.info("创建默认配置, configKey: {}", request.getConfigKey()); try { - DefaultConfigDTO config = defaultConfigIntegrationService.createDefaultConfig(request); + DefaultConfigDTO config = scenicDefaultConfigIntegrationService.createDefaultConfig(request); return ApiResponse.success(config); } catch (Exception e) { log.error("创建默认配置失败, configKey: {}", request.getConfigKey(), e); @@ -75,7 +75,7 @@ public class DefaultConfigController { @RequestBody DefaultConfigDTO request) { log.info("更新默认配置, configKey: {}", configKey); try { - DefaultConfigDTO config = defaultConfigIntegrationService.updateDefaultConfig(configKey, request); + DefaultConfigDTO config = scenicDefaultConfigIntegrationService.updateDefaultConfig(configKey, request); return ApiResponse.success(config); } catch (Exception e) { log.error("更新默认配置失败, configKey: {}", configKey, e); @@ -90,7 +90,7 @@ public class DefaultConfigController { public ApiResponse deleteDefaultConfig(@PathVariable String configKey) { log.info("删除默认配置, configKey: {}", configKey); try { - defaultConfigIntegrationService.deleteDefaultConfig(configKey); + scenicDefaultConfigIntegrationService.deleteDefaultConfig(configKey); return ApiResponse.buildResponse(ApiConst.Code.CODE_SUCCESS.code(), null, "删除成功"); } catch (Exception e) { log.error("删除默认配置失败, configKey: {}", configKey, e); diff --git a/src/main/java/com/ycwl/basic/integration/device/example/DefaultConfigIntegrationExample.java b/src/main/java/com/ycwl/basic/integration/device/example/DefaultConfigIntegrationExample.java index b17410e..75fc610 100644 --- a/src/main/java/com/ycwl/basic/integration/device/example/DefaultConfigIntegrationExample.java +++ b/src/main/java/com/ycwl/basic/integration/device/example/DefaultConfigIntegrationExample.java @@ -2,7 +2,7 @@ package com.ycwl.basic.integration.device.example; import com.ycwl.basic.integration.common.response.PageResponse; import com.ycwl.basic.integration.device.dto.defaults.*; -import com.ycwl.basic.integration.device.service.DefaultConfigIntegrationService; +import com.ycwl.basic.integration.device.service.DeviceDefaultConfigIntegrationService; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.boot.CommandLineRunner; @@ -23,7 +23,7 @@ import java.util.Map; @ConditionalOnProperty(name = "integration.device.example.default-config.enabled", havingValue = "true") public class DefaultConfigIntegrationExample implements CommandLineRunner { - private final DefaultConfigIntegrationService defaultConfigService; + private final DeviceDefaultConfigIntegrationService defaultConfigService; @Override public void run(String... args) throws Exception { diff --git a/src/main/java/com/ycwl/basic/integration/device/service/DefaultConfigIntegrationService.java b/src/main/java/com/ycwl/basic/integration/device/service/DeviceDefaultConfigIntegrationService.java similarity index 99% rename from src/main/java/com/ycwl/basic/integration/device/service/DefaultConfigIntegrationService.java rename to src/main/java/com/ycwl/basic/integration/device/service/DeviceDefaultConfigIntegrationService.java index dbe702a..0c49612 100644 --- a/src/main/java/com/ycwl/basic/integration/device/service/DefaultConfigIntegrationService.java +++ b/src/main/java/com/ycwl/basic/integration/device/service/DeviceDefaultConfigIntegrationService.java @@ -11,7 +11,6 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import java.util.ArrayList; -import java.util.HashMap; import java.util.Map; /** @@ -20,7 +19,7 @@ import java.util.Map; @Slf4j @Service @RequiredArgsConstructor -public class DefaultConfigIntegrationService { +public class DeviceDefaultConfigIntegrationService { private final DefaultConfigClient defaultConfigClient; private final IntegrationFallbackService fallbackService; diff --git a/src/main/java/com/ycwl/basic/integration/questionnaire/config/QuestionnaireIntegrationConfig.java b/src/main/java/com/ycwl/basic/integration/questionnaire/config/QuestionnaireIntegrationConfig.java new file mode 100644 index 0000000..e69de29 diff --git a/src/main/java/com/ycwl/basic/integration/render/config/RenderWorkerIntegrationConfig.java b/src/main/java/com/ycwl/basic/integration/render/config/RenderWorkerIntegrationConfig.java index 65e4edc..4666cb6 100644 --- a/src/main/java/com/ycwl/basic/integration/render/config/RenderWorkerIntegrationConfig.java +++ b/src/main/java/com/ycwl/basic/integration/render/config/RenderWorkerIntegrationConfig.java @@ -3,7 +3,6 @@ package com.ycwl.basic.integration.render.config; import com.ycwl.basic.integration.common.config.IntegrationProperties; import lombok.RequiredArgsConstructor; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; -import org.springframework.cloud.openfeign.EnableFeignClients; import org.springframework.context.annotation.Configuration; /** @@ -11,7 +10,6 @@ import org.springframework.context.annotation.Configuration; */ @Configuration @ConditionalOnProperty(prefix = "integration.render", name = "enabled", havingValue = "true", matchIfMissing = true) -@EnableFeignClients(basePackages = "com.ycwl.basic.integration.render.client") @RequiredArgsConstructor public class RenderWorkerIntegrationConfig { diff --git a/src/main/java/com/ycwl/basic/integration/scenic/service/DefaultConfigIntegrationService.java b/src/main/java/com/ycwl/basic/integration/scenic/service/ScenicDefaultConfigIntegrationService.java similarity index 97% rename from src/main/java/com/ycwl/basic/integration/scenic/service/DefaultConfigIntegrationService.java rename to src/main/java/com/ycwl/basic/integration/scenic/service/ScenicDefaultConfigIntegrationService.java index 220fab0..79f2fac 100644 --- a/src/main/java/com/ycwl/basic/integration/scenic/service/DefaultConfigIntegrationService.java +++ b/src/main/java/com/ycwl/basic/integration/scenic/service/ScenicDefaultConfigIntegrationService.java @@ -13,7 +13,7 @@ import java.util.List; @Slf4j @Service @RequiredArgsConstructor -public class DefaultConfigIntegrationService { +public class ScenicDefaultConfigIntegrationService { private final DefaultConfigClient defaultConfigClient; From 502eca10f63dc3a9f21199150c9a8cde985eddba Mon Sep 17 00:00:00 2001 From: Jerry Yan <792602257@qq.com> Date: Sun, 7 Sep 2025 14:57:47 +0800 Subject: [PATCH 12/16] =?UTF-8?q?refactor(integration):=20=E9=87=8D?= =?UTF-8?q?=E6=9E=84=E6=B8=B2=E6=9F=93=E5=B7=A5=E4=BD=9C=E5=99=A8=E7=9B=B8?= =?UTF-8?q?=E5=85=B3=20DTO=20=E7=B1=BB=E7=9A=84=E5=AD=97=E6=AE=B5=E5=91=BD?= =?UTF-8?q?=E5=90=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 将蛇形命名法(snake_case)改为驼峰命名法(camelCase) - 更新了以下几个 DTO 类的字段名: - RenderWorkerConfigV2DTO - CreateRenderWorkerRequest - RenderWorkerV2DTO - RenderWorkerV2WithConfigDTO - UpdateRenderWorkerRequest- 主要更改集中在配置键、值、类型以及时间相关字段上 --- .../render/dto/config/RenderWorkerConfigV2DTO.java | 14 +++++++------- .../dto/worker/CreateRenderWorkerRequest.java | 2 +- .../render/dto/worker/RenderWorkerV2DTO.java | 6 +++--- .../dto/worker/RenderWorkerV2WithConfigDTO.java | 6 +++--- .../dto/worker/UpdateRenderWorkerRequest.java | 2 +- 5 files changed, 15 insertions(+), 15 deletions(-) diff --git a/src/main/java/com/ycwl/basic/integration/render/dto/config/RenderWorkerConfigV2DTO.java b/src/main/java/com/ycwl/basic/integration/render/dto/config/RenderWorkerConfigV2DTO.java index 1f0aaad..d7ed3b1 100644 --- a/src/main/java/com/ycwl/basic/integration/render/dto/config/RenderWorkerConfigV2DTO.java +++ b/src/main/java/com/ycwl/basic/integration/render/dto/config/RenderWorkerConfigV2DTO.java @@ -17,25 +17,25 @@ public class RenderWorkerConfigV2DTO { /** * 工作器ID */ - @JsonProperty("worker_id") + @JsonProperty("workerId") private Long workerId; /** * 配置键 */ - @JsonProperty("config_key") + @JsonProperty("configKey") private String configKey; /** * 配置值 */ - @JsonProperty("config_value") + @JsonProperty("configValue") private String configValue; /** * 配置类型 (string/int/float/bool/json) */ - @JsonProperty("config_type") + @JsonProperty("configType") private String configType; /** @@ -46,18 +46,18 @@ public class RenderWorkerConfigV2DTO { /** * 是否启用 (0-禁用,1-启用) */ - @JsonProperty("is_active") + @JsonProperty("isActive") private Integer isActive; /** * 创建时间 */ - @JsonProperty("create_time") + @JsonProperty("createTime") private String createTime; /** * 更新时间 */ - @JsonProperty("update_time") + @JsonProperty("updateTime") private String updateTime; } \ No newline at end of file diff --git a/src/main/java/com/ycwl/basic/integration/render/dto/worker/CreateRenderWorkerRequest.java b/src/main/java/com/ycwl/basic/integration/render/dto/worker/CreateRenderWorkerRequest.java index 7947d8c..6f8e3c6 100644 --- a/src/main/java/com/ycwl/basic/integration/render/dto/worker/CreateRenderWorkerRequest.java +++ b/src/main/java/com/ycwl/basic/integration/render/dto/worker/CreateRenderWorkerRequest.java @@ -26,6 +26,6 @@ public class CreateRenderWorkerRequest { /** * 是否启用 (0-禁用,1-启用) */ - @JsonProperty("is_active") + @JsonProperty("isActive") private Integer isActive = 1; } \ No newline at end of file diff --git a/src/main/java/com/ycwl/basic/integration/render/dto/worker/RenderWorkerV2DTO.java b/src/main/java/com/ycwl/basic/integration/render/dto/worker/RenderWorkerV2DTO.java index 32745ee..2b2869b 100644 --- a/src/main/java/com/ycwl/basic/integration/render/dto/worker/RenderWorkerV2DTO.java +++ b/src/main/java/com/ycwl/basic/integration/render/dto/worker/RenderWorkerV2DTO.java @@ -30,20 +30,20 @@ public class RenderWorkerV2DTO { /** * 是否启用 (0-禁用,1-启用) */ - @JsonProperty("is_active") + @JsonProperty("isActive") private Integer isActive; /** * 创建时间 */ - @JsonProperty("create_time") + @JsonProperty("createTime") @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") private Date createTime; /** * 更新时间 */ - @JsonProperty("update_time") + @JsonProperty("updateTime") @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") private Date updateTime; } \ No newline at end of file diff --git a/src/main/java/com/ycwl/basic/integration/render/dto/worker/RenderWorkerV2WithConfigDTO.java b/src/main/java/com/ycwl/basic/integration/render/dto/worker/RenderWorkerV2WithConfigDTO.java index e3bb5d6..9a29bc5 100644 --- a/src/main/java/com/ycwl/basic/integration/render/dto/worker/RenderWorkerV2WithConfigDTO.java +++ b/src/main/java/com/ycwl/basic/integration/render/dto/worker/RenderWorkerV2WithConfigDTO.java @@ -31,20 +31,20 @@ public class RenderWorkerV2WithConfigDTO { /** * 是否启用 (0-禁用,1-启用) */ - @JsonProperty("is_active") + @JsonProperty("isActive") private Integer isActive; /** * 创建时间 */ - @JsonProperty("create_time") + @JsonProperty("createTime") @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") private Date createTime; /** * 更新时间 */ - @JsonProperty("update_time") + @JsonProperty("updateTime") @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") private Date updateTime; diff --git a/src/main/java/com/ycwl/basic/integration/render/dto/worker/UpdateRenderWorkerRequest.java b/src/main/java/com/ycwl/basic/integration/render/dto/worker/UpdateRenderWorkerRequest.java index 6c879b1..b4e4aae 100644 --- a/src/main/java/com/ycwl/basic/integration/render/dto/worker/UpdateRenderWorkerRequest.java +++ b/src/main/java/com/ycwl/basic/integration/render/dto/worker/UpdateRenderWorkerRequest.java @@ -22,6 +22,6 @@ public class UpdateRenderWorkerRequest { /** * 是否启用 (0-禁用,1-启用) */ - @JsonProperty("is_active") + @JsonProperty("isActive") private Integer isActive; } \ No newline at end of file From 4ee79b5db804e8cbf1a629a446248260bfc01b95 Mon Sep 17 00:00:00 2001 From: Jerry Yan <792602257@qq.com> Date: Mon, 8 Sep 2025 00:11:38 +0800 Subject: [PATCH 13/16] =?UTF-8?q?refactor:=20=E5=88=A0=E9=99=A4=E6=B8=B2?= =?UTF-8?q?=E6=9F=93=E6=9C=BA=E7=AE=A1=E7=90=86=E7=9B=B8=E5=85=B3=E4=BB=A3?= =?UTF-8?q?=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 移除 RenderWorkerController、RenderWorkerMapper、RenderWorkerEntity、RenderWorkerService 等类 - 删除相关的 XML 配置文件 - 清理数据库表结构 --- .../controller/pc/RenderWorkerController.java | 61 ------- .../ycwl/basic/mapper/RenderWorkerMapper.java | 22 --- .../entity/RenderWorkerEntity.java | 2 - .../basic/service/pc/RenderWorkerService.java | 23 --- .../pc/impl/RenderWorkerServiceImpl.java | 161 ------------------ .../resources/mapper/RenderWorkerMapper.xml | 142 --------------- src/main/resources/mapper/TaskMapper.xml | 7 - 7 files changed, 418 deletions(-) delete mode 100644 src/main/java/com/ycwl/basic/controller/pc/RenderWorkerController.java delete mode 100644 src/main/java/com/ycwl/basic/mapper/RenderWorkerMapper.java delete mode 100644 src/main/java/com/ycwl/basic/service/pc/RenderWorkerService.java delete mode 100644 src/main/java/com/ycwl/basic/service/pc/impl/RenderWorkerServiceImpl.java delete mode 100644 src/main/resources/mapper/RenderWorkerMapper.xml diff --git a/src/main/java/com/ycwl/basic/controller/pc/RenderWorkerController.java b/src/main/java/com/ycwl/basic/controller/pc/RenderWorkerController.java deleted file mode 100644 index d200d86..0000000 --- a/src/main/java/com/ycwl/basic/controller/pc/RenderWorkerController.java +++ /dev/null @@ -1,61 +0,0 @@ -package com.ycwl.basic.controller.pc; - -import com.ycwl.basic.model.pc.renderWorker.entity.RenderWorkerEntity; -import com.ycwl.basic.model.pc.renderWorker.req.RenderWorkerReqQuery; -import com.ycwl.basic.service.pc.RenderWorkerService; -import com.ycwl.basic.utils.ApiResponse; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.web.bind.annotation.*; - -/** - * @Author:longbinbin - * @Date:2024/12/3 14:59 - */ -@RestController -@RequestMapping("/api/renderWorker/v1") -// 渲染机管理 -public class RenderWorkerController { - - @Autowired - private RenderWorkerService renderWorkerService; - - // 分页查询渲染机 - @PostMapping("/page") - public ApiResponse pageQuery(@RequestBody RenderWorkerReqQuery renderWorkerReqQuery){ - return renderWorkerService.pageQuery(renderWorkerReqQuery); - } - // 渲染机列表查询 - @PostMapping("/list") - public ApiResponse list(@RequestBody RenderWorkerReqQuery renderWorkerReqQuery){ - return renderWorkerService.list(renderWorkerReqQuery); - } - // 渲染机详情查询 - @GetMapping("/detail/{id}") - public ApiResponse detail(@PathVariable Long id){ - return renderWorkerService.detail(id); - } - - // 渲染机新增 - @PostMapping("/add") - public ApiResponse add(@RequestBody RenderWorkerEntity renderWorker){ - return renderWorkerService.add(renderWorker); - } - - // 渲染机删除 - @DeleteMapping("/delete/{id}") - public ApiResponse deleteById(@PathVariable Long id){ - return renderWorkerService.deleteById(id); - } - - // 渲染机修改 - @PostMapping("/update") - public ApiResponse update(@RequestBody RenderWorkerEntity renderWorker){ - return renderWorkerService.update(renderWorker); - } - - // 渲染机修改状态 - @PutMapping("/updateStatus/{id}") - public ApiResponse updateStatus(@PathVariable Long id) { - return renderWorkerService.updateStatus(id); - } -} diff --git a/src/main/java/com/ycwl/basic/mapper/RenderWorkerMapper.java b/src/main/java/com/ycwl/basic/mapper/RenderWorkerMapper.java deleted file mode 100644 index b74da68..0000000 --- a/src/main/java/com/ycwl/basic/mapper/RenderWorkerMapper.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.ycwl.basic.mapper; - -import com.ycwl.basic.model.pc.renderWorker.entity.RenderWorkerEntity; -import com.ycwl.basic.model.pc.renderWorker.req.RenderWorkerReqQuery; -import org.apache.ibatis.annotations.Mapper; - -import java.util.List; - -/** - * @Author:longbinbin - * @Date:2024/11/29 17:22 - * 渲染机管理表 - */ -@Mapper -public interface RenderWorkerMapper { - List list(RenderWorkerReqQuery renderWorkerReqQuery); - int add(RenderWorkerEntity renderWorker); - int deleteById(Long id); - int update(RenderWorkerEntity renderWorker); - int updateStatus(Long id); - -} diff --git a/src/main/java/com/ycwl/basic/model/pc/renderWorker/entity/RenderWorkerEntity.java b/src/main/java/com/ycwl/basic/model/pc/renderWorker/entity/RenderWorkerEntity.java index d9917ae..fcf8986 100644 --- a/src/main/java/com/ycwl/basic/model/pc/renderWorker/entity/RenderWorkerEntity.java +++ b/src/main/java/com/ycwl/basic/model/pc/renderWorker/entity/RenderWorkerEntity.java @@ -14,9 +14,7 @@ import java.util.Date; * 渲染机管理表 */ @Data -@TableName("render_worker") public class RenderWorkerEntity { - @TableId private Long id; /** * 渲染机名称 diff --git a/src/main/java/com/ycwl/basic/service/pc/RenderWorkerService.java b/src/main/java/com/ycwl/basic/service/pc/RenderWorkerService.java deleted file mode 100644 index 21f03fa..0000000 --- a/src/main/java/com/ycwl/basic/service/pc/RenderWorkerService.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.ycwl.basic.service.pc; - -import com.github.pagehelper.PageInfo; -import com.ycwl.basic.model.pc.renderWorker.entity.RenderWorkerEntity; -import com.ycwl.basic.model.pc.renderWorker.req.RenderWorkerReqQuery; -import com.ycwl.basic.model.pc.renderWorker.resp.RenderWorkerRespVO; -import com.ycwl.basic.utils.ApiResponse; - -import java.util.List; - -/** - * @Author:longbinbin - * @Date:2024/12/3 15:07 - */ -public interface RenderWorkerService { - ApiResponse> pageQuery(RenderWorkerReqQuery renderWorkerReqQuery); - ApiResponse> list(RenderWorkerReqQuery renderWorkerReqQuery); - ApiResponse detail(Long id); - ApiResponse add(RenderWorkerEntity renderWorker); - ApiResponse deleteById(Long id); - ApiResponse update(RenderWorkerEntity renderWorker); - ApiResponse updateStatus(Long id); -} diff --git a/src/main/java/com/ycwl/basic/service/pc/impl/RenderWorkerServiceImpl.java b/src/main/java/com/ycwl/basic/service/pc/impl/RenderWorkerServiceImpl.java deleted file mode 100644 index aadcb24..0000000 --- a/src/main/java/com/ycwl/basic/service/pc/impl/RenderWorkerServiceImpl.java +++ /dev/null @@ -1,161 +0,0 @@ -package com.ycwl.basic.service.pc.impl; - -import com.github.pagehelper.PageHelper; -import com.github.pagehelper.PageInfo; -import com.ycwl.basic.mapper.RenderWorkerMapper; -import com.ycwl.basic.model.pc.renderWorker.entity.RenderWorkerEntity; -import com.ycwl.basic.model.pc.renderWorker.req.RenderWorkerReqQuery; -import com.ycwl.basic.model.pc.renderWorker.resp.RenderWorkerRespVO; -import com.ycwl.basic.model.task.req.ClientStatusReqVo; -import com.ycwl.basic.repository.RenderWorkerRepository; -import com.ycwl.basic.service.pc.RenderWorkerService; -import com.ycwl.basic.utils.ApiResponse; -import com.ycwl.basic.utils.SnowFlakeUtil; -import org.apache.commons.lang3.StringUtils; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; - -import java.math.BigDecimal; -import java.math.RoundingMode; -import java.util.List; - -/** - * @Author:longbinbin - * @Date:2024/12/3 15:09 - */ -@Service -public class RenderWorkerServiceImpl implements RenderWorkerService { - - @Autowired - private RenderWorkerMapper renderWorkerMapper; - @Autowired - private RenderWorkerRepository renderWorkerRepository; - - @Override - public ApiResponse> pageQuery(RenderWorkerReqQuery renderWorkerReqQuery) { - PageHelper.startPage(renderWorkerReqQuery.getPageNum(), renderWorkerReqQuery.getPageSize()); - List list = renderWorkerMapper.list(renderWorkerReqQuery); - List workerList = list.stream().map(worker -> { - RenderWorkerRespVO resp = new RenderWorkerRespVO(); - resp.setId(worker.getId()); - resp.setName(worker.getName()); - resp.setAccessKey(worker.getAccessKey()); - resp.setStatus(worker.getStatus()); - resp.setCreateAt(worker.getCreateAt()); - resp.setUpdateAt(worker.getUpdateAt()); - ClientStatusReqVo clientStatus = renderWorkerRepository.getWorkerHostStatus(worker.getId()); - if (clientStatus == null) { - return resp; - } - resp.setCpuCount(clientStatus.getCpu_count()); - resp.setCpuUsage(clientStatus.getCpu_usage()); - // 上报的是字节,存储的是兆 - resp.setMemoryAvailable(clientStatus.getMemory_available().divide(BigDecimal.valueOf(1024 * 1024), RoundingMode.CEILING)); - resp.setMemoryTotal(clientStatus.getMemory_total().divide(BigDecimal.valueOf(1024 * 1024), RoundingMode.CEILING)); - - resp.setPlatform(clientStatus.getPlatform()); - resp.setRuntimeVersion(clientStatus.getRuntime_version()); - resp.setSupportFeature(String.join(",", clientStatus.getSupport_feature())); - resp.setVersion(clientStatus.getVersion()); - resp.setUpdateAt(clientStatus.getUpdateAt()); - return resp; - }).toList(); - PageInfo pageInfo = new PageInfo<>(workerList); - return ApiResponse.success(pageInfo); - } - - @Override - public ApiResponse> list(RenderWorkerReqQuery renderWorkerReqQuery) { - List list = renderWorkerMapper.list(renderWorkerReqQuery); - List workerList = list.stream().map(worker -> { - RenderWorkerRespVO resp = new RenderWorkerRespVO(); - resp.setId(worker.getId()); - resp.setName(worker.getName()); - resp.setAccessKey(worker.getAccessKey()); - resp.setStatus(worker.getStatus()); - resp.setCreateAt(worker.getCreateAt()); - resp.setUpdateAt(worker.getUpdateAt()); - ClientStatusReqVo clientStatus = renderWorkerRepository.getWorkerHostStatus(worker.getId()); - if (clientStatus == null) { - return resp; - } - resp.setCpuCount(clientStatus.getCpu_count()); - resp.setCpuUsage(clientStatus.getCpu_usage()); - // 上报的是字节,存储的是兆 - resp.setMemoryAvailable(clientStatus.getMemory_available().divide(BigDecimal.valueOf(1024 * 1024), RoundingMode.CEILING)); - resp.setMemoryTotal(clientStatus.getMemory_total().divide(BigDecimal.valueOf(1024 * 1024), RoundingMode.CEILING)); - - resp.setPlatform(clientStatus.getPlatform()); - resp.setRuntimeVersion(clientStatus.getRuntime_version()); - resp.setSupportFeature(String.join(",", clientStatus.getSupport_feature())); - resp.setVersion(clientStatus.getVersion()); - resp.setUpdateAt(clientStatus.getUpdateAt()); - return resp; - }).toList(); - return ApiResponse.success(workerList); - } - - @Override - public ApiResponse detail(Long id) { - RenderWorkerEntity worker = renderWorkerRepository.getWorker(id); - - RenderWorkerRespVO resp = new RenderWorkerRespVO(); - resp.setId(worker.getId()); - resp.setName(worker.getName()); - resp.setAccessKey(worker.getAccessKey()); - resp.setStatus(worker.getStatus()); - resp.setCreateAt(worker.getCreateAt()); - resp.setUpdateAt(worker.getUpdateAt()); - - ClientStatusReqVo clientStatus = renderWorkerRepository.getWorkerHostStatus(worker.getId()); - if (clientStatus != null) { - resp.setCpuCount(clientStatus.getCpu_count()); - resp.setCpuUsage(clientStatus.getCpu_usage()); - // 上报的是字节,存储的是兆 - resp.setMemoryAvailable(clientStatus.getMemory_available().divide(BigDecimal.valueOf(1024 * 1024), RoundingMode.CEILING)); - resp.setMemoryTotal(clientStatus.getMemory_total().divide(BigDecimal.valueOf(1024 * 1024), RoundingMode.CEILING)); - - resp.setPlatform(clientStatus.getPlatform()); - resp.setRuntimeVersion(clientStatus.getRuntime_version()); - resp.setSupportFeature(String.join(",", clientStatus.getSupport_feature())); - resp.setVersion(clientStatus.getVersion()); - resp.setUpdateAt(clientStatus.getUpdateAt()); - } - return ApiResponse.success(resp); - } - - @Override - public ApiResponse add(RenderWorkerEntity renderWorker) { - renderWorker.setId(SnowFlakeUtil.getLongId()); - if (StringUtils.isEmpty(renderWorker.getAccessKey())) { - renderWorker.setAccessKey(SnowFlakeUtil.getId()); - } - renderWorker.setStatus(0); - int add = renderWorkerMapper.add(renderWorker); - if (add == 0) { - return ApiResponse.fail("渲染机添加失败"); - }else { - return ApiResponse.success(add); - } - } - - @Override - public ApiResponse deleteById(Long id) { - return ApiResponse.success(renderWorkerMapper.deleteById(id)); - } - - @Override - public ApiResponse update(RenderWorkerEntity renderWorker) { - int update = renderWorkerMapper.update(renderWorker); - if (update == 0) { - return ApiResponse.fail("渲染机修改失败"); - }else { - return ApiResponse.success(update); - } - } - - @Override - public ApiResponse updateStatus(Long id) { - return ApiResponse.success(renderWorkerMapper.updateStatus(id)); - } -} diff --git a/src/main/resources/mapper/RenderWorkerMapper.xml b/src/main/resources/mapper/RenderWorkerMapper.xml deleted file mode 100644 index 4e47bf2..0000000 --- a/src/main/resources/mapper/RenderWorkerMapper.xml +++ /dev/null @@ -1,142 +0,0 @@ - - - - - insert into render_worker(id, `name`, platform, runtime_version, version, access_key, - cpu_count, cpu_usage, memory_total, memory_available, support_feature, scenic_only, test_only, `online`, `status`) - VALUES (#{id}, #{name}, #{platform}, #{runtimeVersion}, #{version}, #{accessKey}, - #{cpuCount}, #{cpuUsage}, #{memoryTotal}, #{memoryAvailable}, #{supportFeature}, #{scenicOnly}, #{testOnly}, #{online}, #{status}) - - - - update render_worker - - - name = #{name}, - - - platform = #{platform}, - - - runtime_version = #{runtimeVersion}, - - - version = #{version}, - - - access_key = #{accessKey}, - - - cpu_count = #{cpuCount}, - - - cpu_usage = #{cpuUsage}, - - - memory_total = #{memoryTotal}, - - - memory_available = #{memoryAvailable}, - - - support_feature = #{supportFeature}, - - - scenic_only = #{scenicOnly}, - - - test_only = #{testOnly}, - - - `online` = #{online}, - - - where id = #{id} - - - update render_worker - set status = (CASE - status - WHEN 1 THEN - 0 - WHEN 0 THEN - 1 - ELSE null - END) - where id = #{id} - - - update render_worker - set platform = #{status.platform}, - runtime_version = #{status.runtimeVersion}, - version = #{status.version}, - cpu_count = #{status.cpuCount}, - cpu_usage = #{status.cpuUsage}, - memory_total = #{status.memoryTotal}, - memory_available = #{status.memoryAvailable}, - support_feature = #{status.supportFeature}, - update_at = #{status.updateAt} - where id = #{id} - - - delete from render_worker where id = #{id} - - - - - - \ No newline at end of file diff --git a/src/main/resources/mapper/TaskMapper.xml b/src/main/resources/mapper/TaskMapper.xml index dbfa2ee..6274ca5 100644 --- a/src/main/resources/mapper/TaskMapper.xml +++ b/src/main/resources/mapper/TaskMapper.xml @@ -84,13 +84,6 @@ from task where status = 0 and worker_id is null - and NOT EXISTS ( - SELECT 1 - FROM render_worker rw - WHERE - rw.status = 1 - AND FIND_IN_SET(task.scenic_id, rw.scenic_only) > 0 -- 检查scenic_id是否在逗号分隔的字符串中 - ) limit 1