feat: 更新 Android 会议控制器,添加 ASR 重试和总结重试功能
- 新增 `retryTranscription` 和 `retrySummary` 方法,支持重试 ASR 识别和会议总结 - 更新 `create` 方法,返回 `AndroidMeetingCreateResponse` 对象 - 更新 `list` 方法,返回 `AndroidMeetingListItemVO` 列表 - 添加辅助方法 `buildAndroidMeetingCreateResponse` 和 `buildAndroidMeetingListPage` 用于构建响应对象 - 引入 `h5BaseUrl` 配置项,用于生成会议预览 URLdev_na
parent
11c3ee1b09
commit
1e7a8ad83c
|
|
@ -6,7 +6,9 @@ import com.imeeting.common.MeetingConstants;
|
|||
import com.imeeting.common.SysParamKeys;
|
||||
import com.imeeting.common.exception.ExistingOfflineMeetingException;
|
||||
import com.imeeting.dto.android.AndroidAuthContext;
|
||||
import com.imeeting.dto.android.AndroidMeetingCreateResponse;
|
||||
import com.imeeting.dto.android.AndroidMeetingConfigVo;
|
||||
import com.imeeting.dto.android.AndroidMeetingListItemVO;
|
||||
import com.imeeting.dto.android.AndroidOfflineMeetingConflictVO;
|
||||
import com.imeeting.dto.android.AndroidOfflineMeetingFinishRequest;
|
||||
import com.imeeting.dto.android.AndroidUnifiedMeetingStatusRequest;
|
||||
|
|
@ -51,6 +53,9 @@ import io.swagger.v3.oas.annotations.tags.Tag;
|
|||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.bind.annotation.DeleteMapping;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
|
|
@ -65,7 +70,9 @@ import org.springframework.web.multipart.MultipartFile;
|
|||
import java.io.IOException;
|
||||
import java.math.BigDecimal;
|
||||
import java.math.RoundingMode;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.util.Arrays;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
|
|
@ -84,6 +91,9 @@ public class AndroidMeetingController {
|
|||
private static final String STAGE_SUMMARY_GENERATION = "summary_generation";
|
||||
private static final String STAGE_COMPLETED = "completed";
|
||||
|
||||
@Value("${imeeting.h5.base-url:}")
|
||||
private String h5BaseUrl;
|
||||
|
||||
private final AndroidAuthService androidAuthService;
|
||||
private final AndroidChunkUploadService androidChunkUploadService;
|
||||
private final LegacyMeetingAdapterService legacyMeetingAdapterService;
|
||||
|
|
@ -138,7 +148,7 @@ public class AndroidMeetingController {
|
|||
@io.swagger.v3.oas.annotations.responses.ApiResponse(
|
||||
responseCode = "200",
|
||||
description = "返回新创建的会议详情",
|
||||
content = @Content(schema = @Schema(implementation = MeetingVO.class))
|
||||
content = @Content(schema = @Schema(implementation = AndroidMeetingCreateResponse.class))
|
||||
)
|
||||
})
|
||||
@PostMapping("/create")
|
||||
|
|
@ -153,7 +163,8 @@ public class AndroidMeetingController {
|
|||
// if (existingMeeting != null) {
|
||||
// return new ApiResponse<>("409", "设备端已有会议", meetingQueryService.getDetailIgnoreTenant(existingMeeting.getId()));
|
||||
// }
|
||||
return ApiResponse.ok(legacyMeetingAdapterService.createMeeting(command, authContext, loginUser));
|
||||
MeetingVO meeting = legacyMeetingAdapterService.createMeeting(command, authContext, loginUser);
|
||||
return ApiResponse.ok(buildAndroidMeetingCreateResponse(meeting));
|
||||
} catch (ExistingOfflineMeetingException ex) {
|
||||
return new ApiResponse<>("409", "有未结束会议", new AndroidOfflineMeetingConflictVO(ex.getMeetingId()));
|
||||
}
|
||||
|
|
@ -247,11 +258,11 @@ public class AndroidMeetingController {
|
|||
)
|
||||
})
|
||||
@GetMapping
|
||||
public ApiResponse<PageResult<List<MeetingVO>>> list(HttpServletRequest request,
|
||||
@RequestParam(value = "user_id", required = false) Long ignoredUserId,
|
||||
@RequestParam(defaultValue = "1") Integer page,
|
||||
@RequestParam(value = "page_size", defaultValue = "10") Integer pageSize,
|
||||
@RequestParam(required = false) String title) {
|
||||
public ApiResponse<PageResult<List<AndroidMeetingListItemVO>>> list(HttpServletRequest request,
|
||||
@RequestParam(value = "user_id", required = false) Long ignoredUserId,
|
||||
@RequestParam(defaultValue = "1") Integer page,
|
||||
@RequestParam(value = "page_size", defaultValue = "10") Integer pageSize,
|
||||
@RequestParam(required = false) String title) {
|
||||
AndroidRequestLogHelper.logRequest(log, "Android会议", "分页查询会议接口",
|
||||
"userId", ignoredUserId,
|
||||
"page", page,
|
||||
|
|
@ -259,7 +270,7 @@ public class AndroidMeetingController {
|
|||
"title", title);
|
||||
AndroidAuthContext authContext = androidAuthService.authenticateHttp(request);
|
||||
LoginUser loginUser = AndroidLoginUserSupport.requireLoginUser(authContext);
|
||||
return ApiResponse.ok(meetingQueryService.pageMeetings(
|
||||
PageResult<List<MeetingVO>> result = meetingQueryService.pageMeetings(
|
||||
page,
|
||||
pageSize,
|
||||
title,
|
||||
|
|
@ -269,7 +280,8 @@ public class AndroidMeetingController {
|
|||
"all",
|
||||
null,
|
||||
AndroidLoginUserSupport.isAdmin(authContext)
|
||||
));
|
||||
);
|
||||
return ApiResponse.ok(buildAndroidMeetingListPage(result));
|
||||
}
|
||||
|
||||
@Operation(summary = "查询Android会议预览数据")
|
||||
|
|
@ -323,14 +335,51 @@ public class AndroidMeetingController {
|
|||
.build());
|
||||
}
|
||||
|
||||
@Operation(summary = "更新Android会议访问密码")
|
||||
@Operation(summary = "重试 Android 会议 ASR 识别")
|
||||
@ApiResponses({
|
||||
@io.swagger.v3.oas.annotations.responses.ApiResponse(
|
||||
responseCode = "200",
|
||||
description = "返回更新后的会议访问密码,传空时表示清空访问密码",
|
||||
content = @Content(schema = @Schema(implementation = String.class))
|
||||
description = "重试成功返回 true",
|
||||
content = @Content(schema = @Schema(implementation = Boolean.class))
|
||||
)
|
||||
})
|
||||
@PostMapping("/{meetingId}/transcripts/retry")
|
||||
@Anonymous
|
||||
public ApiResponse<Boolean> retryTranscription(HttpServletRequest request, @PathVariable Long meetingId) {
|
||||
AndroidRequestLogHelper.logRequest(log, "Android会议", "重试会议 ASR 识别接口", "meetingId", meetingId);
|
||||
AndroidAuthContext authContext = androidAuthService.authenticateHttp(request);
|
||||
LoginUser loginUser = authContext.isAnonymous() ? null : AndroidLoginUserSupport.requireLoginUser(authContext);
|
||||
requireOperableOfflineMeeting(meetingId, authContext, loginUser);
|
||||
meetingCommandService.retryTranscription(meetingId);
|
||||
return ApiResponse.ok(true);
|
||||
}
|
||||
|
||||
@Operation(summary = "重试 Android 会议总结")
|
||||
@ApiResponses({
|
||||
@io.swagger.v3.oas.annotations.responses.ApiResponse(
|
||||
responseCode = "200",
|
||||
description = "重试成功返回 true",
|
||||
content = @Content(schema = @Schema(implementation = Boolean.class))
|
||||
)
|
||||
})
|
||||
@PostMapping("/{meetingId}/summary/retry")
|
||||
@Anonymous
|
||||
public ApiResponse<Boolean> retrySummary(HttpServletRequest request, @PathVariable Long meetingId) {
|
||||
AndroidRequestLogHelper.logRequest(log, "Android会议", "重试会议总结接口", "meetingId", meetingId);
|
||||
AndroidAuthContext authContext = androidAuthService.authenticateHttp(request);
|
||||
LoginUser loginUser = authContext.isAnonymous() ? null : AndroidLoginUserSupport.requireLoginUser(authContext);
|
||||
requireOperableOfflineMeeting(meetingId, authContext, loginUser);
|
||||
meetingCommandService.retrySummary(meetingId);
|
||||
return ApiResponse.ok(true);
|
||||
}
|
||||
@Operation(summary = "更新Android会议访问密码")
|
||||
@ApiResponses({
|
||||
@io.swagger.v3.oas.annotations.responses.ApiResponse(
|
||||
responseCode = "200",
|
||||
description = "返回更新后的会议访问密码,传空时表示清空访问密码",
|
||||
content = @Content(schema = @Schema(implementation = String.class))
|
||||
)
|
||||
})
|
||||
@PutMapping("/{meetingId}/access-password")
|
||||
@Log(value = "修改Android会议访问密码", type = "Android会议管理")
|
||||
public ApiResponse<String> updateAccessPassword(HttpServletRequest request,
|
||||
|
|
@ -419,6 +468,67 @@ public class AndroidMeetingController {
|
|||
return ApiResponse.ok(resultVo);
|
||||
}
|
||||
|
||||
private AndroidMeetingCreateResponse buildAndroidMeetingCreateResponse(MeetingVO meeting) {
|
||||
AndroidMeetingCreateResponse response = new AndroidMeetingCreateResponse();
|
||||
if (meeting == null) {
|
||||
return response;
|
||||
}
|
||||
BeanUtils.copyProperties(meeting, response);
|
||||
response.setPreviewUrl(buildPreviewUrl(meeting.getId()));
|
||||
return response;
|
||||
}
|
||||
|
||||
private PageResult<List<AndroidMeetingListItemVO>> buildAndroidMeetingListPage(PageResult<List<MeetingVO>> source) {
|
||||
PageResult<List<AndroidMeetingListItemVO>> result = new PageResult<>();
|
||||
if (source == null) {
|
||||
result.setTotal(0L);
|
||||
result.setRecords(List.of());
|
||||
return result;
|
||||
}
|
||||
result.setTotal(source.getTotal());
|
||||
result.setRecords(source.getRecords() == null
|
||||
? List.of()
|
||||
: source.getRecords().stream().map(this::buildAndroidMeetingListItem).toList());
|
||||
return result;
|
||||
}
|
||||
|
||||
private AndroidMeetingListItemVO buildAndroidMeetingListItem(MeetingVO meeting) {
|
||||
AndroidMeetingListItemVO item = new AndroidMeetingListItemVO();
|
||||
if (meeting == null) {
|
||||
return item;
|
||||
}
|
||||
BeanUtils.copyProperties(meeting, item);
|
||||
item.setPreviewUrl(buildPreviewUrl(meeting.getId()));
|
||||
item.setDayOffset(resolveDayOffset(meeting.getMeetingTime()));
|
||||
return item;
|
||||
}
|
||||
|
||||
private String buildPreviewUrl(Long meetingId) {
|
||||
if (meetingId == null) {
|
||||
return null;
|
||||
}
|
||||
String baseUrl = normalizeH5BaseUrl();
|
||||
if (!StringUtils.hasText(baseUrl)) {
|
||||
return null;
|
||||
}
|
||||
return baseUrl + "/meetings/" + meetingId + "/preview";
|
||||
}
|
||||
|
||||
private String normalizeH5BaseUrl() {
|
||||
String baseUrl = StringUtils.hasText(h5BaseUrl) ? h5BaseUrl.trim() : "";
|
||||
if (!StringUtils.hasText(baseUrl)) {
|
||||
return "";
|
||||
}
|
||||
return baseUrl.endsWith("/") ? baseUrl.substring(0, baseUrl.length() - 1) : baseUrl;
|
||||
}
|
||||
|
||||
private Long resolveDayOffset(LocalDateTime meetingTime) {
|
||||
if (meetingTime == null) {
|
||||
return null;
|
||||
}
|
||||
return ChronoUnit.DAYS.between(LocalDate.now(), meetingTime.toLocalDate());
|
||||
}
|
||||
|
||||
private MeetingVO requireOperableOfflineMeeting(Long meetingId, AndroidAuthContext authContext, LoginUser loginUser) {
|
||||
MeetingVO meeting = meetingQueryService.getDetailIgnoreTenant(meetingId);
|
||||
if (meeting == null) {
|
||||
|
|
|
|||
Loading…
Reference in New Issue