feat: 引入会议状态枚举并更新相关逻辑
- 新增 `MeetingStatusEnum` 枚举类,定义会议状态及其相关方法 - 更新多个服务和控制器中的会议状态处理逻辑,使用 `MeetingStatusEnum` 代替硬编码的状态值 - 优化会议状态判断和设置的相关代码,提高可读性和维护性dev_na
parent
82dc485dcf
commit
1813b90c6a
|
|
@ -26,6 +26,7 @@ import com.imeeting.dto.biz.UnifiedMeetingStatusVO;
|
|||
import com.imeeting.entity.biz.AiTask;
|
||||
import com.imeeting.entity.biz.Meeting;
|
||||
import com.imeeting.entity.biz.PromptTemplate;
|
||||
import com.imeeting.enums.MeetingStatusEnum;
|
||||
import com.imeeting.service.android.AndroidAuthService;
|
||||
import com.imeeting.service.android.AndroidChunkUploadService;
|
||||
import com.imeeting.service.android.legacy.LegacyMeetingAdapterService;
|
||||
|
|
@ -454,7 +455,7 @@ public class AndroidMeetingController {
|
|||
AiTask asrTask = findLatestTask(meetingId, "ASR");
|
||||
AiTask summaryTask = findLatestTask(meetingId, "SUMMARY");
|
||||
boolean summaryCompleted = summaryTask != null && Integer.valueOf(2).equals(summaryTask.getStatus());
|
||||
MeetingVO detail = (Integer.valueOf(3).equals(meeting.getStatus()) || summaryCompleted)
|
||||
MeetingVO detail = (MeetingStatusEnum.isCode(meeting.getStatus(), MeetingStatusEnum.COMPLETED) || summaryCompleted)
|
||||
? meetingQueryService.getDetail(meetingId)
|
||||
: null;
|
||||
boolean hasSummary = detail != null && detail.getSummaryContent() != null && !detail.getSummaryContent().isBlank();
|
||||
|
|
@ -736,7 +737,11 @@ public class AndroidMeetingController {
|
|||
}
|
||||
return meetingService.getOne(new LambdaQueryWrapper<Meeting>()
|
||||
.eq(Meeting::getSourceDeviceCode, deviceId)
|
||||
.in(Meeting::getStatus, 0, 1, 2)
|
||||
.in(Meeting::getStatus, MeetingStatusEnum.codesOf(
|
||||
MeetingStatusEnum.INITIALIZING,
|
||||
MeetingStatusEnum.TRANSCRIBING,
|
||||
MeetingStatusEnum.SUMMARIZING
|
||||
))
|
||||
.orderByDesc(Meeting::getId)
|
||||
.last("LIMIT 1"));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import com.imeeting.dto.android.AndroidPublicMeetingSessionResultVO;
|
|||
import com.imeeting.dto.android.AndroidPublicMeetingSessionRequest;
|
||||
import com.imeeting.entity.biz.AndroidPushMessage;
|
||||
import com.imeeting.entity.biz.Meeting;
|
||||
import com.imeeting.enums.MeetingStatusEnum;
|
||||
import com.imeeting.enums.MeetingPushTypeEnum;
|
||||
import com.imeeting.mapper.DeviceInfoMapper;
|
||||
import com.imeeting.service.android.AndroidAuthService;
|
||||
|
|
@ -113,7 +114,8 @@ public class AndroidPublicMeetingController {
|
|||
if (meeting.getSourceDeviceCode() == null || !meeting.getSourceDeviceCode().equals(authContext.getDeviceId())) {
|
||||
throw new RuntimeException("当前会议不属于该设备");
|
||||
}
|
||||
if (meeting.getStatus() != null && meeting.getStatus() > 2) {
|
||||
if (MeetingStatusEnum.isCode(meeting.getStatus(), MeetingStatusEnum.COMPLETED)
|
||||
|| MeetingStatusEnum.isCode(meeting.getStatus(), MeetingStatusEnum.FAILED)) {
|
||||
throw new RuntimeException("当前会议状态不允许删除");
|
||||
}
|
||||
meetingCommandService.deleteMeeting(meetingId);
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ import com.imeeting.entity.biz.AiTask;
|
|||
import com.imeeting.entity.biz.Meeting;
|
||||
import com.imeeting.mapper.biz.MeetingTranscriptMapper;
|
||||
import com.imeeting.entity.biz.PromptTemplate;
|
||||
import com.imeeting.enums.MeetingStatusEnum;
|
||||
import com.imeeting.service.android.legacy.LegacyMeetingAdapterService;
|
||||
import com.imeeting.support.AndroidRequestLogHelper;
|
||||
import com.imeeting.service.biz.AiTaskService;
|
||||
|
|
@ -256,7 +257,7 @@ public class LegacyMeetingController {
|
|||
AiTask asrTask = findLatestTask(meetingId, "ASR");
|
||||
AiTask summaryTask = findLatestTask(meetingId, "SUMMARY");
|
||||
boolean summaryCompleted = summaryTask != null && Integer.valueOf(2).equals(summaryTask.getStatus());
|
||||
MeetingVO detail = (Integer.valueOf(3).equals(meeting.getStatus()) || summaryCompleted)
|
||||
MeetingVO detail = (MeetingStatusEnum.isCode(meeting.getStatus(), MeetingStatusEnum.COMPLETED) || summaryCompleted)
|
||||
? meetingQueryService.getDetail(meetingId)
|
||||
: null;
|
||||
boolean hasSummary = detail != null && detail.getSummaryContent() != null && !detail.getSummaryContent().isBlank();
|
||||
|
|
@ -428,7 +429,7 @@ public class LegacyMeetingController {
|
|||
AiTask summaryTask = findLatestTask(meetingId, "SUMMARY");
|
||||
boolean summaryCompleted = summaryTask != null && Integer.valueOf(2).equals(summaryTask.getStatus());
|
||||
|
||||
if (Integer.valueOf(3).equals(meeting.getStatus()) || summaryCompleted) {
|
||||
if (MeetingStatusEnum.isCode(meeting.getStatus(), MeetingStatusEnum.COMPLETED) || summaryCompleted) {
|
||||
return new LegacyMeetingProcessingStatusResponse("completed", 100, STAGE_COMPLETED);
|
||||
}
|
||||
if (isFailed(asrTask)) {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,54 @@
|
|||
package com.imeeting.enums;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
public enum MeetingStatusEnum {
|
||||
INITIALIZING(0, "初始化/待处理"),
|
||||
TRANSCRIBING(1, "转写中"),
|
||||
SUMMARIZING(2, "总结中"),
|
||||
COMPLETED(3, "已完成"),
|
||||
FAILED(4, "失败");
|
||||
|
||||
private final int code;
|
||||
private final String description;
|
||||
|
||||
MeetingStatusEnum(int code, String description) {
|
||||
this.code = code;
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public int getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
public boolean isTerminal() {
|
||||
return this == COMPLETED || this == FAILED;
|
||||
}
|
||||
|
||||
public boolean isUnfinished() {
|
||||
return this == INITIALIZING || this == TRANSCRIBING || this == SUMMARIZING;
|
||||
}
|
||||
|
||||
public static MeetingStatusEnum fromCode(Integer code) {
|
||||
if (code == null) {
|
||||
return null;
|
||||
}
|
||||
return Arrays.stream(values())
|
||||
.filter(item -> item.code == code)
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
}
|
||||
|
||||
public static boolean isCode(Integer code, MeetingStatusEnum status) {
|
||||
return code != null && status != null && code == status.code;
|
||||
}
|
||||
|
||||
public static List<Integer> codesOf(MeetingStatusEnum... statuses) {
|
||||
return Arrays.stream(statuses).map(MeetingStatusEnum::getCode).toList();
|
||||
}
|
||||
}
|
||||
|
|
@ -2,6 +2,7 @@ package com.imeeting.listener;
|
|||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.imeeting.entity.biz.Meeting;
|
||||
import com.imeeting.enums.MeetingStatusEnum;
|
||||
import com.imeeting.mapper.biz.MeetingMapper;
|
||||
import com.imeeting.service.biz.AiTaskService;
|
||||
import com.imeeting.support.TaskSecurityContextRunner;
|
||||
|
|
@ -33,7 +34,10 @@ public class MeetingTaskRecoveryListener implements ApplicationRunner {
|
|||
|
||||
List<Meeting> pendingMeetings = taskSecurityContextRunner.callAsPlatformAdmin(() ->
|
||||
meetingMapper.selectList(new LambdaQueryWrapper<Meeting>()
|
||||
.in(Meeting::getStatus, 1, 2)
|
||||
.in(Meeting::getStatus, MeetingStatusEnum.codesOf(
|
||||
MeetingStatusEnum.TRANSCRIBING,
|
||||
MeetingStatusEnum.SUMMARIZING
|
||||
))
|
||||
.eq(Meeting::getIsDeleted, 0))
|
||||
);
|
||||
if (pendingMeetings.isEmpty()) {
|
||||
|
|
@ -46,10 +50,10 @@ public class MeetingTaskRecoveryListener implements ApplicationRunner {
|
|||
meetingLockCache.clearDispatchLocks(meeting.getId());
|
||||
meetingAsrPermitCache.clearRecoveryState(meeting.getId());
|
||||
|
||||
if (Integer.valueOf(1).equals(meeting.getStatus())) {
|
||||
if (MeetingStatusEnum.isCode(meeting.getStatus(), MeetingStatusEnum.TRANSCRIBING)) {
|
||||
log.info("Recovering ASR task for meeting {}", meeting.getId());
|
||||
aiTaskService.dispatchTasks(meeting.getId(), meeting.getTenantId(), meeting.getCreatorId());
|
||||
} else if (Integer.valueOf(2).equals(meeting.getStatus())) {
|
||||
} else if (MeetingStatusEnum.isCode(meeting.getStatus(), MeetingStatusEnum.SUMMARIZING)) {
|
||||
log.info("Recovering summary task for meeting {}", meeting.getId());
|
||||
aiTaskService.dispatchSummaryTask(meeting.getId(), meeting.getTenantId(), meeting.getCreatorId());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@ public interface MeetingMapper extends BaseMapper<Meeting> {
|
|||
FROM biz_meetings
|
||||
WHERE tenant_id = #{tenantId}
|
||||
AND source_device_code = #{deviceCode}
|
||||
AND status=3
|
||||
AND is_deleted = 0
|
||||
<if test="resetAt != null">
|
||||
AND created_at >= #{resetAt}
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ import com.imeeting.entity.biz.AiTask;
|
|||
import com.imeeting.entity.biz.LlmModel;
|
||||
import com.imeeting.entity.biz.Meeting;
|
||||
import com.imeeting.entity.biz.MeetingTranscript;
|
||||
import com.imeeting.enums.MeetingStatusEnum;
|
||||
import com.imeeting.mapper.biz.LlmModelMapper;
|
||||
import com.imeeting.mapper.biz.MeetingTranscriptMapper;
|
||||
import com.imeeting.service.android.legacy.LegacyMeetingAdapterService;
|
||||
|
|
@ -183,7 +184,7 @@ public class LegacyMeetingAdapterServiceImpl implements LegacyMeetingAdapterServ
|
|||
meeting.setAudioSaveStatus(RealtimeMeetingAudioStorageService.STATUS_SUCCESS);
|
||||
meeting.setAudioSaveMessage(null);
|
||||
meeting.setOfflineRecordingStatus(MeetingConstants.OFFLINE_RECORDING_UPLOAD_FINISHED);
|
||||
meeting.setStatus(1);
|
||||
meeting.setStatus(MeetingStatusEnum.TRANSCRIBING.getCode());
|
||||
meetingService.updateById(meeting);
|
||||
|
||||
resetOrCreateAsrTask(meetingId, profile);
|
||||
|
|
@ -252,7 +253,7 @@ public class LegacyMeetingAdapterServiceImpl implements LegacyMeetingAdapterServ
|
|||
meeting.setAudioSaveStatus(RealtimeMeetingAudioStorageService.STATUS_SUCCESS);
|
||||
meeting.setAudioSaveMessage(null);
|
||||
meeting.setOfflineRecordingStatus(MeetingConstants.OFFLINE_RECORDING_UPLOAD_FINISHED);
|
||||
meeting.setStatus(1);
|
||||
meeting.setStatus(MeetingStatusEnum.TRANSCRIBING.getCode());
|
||||
meetingService.updateById(meeting);
|
||||
|
||||
resetOrCreateAsrTask(meetingId, profile);
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ import com.imeeting.entity.biz.AiTask;
|
|||
import com.imeeting.entity.biz.HotWord;
|
||||
import com.imeeting.entity.biz.Meeting;
|
||||
import com.imeeting.entity.biz.MeetingTranscript;
|
||||
import com.imeeting.enums.MeetingStatusEnum;
|
||||
import com.imeeting.mapper.biz.AiTaskMapper;
|
||||
import com.imeeting.mapper.biz.MeetingMapper;
|
||||
import com.imeeting.mapper.biz.MeetingTranscriptMapper;
|
||||
|
|
@ -953,7 +954,7 @@ public class AiTaskServiceImpl extends ServiceImpl<AiTaskMapper, AiTask> impleme
|
|||
|
||||
Files.writeString(filePath, markdownContent, StandardCharsets.UTF_8);
|
||||
|
||||
boolean alreadyCompleted = Integer.valueOf(3).equals(meeting.getStatus());
|
||||
boolean alreadyCompleted = MeetingStatusEnum.isCode(meeting.getStatus(), MeetingStatusEnum.COMPLETED);
|
||||
taskRecord.setResultFilePath("meetings/" + meeting.getId() + "/summaries/" + fileName);
|
||||
Map<String, Object> responseData = objectMapper.convertValue(respNode, Map.class);
|
||||
responseData.put("summarySource", summarySource.toSnapshot());
|
||||
|
|
@ -1206,22 +1207,22 @@ public class AiTaskServiceImpl extends ServiceImpl<AiTaskMapper, AiTask> impleme
|
|||
int meetingStatus;
|
||||
if (percent < 0) {
|
||||
stage = MeetingProgressStage.FAILED;
|
||||
meetingStatus = 4;
|
||||
meetingStatus = MeetingStatusEnum.FAILED.getCode();
|
||||
} else if (percent >= 100) {
|
||||
stage = MeetingProgressStage.COMPLETED;
|
||||
meetingStatus = 3;
|
||||
meetingStatus = MeetingStatusEnum.COMPLETED.getCode();
|
||||
} else if (percent >= 90) {
|
||||
stage = MeetingProgressStage.SUMMARY_RUNNING;
|
||||
meetingStatus = 2;
|
||||
meetingStatus = MeetingStatusEnum.SUMMARIZING.getCode();
|
||||
} else if (percent >= 85) {
|
||||
stage = MeetingProgressStage.CHAPTER_RUNNING;
|
||||
meetingStatus = 2;
|
||||
meetingStatus = MeetingStatusEnum.SUMMARIZING.getCode();
|
||||
} else if (percent >= 5) {
|
||||
stage = MeetingProgressStage.ASR_RUNNING;
|
||||
meetingStatus = 1;
|
||||
meetingStatus = MeetingStatusEnum.TRANSCRIBING.getCode();
|
||||
} else {
|
||||
stage = MeetingProgressStage.QUEUED;
|
||||
meetingStatus = 1;
|
||||
meetingStatus = MeetingStatusEnum.TRANSCRIBING.getCode();
|
||||
}
|
||||
meetingProgressService.markStage(meetingId, findLatestTaskForProgress(meetingId), meetingStatus, stage, percent, msg, eta);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ import com.imeeting.entity.biz.HotWord;
|
|||
import com.imeeting.entity.biz.Meeting;
|
||||
import com.imeeting.entity.biz.MeetingTranscript;
|
||||
import com.imeeting.entity.biz.MeetingTranscriptChapterVersion;
|
||||
import com.imeeting.enums.MeetingStatusEnum;
|
||||
import com.imeeting.service.android.AndroidMeetingPushService;
|
||||
import com.imeeting.service.android.AndroidPendingMeetingDraftService;
|
||||
import com.imeeting.service.android.AndroidPushMessageService;
|
||||
|
|
@ -485,7 +486,7 @@ public class MeetingCommandServiceImpl implements MeetingCommandService {
|
|||
}
|
||||
|
||||
realtimeMeetingSessionStateService.clear(meetingId);
|
||||
meeting.setStatus(2);
|
||||
meeting.setStatus(MeetingStatusEnum.SUMMARIZING.getCode());
|
||||
meetingService.updateById(meeting);
|
||||
updateMeetingProgress(meetingId, 85, "正在生成 AI 目录与总结...", 0);
|
||||
meetingDomainSupport.prewarmPlaybackAudioAfterCommit(meeting.getAudioUrl());
|
||||
|
|
@ -824,7 +825,7 @@ public class MeetingCommandServiceImpl implements MeetingCommandService {
|
|||
"RESUMMARY"
|
||||
);
|
||||
meeting.setLatestSummaryTaskId(createdSummaryTask.getId());
|
||||
meeting.setStatus(2);
|
||||
meeting.setStatus(MeetingStatusEnum.SUMMARIZING.getCode());
|
||||
meetingService.updateById(meeting);
|
||||
aiTaskService.dispatchSummaryTask(meeting.getId(), meeting.getTenantId(), meeting.getCreatorId());
|
||||
|
||||
|
|
@ -885,7 +886,7 @@ public class MeetingCommandServiceImpl implements MeetingCommandService {
|
|||
aiTaskService.updateById(summaryTask);
|
||||
meetingPointsService.recordSummarySuccessCharge(meeting, summaryTask);
|
||||
|
||||
boolean alreadyCompleted = Integer.valueOf(3).equals(meeting.getStatus());
|
||||
boolean alreadyCompleted = MeetingStatusEnum.isCode(meeting.getStatus(), MeetingStatusEnum.COMPLETED);
|
||||
meeting.setLatestSummaryTaskId(summaryTask.getId());
|
||||
meetingService.updateById(meeting);
|
||||
aiTaskService.reconcileMeetingStatus(meeting.getId());
|
||||
|
|
@ -1012,7 +1013,7 @@ public class MeetingCommandServiceImpl implements MeetingCommandService {
|
|||
"RESUMMARY"
|
||||
);
|
||||
meeting.setSummaryDetailLevel(effectiveSummaryDetailLevel);
|
||||
meeting.setStatus(2);
|
||||
meeting.setStatus(MeetingStatusEnum.SUMMARIZING.getCode());
|
||||
meetingService.updateById(meeting);
|
||||
if ("EXTERNAL_N8N".equalsIgnoreCase(summaryOrchestrationMode)) {
|
||||
updateMeetingProgress(meetingId, 95, "等待外部总结编排...", 0);
|
||||
|
|
@ -1047,7 +1048,7 @@ public class MeetingCommandServiceImpl implements MeetingCommandService {
|
|||
if (asrTask == null || asrTask.getTaskConfig() == null || asrTask.getTaskConfig().get("asrModelId") == null) {
|
||||
throw new RuntimeException("未找到可用的识别任务配置");
|
||||
}
|
||||
if (Integer.valueOf(1).equals(asrTask.getStatus()) && !Integer.valueOf(4).equals(meeting.getStatus())) {
|
||||
if (Integer.valueOf(1).equals(asrTask.getStatus()) && !MeetingStatusEnum.isCode(meeting.getStatus(), MeetingStatusEnum.FAILED)) {
|
||||
throw new RuntimeException("当前会议转写任务仍在处理中,请勿重复重试");
|
||||
}
|
||||
|
||||
|
|
@ -1087,7 +1088,7 @@ public class MeetingCommandServiceImpl implements MeetingCommandService {
|
|||
resetAiTask(summaryTask, new HashMap<>(summaryTask.getTaskConfig()));
|
||||
aiTaskService.updateById(summaryTask);
|
||||
|
||||
meeting.setStatus(1);
|
||||
meeting.setStatus(MeetingStatusEnum.TRANSCRIBING.getCode());
|
||||
meetingService.updateById(meeting);
|
||||
clearLegacyDispatchState(meetingId);
|
||||
updateMeetingProgress(meetingId, 0, "已重新提交识别任务,等待 ASR 处理...", 0);
|
||||
|
|
@ -1101,7 +1102,7 @@ public class MeetingCommandServiceImpl implements MeetingCommandService {
|
|||
if (meeting == null) {
|
||||
throw new RuntimeException("会议不存在");
|
||||
}
|
||||
if (meeting.getStatus() == 2) {
|
||||
if (MeetingStatusEnum.isCode(meeting.getStatus(), MeetingStatusEnum.SUMMARIZING)) {
|
||||
throw new RuntimeException("当前会议仍在处理中,请稍后再试");
|
||||
}
|
||||
long transcriptCount = transcriptMapper.selectCount(new LambdaQueryWrapper<MeetingTranscript>()
|
||||
|
|
@ -1122,7 +1123,7 @@ public class MeetingCommandServiceImpl implements MeetingCommandService {
|
|||
}
|
||||
resetAiTask(summaryTask, new HashMap<>(summaryTask.getTaskConfig()));
|
||||
aiTaskService.updateById(summaryTask);
|
||||
meeting.setStatus(2);
|
||||
meeting.setStatus(MeetingStatusEnum.SUMMARIZING.getCode());
|
||||
meetingService.updateById(meeting);
|
||||
updateMeetingProgress(meetingId, 90, "已重新提交总结任务,正在生成总结...", 0);
|
||||
dispatchSummaryTaskAfterCommit(meetingId, meeting.getTenantId(), meeting.getCreatorId());
|
||||
|
|
@ -1135,7 +1136,7 @@ public class MeetingCommandServiceImpl implements MeetingCommandService {
|
|||
if (meeting == null) {
|
||||
throw new RuntimeException("会议不存在");
|
||||
}
|
||||
if (meeting.getStatus() == 2) {
|
||||
if (MeetingStatusEnum.isCode(meeting.getStatus(), MeetingStatusEnum.SUMMARIZING)) {
|
||||
throw new RuntimeException("当前会议仍在处理中,请稍后再试");
|
||||
}
|
||||
long transcriptCount = transcriptMapper.selectCount(new LambdaQueryWrapper<MeetingTranscript>()
|
||||
|
|
@ -1156,7 +1157,7 @@ public class MeetingCommandServiceImpl implements MeetingCommandService {
|
|||
}
|
||||
resetAiTask(chapterTask, new HashMap<>(chapterTask.getTaskConfig()));
|
||||
aiTaskService.updateById(chapterTask);
|
||||
meeting.setStatus(2);
|
||||
meeting.setStatus(MeetingStatusEnum.SUMMARIZING.getCode());
|
||||
meetingService.updateById(meeting);
|
||||
updateMeetingProgress(meetingId, 85, "已重新提交 AI 目录任务,正在生成目录...", 0);
|
||||
dispatchChapterTaskAfterCommit(meetingId, meeting.getTenantId(), meeting.getCreatorId());
|
||||
|
|
@ -1340,22 +1341,22 @@ public class MeetingCommandServiceImpl implements MeetingCommandService {
|
|||
int meetingStatus;
|
||||
if (percent < 0) {
|
||||
stage = com.imeeting.common.MeetingProgressStage.FAILED;
|
||||
meetingStatus = 4;
|
||||
meetingStatus = MeetingStatusEnum.FAILED.getCode();
|
||||
} else if (percent >= 100) {
|
||||
stage = com.imeeting.common.MeetingProgressStage.COMPLETED;
|
||||
meetingStatus = 3;
|
||||
meetingStatus = MeetingStatusEnum.COMPLETED.getCode();
|
||||
} else if (percent >= 90) {
|
||||
stage = com.imeeting.common.MeetingProgressStage.SUMMARY_RUNNING;
|
||||
meetingStatus = 2;
|
||||
meetingStatus = MeetingStatusEnum.SUMMARIZING.getCode();
|
||||
} else if (percent >= 85) {
|
||||
stage = com.imeeting.common.MeetingProgressStage.CHAPTER_RUNNING;
|
||||
meetingStatus = 2;
|
||||
meetingStatus = MeetingStatusEnum.SUMMARIZING.getCode();
|
||||
} else if (percent >= 5) {
|
||||
stage = com.imeeting.common.MeetingProgressStage.ASR_RUNNING;
|
||||
meetingStatus = 1;
|
||||
meetingStatus = MeetingStatusEnum.TRANSCRIBING.getCode();
|
||||
} else {
|
||||
stage = com.imeeting.common.MeetingProgressStage.QUEUED;
|
||||
meetingStatus = 1;
|
||||
meetingStatus = MeetingStatusEnum.TRANSCRIBING.getCode();
|
||||
}
|
||||
meetingProgressService.markStageAfterCommitOrNow(meetingId, null, meetingStatus, stage, percent, message, eta);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -568,25 +568,32 @@ public class MeetingDomainSupport {
|
|||
);
|
||||
try {
|
||||
ProcessBuilder processBuilder = new ProcessBuilder(command);
|
||||
processBuilder.redirectErrorStream(true);
|
||||
Process process = processBuilder.start();
|
||||
byte[] output;
|
||||
try (InputStream processStream = process.getInputStream()) {
|
||||
output = processStream.readAllBytes();
|
||||
byte[] stdout;
|
||||
byte[] stderr;
|
||||
try (InputStream stdoutStream = process.getInputStream();
|
||||
InputStream stderrStream = process.getErrorStream()) {
|
||||
stdout = stdoutStream.readAllBytes();
|
||||
stderr = stderrStream.readAllBytes();
|
||||
}
|
||||
if (!process.waitFor(30, TimeUnit.SECONDS)) {
|
||||
process.destroyForcibly();
|
||||
return null;
|
||||
}
|
||||
if (process.exitValue() != 0) {
|
||||
return null;
|
||||
String stdoutText = new String(stdout, StandardCharsets.UTF_8).trim();
|
||||
String stderrText = new String(stderr, StandardCharsets.UTF_8).trim();
|
||||
Double duration = extractDurationSeconds(stdoutText);
|
||||
if (duration == null) {
|
||||
duration = extractDurationSeconds(stderrText);
|
||||
}
|
||||
String raw = new String(output, StandardCharsets.UTF_8).trim();
|
||||
if (raw.isBlank()) {
|
||||
return null;
|
||||
if (duration != null && duration > 0D) {
|
||||
return (int) Math.ceil(duration);
|
||||
}
|
||||
double duration = Double.parseDouble(raw);
|
||||
return duration > 0 ? (int) Math.ceil(duration) : null;
|
||||
if (process.exitValue() != 0 || !stderrText.isBlank() || !stdoutText.isBlank()) {
|
||||
log.warn("ffprobe returned no parsable duration, path={}, exitCode={}, stdout={}, stderr={}",
|
||||
audioPath, process.exitValue(), stdoutText, stderrText);
|
||||
}
|
||||
return null;
|
||||
} catch (Exception ex) {
|
||||
log.warn("ffprobe failed to resolve audio duration from path={}", audioPath, ex);
|
||||
return null;
|
||||
|
|
@ -599,12 +606,21 @@ public class MeetingDomainSupport {
|
|||
}
|
||||
String trimmed = ffmpegPath.trim();
|
||||
try {
|
||||
Path ffmpeg = Paths.get(trimmed);
|
||||
Path fileName = ffmpeg.getFileName();
|
||||
Path configuredPath = Paths.get(trimmed);
|
||||
if (Files.isDirectory(configuredPath)) {
|
||||
Path ffprobeInDir = configuredPath.resolve(isWindowsLikePath(trimmed) ? "ffprobe.exe" : "ffprobe");
|
||||
if (Files.exists(ffprobeInDir)) {
|
||||
return ffprobeInDir.toString();
|
||||
}
|
||||
}
|
||||
Path fileName = configuredPath.getFileName();
|
||||
if (fileName != null) {
|
||||
String normalizedName = fileName.toString().toLowerCase();
|
||||
if ("ffprobe".equals(normalizedName) || "ffprobe.exe".equals(normalizedName)) {
|
||||
return configuredPath.toString();
|
||||
}
|
||||
if ("ffmpeg".equals(normalizedName) || "ffmpeg.exe".equals(normalizedName)) {
|
||||
Path sibling = ffmpeg.resolveSibling(normalizedName.endsWith(".exe") ? "ffprobe.exe" : "ffprobe");
|
||||
Path sibling = configuredPath.resolveSibling(normalizedName.endsWith(".exe") ? "ffprobe.exe" : "ffprobe");
|
||||
if (Files.exists(sibling)) {
|
||||
return sibling.toString();
|
||||
}
|
||||
|
|
@ -616,6 +632,29 @@ public class MeetingDomainSupport {
|
|||
return "ffprobe";
|
||||
}
|
||||
|
||||
private Double extractDurationSeconds(String rawOutput) {
|
||||
if (rawOutput == null || rawOutput.isBlank()) {
|
||||
return null;
|
||||
}
|
||||
String[] lines = rawOutput.split("\\R");
|
||||
for (int i = lines.length - 1; i >= 0; i--) {
|
||||
String candidate = lines[i] == null ? null : lines[i].trim();
|
||||
if (candidate == null || candidate.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
try {
|
||||
return Double.parseDouble(candidate);
|
||||
} catch (NumberFormatException ignored) {
|
||||
// Keep scanning upward until a numeric duration line is found.
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private boolean isWindowsLikePath(String path) {
|
||||
return path != null && path.contains("\\");
|
||||
}
|
||||
|
||||
private Path resolvePublicAudioPath(String audioUrl) {
|
||||
if (audioUrl == null || audioUrl.isBlank()) {
|
||||
return null;
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import com.imeeting.dto.biz.MeetingVO;
|
|||
import com.imeeting.dto.biz.UnifiedMeetingStatusVO;
|
||||
import com.imeeting.entity.biz.AiTask;
|
||||
import com.imeeting.entity.biz.Meeting;
|
||||
import com.imeeting.enums.MeetingStatusEnum;
|
||||
import com.imeeting.mapper.biz.AiTaskMapper;
|
||||
import com.imeeting.mapper.biz.MeetingMapper;
|
||||
import com.imeeting.service.android.AndroidMeetingPushService;
|
||||
|
|
@ -222,10 +223,10 @@ public class MeetingProgressServiceImpl implements MeetingProgressService {
|
|||
.eq(AiTask::getMeetingId, meetingId)
|
||||
.orderByDesc(AiTask::getId)
|
||||
.last("LIMIT 1"));
|
||||
if (meeting.getStatus() != null && meeting.getStatus() == 3) {
|
||||
if (MeetingStatusEnum.isCode(meeting.getStatus(), MeetingStatusEnum.COMPLETED)) {
|
||||
return buildSnapshot(meetingId, latestTask, meeting.getStatus(), MeetingProgressStage.COMPLETED, 100, "处理完成", 0);
|
||||
}
|
||||
if (meeting.getStatus() != null && meeting.getStatus() == 4) {
|
||||
if (MeetingStatusEnum.isCode(meeting.getStatus(), MeetingStatusEnum.FAILED)) {
|
||||
String message = latestTask != null && latestTask.getErrorMsg() != null && !latestTask.getErrorMsg().isBlank()
|
||||
? latestTask.getErrorMsg()
|
||||
: "处理失败";
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import com.imeeting.dto.biz.MeetingVO;
|
|||
import com.imeeting.entity.biz.AiTask;
|
||||
import com.imeeting.entity.biz.Meeting;
|
||||
import com.imeeting.entity.biz.MeetingTranscript;
|
||||
import com.imeeting.enums.MeetingStatusEnum;
|
||||
import com.imeeting.service.biz.AiTaskService;
|
||||
import com.imeeting.mapper.biz.MeetingMapper;
|
||||
import com.imeeting.mapper.biz.MeetingTranscriptMapper;
|
||||
|
|
@ -186,12 +187,18 @@ public class MeetingQueryServiceImpl implements MeetingQueryService {
|
|||
}
|
||||
|
||||
stats.put("totalMeetings", meetingService.count(baseWrapper.clone()));
|
||||
stats.put("processingTasks", meetingService.count(baseWrapper.clone().in(Meeting::getStatus, 1, 2)));
|
||||
stats.put("processingTasks", meetingService.count(baseWrapper.clone().in(
|
||||
Meeting::getStatus,
|
||||
MeetingStatusEnum.codesOf(MeetingStatusEnum.TRANSCRIBING, MeetingStatusEnum.SUMMARIZING)
|
||||
)));
|
||||
LocalDateTime todayStart = LocalDateTime.now().withHour(0).withMinute(0).withSecond(0);
|
||||
stats.put("todayNew", meetingService.count(baseWrapper.clone().ge(Meeting::getCreatedAt, todayStart)));
|
||||
|
||||
long totalFinished = meetingService.count(baseWrapper.clone().in(Meeting::getStatus, 3, 4));
|
||||
long success = meetingService.count(baseWrapper.clone().eq(Meeting::getStatus, 3));
|
||||
long totalFinished = meetingService.count(baseWrapper.clone().in(
|
||||
Meeting::getStatus,
|
||||
MeetingStatusEnum.codesOf(MeetingStatusEnum.COMPLETED, MeetingStatusEnum.FAILED)
|
||||
));
|
||||
long success = meetingService.count(baseWrapper.clone().eq(Meeting::getStatus, MeetingStatusEnum.COMPLETED.getCode()));
|
||||
stats.put("successRate", totalFinished == 0 ? 100 : (int) ((double) success / totalFinished * 100));
|
||||
return stats;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import com.imeeting.entity.biz.AiTask;
|
|||
import com.imeeting.entity.biz.Meeting;
|
||||
import com.imeeting.entity.biz.MeetingTranscript;
|
||||
import com.imeeting.entity.biz.MeetingTranscriptChapterVersion;
|
||||
import com.imeeting.enums.MeetingStatusEnum;
|
||||
import com.imeeting.mapper.biz.AiTaskMapper;
|
||||
import com.imeeting.mapper.biz.MeetingMapper;
|
||||
import com.imeeting.mapper.biz.MeetingTranscriptChapterVersionMapper;
|
||||
|
|
@ -80,7 +81,7 @@ public class MeetingUnifiedStatusServiceImpl implements MeetingUnifiedStatusServ
|
|||
if (meeting == null) {
|
||||
return UnifiedMeetingStatusStage.INITIALIZING;
|
||||
}
|
||||
if (Integer.valueOf(3).equals(meeting.getStatus())) {
|
||||
if (MeetingStatusEnum.isCode(meeting.getStatus(), MeetingStatusEnum.COMPLETED)) {
|
||||
return UnifiedMeetingStatusStage.COMPLETED;
|
||||
}
|
||||
UnifiedMeetingStatusStage stageFromSnapshot = resolveStageFromSnapshot(snapshot);
|
||||
|
|
@ -117,7 +118,7 @@ public class MeetingUnifiedStatusServiceImpl implements MeetingUnifiedStatusServ
|
|||
}
|
||||
|
||||
private UnifiedMeetingStatusStage resolveFailedStage(MeetingVO meeting) {
|
||||
if (meeting == null || !Integer.valueOf(4).equals(meeting.getStatus())) {
|
||||
if (meeting == null || !MeetingStatusEnum.isCode(meeting.getStatus(), MeetingStatusEnum.FAILED)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import com.imeeting.dto.biz.RealtimeMeetingSessionState;
|
|||
import com.imeeting.dto.biz.RealtimeMeetingSessionStatusVO;
|
||||
import com.imeeting.entity.biz.Meeting;
|
||||
import com.imeeting.entity.biz.MeetingTranscript;
|
||||
import com.imeeting.enums.MeetingStatusEnum;
|
||||
import com.imeeting.mapper.biz.MeetingMapper;
|
||||
import com.imeeting.mapper.biz.MeetingTranscriptMapper;
|
||||
import com.imeeting.service.biz.RealtimeMeetingSessionStateService;
|
||||
|
|
@ -299,7 +300,7 @@ public class RealtimeMeetingSessionStateServiceImpl implements RealtimeMeetingSe
|
|||
return vo;
|
||||
}
|
||||
|
||||
if (Integer.valueOf(2).equals(meeting.getStatus())) {
|
||||
if (MeetingStatusEnum.isCode(meeting.getStatus(), MeetingStatusEnum.SUMMARIZING)) {
|
||||
vo.setStatus("COMPLETING");
|
||||
} else if (isDatabaseTerminalStatus(meeting.getStatus())) {
|
||||
vo.setStatus("COMPLETED");
|
||||
|
|
@ -322,7 +323,8 @@ public class RealtimeMeetingSessionStateServiceImpl implements RealtimeMeetingSe
|
|||
}
|
||||
|
||||
private boolean isDatabaseTerminalStatus(Integer status) {
|
||||
return Integer.valueOf(3).equals(status) || Integer.valueOf(4).equals(status);
|
||||
return MeetingStatusEnum.isCode(status, MeetingStatusEnum.COMPLETED)
|
||||
|| MeetingStatusEnum.isCode(status, MeetingStatusEnum.FAILED);
|
||||
}
|
||||
|
||||
private boolean isRedisTerminalStatus(String status) {
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ import com.imeeting.dto.biz.MeetingVO;
|
|||
import com.imeeting.entity.biz.AiTask;
|
||||
import com.imeeting.entity.biz.Meeting;
|
||||
import com.imeeting.entity.biz.PromptTemplate;
|
||||
import com.imeeting.enums.MeetingStatusEnum;
|
||||
import com.imeeting.service.biz.AiTaskService;
|
||||
import com.imeeting.service.biz.MeetingAccessService;
|
||||
import com.imeeting.service.biz.MeetingProgressService;
|
||||
|
|
@ -188,7 +189,7 @@ public class MeetingMcpToolService {
|
|||
AiTask asrTask = findLatestTask(meetingId, "ASR");
|
||||
AiTask summaryTask = findLatestTask(meetingId, "SUMMARY");
|
||||
boolean summaryCompleted = summaryTask != null && Integer.valueOf(2).equals(summaryTask.getStatus());
|
||||
MeetingVO detail = (Integer.valueOf(3).equals(meeting.getStatus()) || summaryCompleted)
|
||||
MeetingVO detail = (MeetingStatusEnum.isCode(meeting.getStatus(), MeetingStatusEnum.COMPLETED) || summaryCompleted)
|
||||
? meetingQueryService.getDetail(meetingId)
|
||||
: null;
|
||||
boolean hasSummary = detail != null && detail.getSummaryContent() != null && !detail.getSummaryContent().isBlank();
|
||||
|
|
@ -340,7 +341,7 @@ public class MeetingMcpToolService {
|
|||
AiTask summaryTask = findLatestTask(meetingId, "SUMMARY");
|
||||
boolean summaryCompleted = summaryTask != null && Integer.valueOf(2).equals(summaryTask.getStatus());
|
||||
|
||||
if (Integer.valueOf(3).equals(meeting.getStatus()) || summaryCompleted) {
|
||||
if (MeetingStatusEnum.isCode(meeting.getStatus(), MeetingStatusEnum.COMPLETED) || summaryCompleted) {
|
||||
return new LegacyMeetingProcessingStatusResponse("completed", 100, STAGE_COMPLETED);
|
||||
}
|
||||
if (isFailed(asrTask)) {
|
||||
|
|
|
|||
Loading…
Reference in New Issue