Files
smartDriveEE/src/main/java/com/rj/controller/AudioManagementSegmentsController.java

754 lines
32 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package com.rj.controller;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.rj.dto.AsrRequest;
import com.rj.dto.AsrResponse;
import com.rj.config.MinIOConfig;
import com.rj.entity.AudioManagementSegments;
import com.rj.service.IAudioManagementSegmentsService;
import com.rj.service.ITtsRequestLogService;
import com.rj.tenant.TenantContextHolder;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.FileSystemResource;
import org.springframework.core.io.InputStreamResource;
import org.springframework.core.io.Resource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.io.File;
import java.io.InputStream;
import java.nio.file.Files;
import java.time.LocalDateTime;
import java.util.Locale;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.web.multipart.MultipartFile;
import com.rj.service.MinIOService;
/**
* <p>
* 录音分段管理表 前端控制器
* </p>
*
* 对应表audio_management_segments
*/
@RestController
@RequestMapping("/api/audioManagementSegments")
@Tag(name = "录音分段管理", description = "录音分段管理相关接口")
@Slf4j
public class AudioManagementSegmentsController {
@Autowired
private IAudioManagementSegmentsService audioManagementSegmentsService;
/**
* 新增录音分段
*/
@PostMapping("/add")
@Operation(summary = "新增录音分段", description = "添加新的录音分段信息")
public ResponseEntity<Map<String, Object>> addSegment(
@Parameter(description = "录音分段信息", required = true)
@RequestBody AudioManagementSegments segment) {
Map<String, Object> result = new HashMap<>();
try {
if (segment.getId() == null || segment.getId().trim().isEmpty()) {
segment.setId(UUID.randomUUID().toString());
}
if (segment.getCreateTime() == null) {
segment.setCreateTime(LocalDateTime.now());
}
boolean success = audioManagementSegmentsService.save(segment);
if (success) {
result.put("success", true);
result.put("message", "录音分段添加成功");
result.put("data", segment);
return ResponseEntity.ok(result);
} else {
result.put("success", false);
result.put("message", "录音分段添加失败");
return ResponseEntity.badRequest().body(result);
}
} catch (Exception e) {
log.error("录音分段添加异常:{}", e.getMessage(), e);
result.put("success", false);
result.put("message", "录音分段添加异常:" + e.getMessage());
return ResponseEntity.internalServerError().body(result);
}
}
/**
* 根据ID查询录音分段
*/
@GetMapping("/get/{id}")
@Operation(summary = "根据ID查询录音分段", description = "根据分段ID获取录音分段详细信息")
public ResponseEntity<Map<String, Object>> getSegmentById(
@Parameter(description = "分段ID", required = true)
@PathVariable String id) {
Map<String, Object> result = new HashMap<>();
try {
AudioManagementSegments segment = audioManagementSegmentsService.getById(id);
if (segment != null) {
result.put("success", true);
result.put("message", "查询成功");
result.put("data", segment);
return ResponseEntity.ok(result);
} else {
result.put("success", false);
result.put("message", "录音分段不存在");
return ResponseEntity.notFound().build();
}
} catch (Exception e) {
log.error("录音分段查询异常:{}", e.getMessage(), e);
result.put("success", false);
result.put("message", "查询异常:" + e.getMessage());
return ResponseEntity.internalServerError().body(result);
}
}
/**
* 根据ID播放录音分段音频文件
*/
@PostMapping("/playSegmentById/{id}")
@Operation(summary = "播放分段音频文件", description = "播放音频文件")
public ResponseEntity<Resource> playSegmentById(
@Parameter(description = "分段ID", required = true)
@PathVariable String id) {
try {
AudioManagementSegments segment = audioManagementSegmentsService.getById(id);
if (segment == null) {
log.warn("录音分段不存在ID: {}", id);
return ResponseEntity.notFound().build();
}
if (isWindowsOs()) {
return playSegmentUsingAudioFileUrl(segment, id);
}
return playSegmentUsingLocalFilePath(segment, id);
} catch (Exception e) {
log.error("播放录音分段音频文件异常ID: {}, error: {}", id, e.getMessage(), e);
return ResponseEntity.internalServerError().build();
}
}
/**
* Linux 等环境:按分段表中的本地路径 {@link AudioManagementSegments#getAudioFilePath()} 读取并返回音频流(与原实现一致)。
*/
private ResponseEntity<Resource> playSegmentUsingLocalFilePath(AudioManagementSegments segment, String id) {
String audioFilePath = segment.getAudioFilePath();
if (audioFilePath == null || audioFilePath.trim().isEmpty()) {
log.warn("录音分段文件路径为空ID: {}", id);
return ResponseEntity.badRequest().build();
}
File file = new File(audioFilePath);
if (!file.exists() || !file.isFile()) {
log.warn("音频文件不存在或不是文件,路径: {}", audioFilePath);
return ResponseEntity.notFound().build();
}
if (!isAudioFile(audioFilePath)) {
log.warn("文件不是音频文件,路径: {}", audioFilePath);
return ResponseEntity.badRequest().build();
}
Resource resource = new FileSystemResource(file);
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.parseMediaType(getContentType(audioFilePath)));
headers.setContentLength(file.length());
headers.set("Accept-Ranges", "bytes");
return ResponseEntity.ok()
.headers(headers)
.body(resource);
}
/**
* Windows在已根据 ID 查到分段记录的前提下,使用 {@link AudioManagementSegments#getAudioFileUrl()}MinIO 访问 URL
* 解析对象名并从 MinIO 拉流播放,逻辑对齐 {@link MinIOController#downloadFile} 的 downloadFile 调用方式。
*/
private ResponseEntity<Resource> playSegmentUsingAudioFileUrl(AudioManagementSegments segment, String id) {
String audioFileUrl = segment.getAudioFileUrl();
if (audioFileUrl == null || audioFileUrl.trim().isEmpty()) {
log.warn("录音分段音频 URL 为空ID: {}", id);
return ResponseEntity.badRequest().build();
}
String loc = audioFileUrl.trim();
String nameProbe = lastPathSegmentForAudioCheck(loc);
if (!isAudioFile(nameProbe)) {
log.warn("文件不是音频文件location: {}", loc);
return ResponseEntity.badRequest().build();
}
String objectName = resolveMinioObjectName(loc);
if (objectName == null || objectName.isEmpty()) {
log.warn("无法从 URL 解析 MinIO 对象名ID: {}, location: {}", id, loc);
return ResponseEntity.badRequest().build();
}
try {
InputStream inputStream = minIOService.downloadFile(objectName);
Resource resource = new InputStreamResource(inputStream);
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.parseMediaType(getContentType(nameProbe)));
headers.set("Accept-Ranges", "bytes");
return ResponseEntity.ok()
.headers(headers)
.body(resource);
} catch (Exception e) {
log.error("从 MinIO 读取分段音频失败ID: {}, objectName: {}", id, objectName, e);
return ResponseEntity.notFound().build();
}
}
private static boolean isWindowsOs() {
String os = System.getProperty("os.name", "");
return os != null && os.toLowerCase(Locale.ROOT).contains("win");
}
/** 去掉查询串后取路径最后一段,避免 URL 中带 IP 时扩展名判断错误。 */
private static String lastPathSegmentForAudioCheck(String urlOrPath) {
if (urlOrPath == null) {
return "";
}
String s = urlOrPath.trim();
int q = s.indexOf('?');
if (q >= 0) {
s = s.substring(0, q);
}
int slash = Math.max(s.lastIndexOf('/'), s.lastIndexOf('\\'));
return slash >= 0 ? s.substring(slash + 1) : s;
}
@Autowired
private ITtsRequestLogService ttsRequestLogService;
@Autowired
private MinIOService minIOService;
@Autowired
private MinIOConfig minioConfig;
/**
* 转文本请求
*/
@PostMapping("/transcribe/{id}")
@Operation(summary = "转文本", description = "分段音频文件转文本")
public ResponseEntity<Map<String, Object>> transcribeSegmentById(
@Parameter(description = "分段ID", required = true)
@PathVariable String id) {
Map<String, Object> result = new HashMap<>();
try {
// 先查询记录是否存在
AudioManagementSegments segment = audioManagementSegmentsService.getById(id);
if (segment == null) {
result.put("success", false);
result.put("message", "录音分段不存在ID: " + id);
return ResponseEntity.notFound().build();
}
// 检查本地文件路径是否存在
String audioFilePath = segment.getAudioFilePath();
if (audioFilePath == null || audioFilePath.trim().isEmpty()) {
result.put("success", false);
result.put("message", "音频文件路径为空");
return ResponseEntity.badRequest().body(result);
}
File audioFile = new File(audioFilePath);
if (!audioFile.exists() || !audioFile.isFile()) {
result.put("success", false);
result.put("message", "音频文件不存在: " + audioFilePath);
return ResponseEntity.badRequest().body(result);
}
// TODO 1: 上传文件到MinIO
String minioUrl = null;
try {
// 读取本地文件
byte[] fileBytes = Files.readAllBytes(audioFile.toPath());
String fileName = segment.getAudioFileOriginalName() != null
? segment.getAudioFileOriginalName()
: audioFile.getName();
// 获取文件扩展名确定contentType
String contentType = getContentType(fileName);
// 创建MultipartFile对象
MultipartFile multipartFile = new MockMultipartFile(
"file",
fileName,
contentType,
fileBytes
);
// 上传到MinIO
minioUrl = minIOService.uploadFile(multipartFile);
log.info("文件上传到MinIO成功ID: {}, minioUrl: {}", id, minioUrl);
} catch (Exception e) {
log.error("上传文件到MinIO失败ID: {}, error: {}", id, e.getMessage(), e);
result.put("success", false);
result.put("message", "上传文件到MinIO失败: " + e.getMessage());
return ResponseEntity.internalServerError().body(result);
}
// 根据id修改audio_management_segments 表字段: needTranscribe为 1 transcribeRequestTime为当前时间
AudioManagementSegments updateEntity = new AudioManagementSegments();
updateEntity.setNeedTranscribe(true);
updateEntity.setTranscribeRequestTime(LocalDateTime.now());
updateEntity.setAudioFileUrl(minioUrl);
LambdaUpdateWrapper<AudioManagementSegments> updateWrapper = new LambdaUpdateWrapper<>();
updateWrapper.eq(AudioManagementSegments::getId, id);
boolean success = audioManagementSegmentsService.updateNoTenant(updateEntity, updateWrapper);
if (!success) {
result.put("success", false);
result.put("message", "更新转文本状态失败");
return ResponseEntity.badRequest().body(result);
}
// 从minioUrl中提取objectName生成presignedUrl
String presignedUrl = null;
try {
String objectName = extractObjectNameFromUrl(minioUrl);
if (objectName != null) {
// 生成7天有效期的预签名URL
presignedUrl = minIOService.getPresignedUrl(objectName, 7 * 24 * 60 * 60);
log.info("生成预签名URL成功ID: {}, presignedUrl: {}", id, presignedUrl);
} else {
// 如果无法提取objectName直接使用minioUrl
presignedUrl = minioUrl;
log.warn("无法从minioUrl提取objectName使用原始URL: {}", minioUrl);
}
} catch (Exception e) {
log.error("生成预签名URL失败使用原始URL: {}", e.getMessage(), e);
presignedUrl = minioUrl;
}
// TODO 2: 启用异步线程处理转文本
// 获取租户ID优先从segment对象获取如果没有则从当前线程的租户上下文获取
final String tenantId = segment.getTenantId() != null
? segment.getTenantId()
: TenantContextHolder.getTenantId();
final String finalPresignedUrl = presignedUrl;
final String segmentId = id;
final String audioFileName = segment.getAudioFileOriginalName();
CompletableFuture.runAsync(() -> {
try {
// 在异步线程中设置租户上下文
if (tenantId != null && !tenantId.trim().isEmpty()) {
TenantContextHolder.setTenantId(tenantId);
log.info("异步线程中设置租户ID: {}, segmentId: {}", tenantId, segmentId);
} else {
log.warn("租户ID为空segmentId: {}", segmentId);
}
log.info("开始异步转文本处理ID: {}, tenantId: {}", segmentId, tenantId);
AsrRequest asrRequest = new AsrRequest();
asrRequest.setAudioUrl(finalPresignedUrl);
asrRequest.setAudioName(audioFileName);
asrRequest.setModel("paraformer-v2"); // 使用默认模型
asrRequest.setFormat("wav"); // 默认格式
asrRequest.setSampleRate(16000); // 默认采样率
asrRequest.setEnablePunctuation(true); // 启用标点符号
asrRequest.setEnableNumberConversion(true); // 启用数字转换
asrRequest.setEnableSpeakerDiarization(false); // 不启用说话人分离
// 调用ASR服务进行语音识别
AsrResponse asrResponse = ttsRequestLogService.speechToText(asrRequest);
if (asrResponse != null && asrResponse.isSuccess() && asrResponse.getText() != null) {
// 更新转文本结果到数据库
AudioManagementSegments textUpdateEntity = new AudioManagementSegments();
textUpdateEntity.setRecordingText(asrResponse.getText());
textUpdateEntity.setTranscribeEndTime(LocalDateTime.now());
LambdaUpdateWrapper<AudioManagementSegments> textUpdateWrapper = new LambdaUpdateWrapper<>();
textUpdateWrapper.eq(AudioManagementSegments::getId, segmentId);
// 使用正常的update方法因为已经设置了租户上下文
boolean updateSuccess = audioManagementSegmentsService.update(textUpdateEntity, textUpdateWrapper);
if (updateSuccess) {
log.info("转文本结果保存成功ID: {}, tenantId: {}, 文本长度: {}", segmentId, tenantId, asrResponse.getText().length());
} else {
log.error("转文本结果保存失败ID: {}, tenantId: {}", segmentId, tenantId);
}
} else {
String errorMsg = asrResponse != null ? asrResponse.getMessage() : "ASR响应为空";
log.error("转文本失败ID: {}, tenantId: {}, error: {}", segmentId, tenantId, errorMsg);
}
} catch (Exception e) {
log.error("异步转文本处理异常ID: {}, tenantId: {}, error: {}", segmentId, tenantId, e.getMessage(), e);
} finally {
// 清理租户上下文,防止线程复用导致租户串用
TenantContextHolder.clear();
log.debug("清理异步线程租户上下文segmentId: {}", segmentId);
}
});
result.put("success", true);
result.put("message", "转文本请求已提交,正在后台处理");
result.put("data", updateEntity);
return ResponseEntity.ok(result);
} catch (Exception e) {
log.error("转文本请求异常ID: {}, error: {}", id, e.getMessage(), e);
result.put("success", false);
result.put("message", "转文本请求异常:" + e.getMessage());
return ResponseEntity.internalServerError().body(result);
}
}
/**
* 从分段表中的 MinIO 访问 URL 解析对象键:优先按 {@link MinIOConfig#getFileUrlPrefix()} 去掉前缀得到完整 object 路径
*(与 {@link MinIOService#getFileUrl(String)} 生成的 URL 一致),否则回退为 {@link #extractObjectNameFromUrl(String)}。
*/
private String resolveMinioObjectName(String audioFileUrl) {
if (audioFileUrl == null || audioFileUrl.trim().isEmpty()) {
return null;
}
String trimmed = audioFileUrl.trim();
String withoutQuery = trimmed;
int q = trimmed.indexOf('?');
if (q >= 0) {
withoutQuery = trimmed.substring(0, q);
}
String prefix = minioConfig.getFileUrlPrefix();
if (prefix != null && !prefix.isEmpty() && withoutQuery.startsWith(prefix)) {
return withoutQuery.substring(prefix.length());
}
return extractObjectNameFromUrl(trimmed);
}
/**
* 从MinIO URL中提取对象名
* @param url MinIO文件URL
* @return 对象名
*/
private String extractObjectNameFromUrl(String url) {
if (url == null || url.trim().isEmpty()) {
return null;
}
try {
// 去掉查询参数
String urlWithoutParams = url;
if (url.contains("?")) {
urlWithoutParams = url.substring(0, url.indexOf("?"));
}
// 按"/"分割URL获取最后一个部分作为对象名
String[] parts = urlWithoutParams.split("/");
if (parts.length > 0) {
// 获取最后一个非空部分作为对象名
for (int i = parts.length - 1; i >= 0; i--) {
if (parts[i] != null && !parts[i].trim().isEmpty()) {
return parts[i];
}
}
}
return null;
} catch (Exception e) {
log.error("从URL提取对象名失败: {}", url, e);
return null;
}
}
/**
* 判断文件是否为音频文件
*/
private boolean isAudioFile(String fileName) {
if (fileName == null || fileName.isEmpty()) {
return false;
}
String extension = getFileExtension(fileName).toLowerCase();
String[] audioExtensions = {"mp3", "wav", "m4a", "aac", "ogg", "flac", "wma"};
for (String ext : audioExtensions) {
if (ext.equals(extension)) {
return true;
}
}
return false;
}
/**
* 获取文件扩展名
*/
private String getFileExtension(String fileName) {
if (fileName == null || fileName.isEmpty()) {
return "";
}
int lastDotIndex = fileName.lastIndexOf('.');
if (lastDotIndex > 0 && lastDotIndex < fileName.length() - 1) {
return fileName.substring(lastDotIndex + 1);
}
return "";
}
/**
* 根据文件名获取Content-Type
*/
private String getContentType(String fileName) {
String extension = getFileExtension(fileName).toLowerCase();
switch (extension) {
case "mp3":
return "audio/mpeg";
case "wav":
return "audio/wav";
case "m4a":
return "audio/mp4";
case "aac":
return "audio/aac";
case "ogg":
return "audio/ogg";
case "flac":
return "audio/flac";
case "wma":
return "audio/x-ms-wma";
default:
return "application/octet-stream";
}
}
/**
* 分页查询录音分段列表
*/
@GetMapping("/list")
@Operation(summary = "分页查询录音分段列表", description = "分页查询录音分段信息列表")
public ResponseEntity<Map<String, Object>> getSegmentList(
@Parameter(description = "页码", example = "1")
@RequestParam(defaultValue = "1") Integer current,
@Parameter(description = "每页大小", example = "10")
@RequestParam(defaultValue = "10") Integer size,
@Parameter(description = "父录音ID")
@RequestParam(required = false) String parentId,
@Parameter(description = "租户ID")
@RequestParam(required = false) String tenantId,
@Parameter(description = "设备编号(模糊查询)")
@RequestParam(required = false) String deviceNo,
@Parameter(description = "销售姓名(模糊查询)")
@RequestParam(required = false) String salesName,
@Parameter(description = "销售电话(模糊查询)")
@RequestParam(required = false) String salesPhone,
@Parameter(description = "意向级别")
@RequestParam(required = false) String intentionLevel,
@Parameter(description = "上传状态")
@RequestParam(required = false) String uploadStatus,
@Parameter(description = "同步状态")
@RequestParam(required = false) String syncStatus,
@Parameter(description = "场景")
@RequestParam(required = false) String scenario) {
Map<String, Object> result = new HashMap<>();
try {
Page<AudioManagementSegments> page = new Page<>(current, size);
LambdaQueryWrapper<AudioManagementSegments> queryWrapper = new LambdaQueryWrapper<>();
if (parentId != null && !parentId.trim().isEmpty()) {
queryWrapper.eq(AudioManagementSegments::getParentId, parentId);
}
if (tenantId != null && !tenantId.trim().isEmpty()) {
queryWrapper.eq(AudioManagementSegments::getTenantId, tenantId);
}
if (deviceNo != null && !deviceNo.trim().isEmpty()) {
queryWrapper.like(AudioManagementSegments::getDeviceNo, deviceNo);
}
if (salesName != null && !salesName.trim().isEmpty()) {
queryWrapper.like(AudioManagementSegments::getSalesName, salesName);
}
if (salesPhone != null && !salesPhone.trim().isEmpty()) {
queryWrapper.like(AudioManagementSegments::getSalesPhone, salesPhone);
}
if (intentionLevel != null && !intentionLevel.trim().isEmpty()) {
queryWrapper.eq(AudioManagementSegments::getIntentionLevel, intentionLevel);
}
if (uploadStatus != null && !uploadStatus.trim().isEmpty()) {
queryWrapper.eq(AudioManagementSegments::getUploadStatus, uploadStatus);
}
if (syncStatus != null && !syncStatus.trim().isEmpty()) {
queryWrapper.eq(AudioManagementSegments::getSyncStatus, syncStatus);
}
if (scenario != null && !scenario.trim().isEmpty()) {
queryWrapper.eq(AudioManagementSegments::getScenario, scenario);
}
// 按创建时间倒序排列
queryWrapper.orderByDesc(AudioManagementSegments::getCreateTime);
Page<AudioManagementSegments> segmentPage = audioManagementSegmentsService.page(page, queryWrapper);
result.put("success", true);
result.put("message", "查询成功");
result.put("data", segmentPage.getRecords());
result.put("total", segmentPage.getTotal());
result.put("current", segmentPage.getCurrent());
result.put("size", segmentPage.getSize());
result.put("pages", segmentPage.getPages());
return ResponseEntity.ok(result);
} catch (Exception e) {
log.error("录音分段分页查询异常:{}", e.getMessage(), e);
result.put("success", false);
result.put("message", "查询异常:" + e.getMessage());
return ResponseEntity.internalServerError().body(result);
}
}
/**
* 根据父ID查询录音分段列表不分页
*/
@GetMapping("/listByParentId")
@Operation(summary = "根据父ID查询录音分段列表不分页",
description = "根据父录音ID查询所有分段列表不分页")
public ResponseEntity<Map<String, Object>> listByParentId(
@Parameter(description = "父录音ID", required = true)
@RequestParam String parentId) {
Map<String, Object> result = new HashMap<>();
try {
LambdaQueryWrapper<AudioManagementSegments> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(AudioManagementSegments::getParentId, parentId);
// 通常按开始时间或段索引排序
queryWrapper.orderByAsc(AudioManagementSegments::getStartTime);
List<AudioManagementSegments> list = audioManagementSegmentsService.list(queryWrapper);
result.put("success", true);
result.put("message", "查询成功");
result.put("data", list);
result.put("count", list.size());
return ResponseEntity.ok(result);
} catch (Exception e) {
log.error("根据父ID查询录音分段列表异常{}", e.getMessage(), e);
result.put("success", false);
result.put("message", "查询异常:" + e.getMessage());
return ResponseEntity.internalServerError().body(result);
}
}
/**
* 更新录音分段信息
*/
@PutMapping("/update")
@Operation(summary = "更新录音分段信息", description = "更新录音分段详细信息")
public ResponseEntity<Map<String, Object>> updateSegment(
@Parameter(description = "录音分段信息", required = true)
@RequestBody AudioManagementSegments segment) {
Map<String, Object> result = new HashMap<>();
try {
if (segment.getId() == null || segment.getId().trim().isEmpty()) {
result.put("success", false);
result.put("message", "分段ID不能为空");
return ResponseEntity.badRequest().body(result);
}
boolean success = audioManagementSegmentsService.updateById(segment);
if (success) {
result.put("success", true);
result.put("message", "录音分段信息更新成功");
result.put("data", segment);
return ResponseEntity.ok(result);
} else {
result.put("success", false);
result.put("message", "录音分段信息更新失败");
return ResponseEntity.badRequest().body(result);
}
} catch (Exception e) {
log.error("录音分段更新异常:{}", e.getMessage(), e);
result.put("success", false);
result.put("message", "更新异常:" + e.getMessage());
return ResponseEntity.internalServerError().body(result);
}
}
/**
* 根据ID删除录音分段
*/
@DeleteMapping("/delete/{id}")
@Operation(summary = "删除录音分段", description = "根据分段ID删除录音分段信息")
public ResponseEntity<Map<String, Object>> deleteSegment(
@Parameter(description = "分段ID", required = true)
@PathVariable String id) {
Map<String, Object> result = new HashMap<>();
try {
boolean success = audioManagementSegmentsService.removeById(id);
if (success) {
result.put("success", true);
result.put("message", "录音分段删除成功");
return ResponseEntity.ok(result);
} else {
result.put("success", false);
result.put("message", "录音分段删除失败");
return ResponseEntity.badRequest().body(result);
}
} catch (Exception e) {
log.error("录音分段删除异常:{}", e.getMessage(), e);
result.put("success", false);
result.put("message", "删除异常:" + e.getMessage());
return ResponseEntity.internalServerError().body(result);
}
}
/**
* 批量删除录音分段
*/
@DeleteMapping("/batchDelete")
@Operation(summary = "批量删除录音分段", description = "根据分段ID列表批量删除录音分段信息")
public ResponseEntity<Map<String, Object>> batchDeleteSegments(
@Parameter(description = "分段ID列表", required = true)
@RequestBody List<String> ids) {
Map<String, Object> result = new HashMap<>();
try {
if (ids == null || ids.isEmpty()) {
result.put("success", false);
result.put("message", "分段ID列表不能为空");
return ResponseEntity.badRequest().body(result);
}
boolean success = audioManagementSegmentsService.removeByIds(ids);
if (success) {
result.put("success", true);
result.put("message", "批量删除成功,共删除 " + ids.size() + " 条记录");
return ResponseEntity.ok(result);
} else {
result.put("success", false);
result.put("message", "批量删除失败");
return ResponseEntity.badRequest().body(result);
}
} catch (Exception e) {
log.error("批量删除录音分段异常:{}", e.getMessage(), e);
result.put("success", false);
result.put("message", "批量删除异常:" + e.getMessage());
return ResponseEntity.internalServerError().body(result);
}
}
}