package com.rj.service.impl; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.rj.entity.DetectVideoTemplate; import com.rj.mapper.DetectVideoTemplateMapper; import com.rj.service.IDetectVideoTemplateService; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; import org.springframework.http.*; import org.springframework.stereotype.Service; import org.springframework.web.client.RestTemplate; import org.springframework.web.client.HttpClientErrorException; import org.springframework.web.client.HttpServerErrorException; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.JsonNode; import java.time.LocalDateTime; import java.util.HashMap; import java.util.Map; import java.util.UUID; /** * 检测视频模板日志服务实现 */ @Slf4j @Service public class DetectVideoTemplateServiceImpl extends ServiceImpl implements IDetectVideoTemplateService { private static final String API_URL = "https://dashscope.aliyuncs.com/api/v1/services/aigc/image2video/aa-template-generation"; @Value("${dashscope.api.key:}") private String apiKey; private final RestTemplate restTemplate; private final ObjectMapper objectMapper; public DetectVideoTemplateServiceImpl() { this.restTemplate = new RestTemplate(); this.objectMapper = new ObjectMapper(); } @Override public boolean saveDetectVideoTemplateLog(DetectVideoTemplate detectVideoTemplate) { try { return save(detectVideoTemplate); } catch (Exception e) { log.error("保存检测视频模板日志失败: {}", e.getMessage(), e); return false; } } /** * 执行视频模板检测并保存日志 */ public DetectVideoTemplate detectVideoTemplateAndSave(String videoUrl, String ownerName, String ownerPhone, String avatarName, String model) { if (apiKey == null || apiKey.trim().isEmpty()) { log.error("DASHSCOPE_API_KEY未配置"); return createErrorLog(videoUrl, "DASHSCOPE_API_KEY未配置", ownerName, ownerPhone, avatarName); } // 创建日志记录 DetectVideoTemplate detectVideoTemplate = new DetectVideoTemplate(); String requestId = UUID.randomUUID().toString(); LocalDateTime requestTime = LocalDateTime.now(); detectVideoTemplate.setRequestId(requestId); // 设置模型名称,如果未提供则使用默认值 String modelName = (model != null && !model.trim().isEmpty()) ? model : "video-template-detect"; detectVideoTemplate.setModel(modelName); log.info("使用模型: {}", modelName); detectVideoTemplate.setVideoUrl(videoUrl); detectVideoTemplate.setOwnerName(ownerName); detectVideoTemplate.setOwnerPhone(ownerPhone); detectVideoTemplate.setAvatarName(avatarName); detectVideoTemplate.setRequestTime(requestTime); long startTime = System.currentTimeMillis(); try { // 创建请求体 Map requestBody = new HashMap<>(); requestBody.put("model", modelName); Map input = new HashMap<>(); input.put("video_url", videoUrl); requestBody.put("input", input); // 设置请求头 HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_JSON); headers.setBearerAuth(apiKey); log.info("发送视频模板检测请求,requestBody : {}, 请求参数headers: {}", requestBody , headers); // 创建请求实体 HttpEntity> requestEntity = new HttpEntity<>(requestBody, headers); // 发送请求 ResponseEntity response = restTemplate.exchange( API_URL, HttpMethod.POST, requestEntity, String.class ); log.info("发送视频模板检测请求,请求ID: {}, 视频URL: {}", requestId, videoUrl); // 计算处理时间 long endTime = System.currentTimeMillis(); long processingTime = endTime - startTime; // 更新日志记录 detectVideoTemplate.setResponseTime(LocalDateTime.now()); detectVideoTemplate.setStatusCode(response.getStatusCode().value()); detectVideoTemplate.setProcessingTimeMs(processingTime); detectVideoTemplate.setResponseData(response.getBody()); // 处理响应 log.info("视频模板检测响应,状态码: {}, 处理时间: {}ms", response.getStatusCode(), processingTime); // 解析JSON响应 if (response.getStatusCode() == HttpStatus.OK) { JsonNode jsonResponse = objectMapper.readTree(response.getBody()); // 根据success字段判断是否成功 boolean isSuccess = false; if (jsonResponse.has("output") && jsonResponse.get("output").has("success")) { isSuccess = jsonResponse.get("output").get("success").asBoolean(); detectVideoTemplate.setSuccess(isSuccess); log.info("视频模板检测结果 - success: {}", isSuccess); } else { // 如果没有success字段,则根据HTTP状态码判断 isSuccess = response.getStatusCode().is2xxSuccessful(); detectVideoTemplate.setSuccess(isSuccess); } // 检查是否有检测到模板 if (jsonResponse.has("output")) { JsonNode output = jsonResponse.get("output"); // 解析模板ID if (output.has("template_id")) { String templateId = output.get("template_id").asText(); detectVideoTemplate.setTemplateId(templateId); log.info("检测到的模板ID: {}", templateId); } // 记录message信息 if (output.has("message")) { String message = output.get("message").asText(); log.info("检测消息: {}", message); } } // 记录请求ID if (jsonResponse.has("request_id")) { String apiRequestId = jsonResponse.get("request_id").asText(); log.info("API请求ID: {}", apiRequestId); } // 记录使用情况 if (jsonResponse.has("usage")) { JsonNode usage = jsonResponse.get("usage"); log.info("使用情况: {}", usage.toString()); } } else { // HTTP状态码不是200,直接标记为失败 detectVideoTemplate.setSuccess(false); } // 保存到数据库 boolean saved = saveDetectVideoTemplateLog(detectVideoTemplate); if (saved) { log.info("视频模板检测日志已保存,请求ID: {}", requestId); } else { log.error("保存视频模板检测日志失败,请求ID: {}", requestId); } return detectVideoTemplate; } catch (HttpClientErrorException e) { return handleError(detectVideoTemplate, e, "客户端错误 (4xx): " + e.getStatusCode(), startTime); } catch (HttpServerErrorException e) { return handleError(detectVideoTemplate, e, "服务器错误 (5xx): " + e.getStatusCode(), startTime); } catch (Exception e) { return handleError(detectVideoTemplate, e, "视频模板检测请求失败: " + e.getMessage(), startTime); } } /** * 处理错误并保存到数据库 */ private DetectVideoTemplate handleError(DetectVideoTemplate detectVideoTemplate, Exception e, String errorMessage, long startTime) { long endTime = System.currentTimeMillis(); long processingTime = endTime - startTime; detectVideoTemplate.setResponseTime(LocalDateTime.now()); detectVideoTemplate.setSuccess(false); detectVideoTemplate.setProcessingTimeMs(processingTime); detectVideoTemplate.setErrorMessage(errorMessage); if (e instanceof HttpClientErrorException) { detectVideoTemplate.setStatusCode(((HttpClientErrorException) e).getStatusCode().value()); detectVideoTemplate.setResponseData(((HttpClientErrorException) e).getResponseBodyAsString()); } else if (e instanceof HttpServerErrorException) { detectVideoTemplate.setStatusCode(((HttpServerErrorException) e).getStatusCode().value()); detectVideoTemplate.setResponseData(((HttpServerErrorException) e).getResponseBodyAsString()); } log.error("视频模板检测失败: {}", errorMessage); log.error("错误详情: {}", e.getMessage()); // 保存错误日志到数据库 try { saveDetectVideoTemplateLog(detectVideoTemplate); log.info("错误日志已保存,请求ID: {}", detectVideoTemplate.getRequestId()); } catch (Exception saveException) { log.error("保存错误日志失败: {}", saveException.getMessage()); } return detectVideoTemplate; } /** * 创建错误日志 */ private DetectVideoTemplate createErrorLog(String videoUrl, String errorMessage, String ownerName, String ownerPhone, String avatarName) { DetectVideoTemplate detectVideoTemplate = new DetectVideoTemplate(); detectVideoTemplate.setRequestId(UUID.randomUUID().toString()); detectVideoTemplate.setModel("video-template-detect"); detectVideoTemplate.setVideoUrl(videoUrl); detectVideoTemplate.setOwnerName(ownerName); detectVideoTemplate.setOwnerPhone(ownerPhone); detectVideoTemplate.setAvatarName(avatarName); detectVideoTemplate.setRequestTime(LocalDateTime.now()); detectVideoTemplate.setResponseTime(LocalDateTime.now()); detectVideoTemplate.setSuccess(false); detectVideoTemplate.setErrorMessage(errorMessage); try { saveDetectVideoTemplateLog(detectVideoTemplate); } catch (Exception e) { log.error("保存错误日志失败: {}", e.getMessage()); } return detectVideoTemplate; } /** * 分页查询检测视频模板日志 */ @Override public com.baomidou.mybatisplus.extension.plugins.pagination.Page getPageList( Integer current, Integer size, Boolean success, String startTime, String endTime, String ownerName, String ownerPhone, String avatarName) { com.baomidou.mybatisplus.extension.plugins.pagination.Page page = new com.baomidou.mybatisplus.extension.plugins.pagination.Page<>(current, size); com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper queryWrapper = new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<>(); // 添加查询条件 if (success != null) { queryWrapper.eq(DetectVideoTemplate::getSuccess, success); } if (startTime != null && !startTime.trim().isEmpty()) { queryWrapper.ge(DetectVideoTemplate::getRequestTime, startTime); } if (endTime != null && !endTime.trim().isEmpty()) { queryWrapper.le(DetectVideoTemplate::getRequestTime, endTime); } if (ownerName != null && !ownerName.trim().isEmpty()) { queryWrapper.like(DetectVideoTemplate::getOwnerName, ownerName); } if (ownerPhone != null && !ownerPhone.trim().isEmpty()) { queryWrapper.like(DetectVideoTemplate::getOwnerPhone, ownerPhone); } if (avatarName != null && !avatarName.trim().isEmpty()) { queryWrapper.like(DetectVideoTemplate::getAvatarName, avatarName); } // 按请求时间倒序排列 queryWrapper.orderByDesc(DetectVideoTemplate::getRequestTime); return page(page, queryWrapper); } /** * 获取统计信息 */ @Override public Map getStatistics(String startTime, String endTime) { Map statistics = new HashMap<>(); // 构建查询条件 com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper queryWrapper = new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<>(); // 时间范围筛选 if (startTime != null && !startTime.trim().isEmpty()) { queryWrapper.ge(DetectVideoTemplate::getRequestTime, startTime); } if (endTime != null && !endTime.trim().isEmpty()) { queryWrapper.le(DetectVideoTemplate::getRequestTime, endTime); } // 查询总数 long totalCount = count(queryWrapper); // 查询成功数 com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper successWrapper = new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<>(); // 时间范围筛选 if (startTime != null && !startTime.trim().isEmpty()) { successWrapper.ge(DetectVideoTemplate::getRequestTime, startTime); } if (endTime != null && !endTime.trim().isEmpty()) { successWrapper.le(DetectVideoTemplate::getRequestTime, endTime); } successWrapper.eq(DetectVideoTemplate::getSuccess, true); long successCount = count(successWrapper); // 查询失败数 long failureCount = totalCount - successCount; // 计算成功率 double successRate = totalCount > 0 ? (double) successCount / totalCount * 100 : 0; // 查询平均处理时间 java.util.List logs = list(queryWrapper); double avgProcessingTime = logs.stream() .filter(log -> log.getProcessingTimeMs() != null) .mapToLong(DetectVideoTemplate::getProcessingTimeMs) .average() .orElse(0.0); // 构建统计结果 statistics.put("totalCount", totalCount); statistics.put("successCount", successCount); statistics.put("failureCount", failureCount); statistics.put("successRate", Math.round(successRate * 100.0) / 100.0); statistics.put("avgProcessingTimeMs", Math.round(avgProcessingTime)); log.info("统计信息查询完成,总数: {}, 成功数: {}, 失败数: {}, 成功率: {}%", totalCount, successCount, failureCount, successRate); return statistics; } }