parent
22aefae6cf
commit
c296600060
|
|
@ -4,9 +4,6 @@ public final class MeetingConstants {
|
|||
public static final String TYPE_OFFLINE = "OFFLINE";
|
||||
public static final String TYPE_REALTIME = "REALTIME";
|
||||
|
||||
public static final String SOURCE_WEB = "WEB";
|
||||
public static final String SOURCE_ANDROID = "ANDROID";
|
||||
|
||||
public static final String DEVICE_MODE_PUBLIC = "PUBLIC";
|
||||
public static final String DEVICE_MODE_PRIVATE = "PRIVATE";
|
||||
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ import com.imeeting.dto.biz.RealtimeMeetingCompleteDTO;
|
|||
import com.imeeting.dto.biz.RealtimeMeetingRuntimeProfile;
|
||||
import com.imeeting.dto.biz.RealtimeMeetingSessionStatusVO;
|
||||
import com.imeeting.entity.biz.Meeting;
|
||||
import com.imeeting.enums.MeetingTerminalEnum;
|
||||
import com.imeeting.service.android.AndroidAuthService;
|
||||
import com.imeeting.service.biz.MeetingAccessService;
|
||||
import com.imeeting.service.biz.MeetingAuthorizationService;
|
||||
|
|
@ -96,7 +97,7 @@ public class AndroidMeetingRealtimeController {
|
|||
authContext.getTenantId(),
|
||||
authContext.getUserId(),
|
||||
resolveCreatorName(authContext),
|
||||
MeetingConstants.SOURCE_ANDROID
|
||||
MeetingTerminalEnum.CUSTOM_TERMINAL.getCode()
|
||||
);
|
||||
|
||||
RealtimeMeetingSessionStatusVO status = realtimeMeetingSessionStateService.getStatus(meeting.getId());
|
||||
|
|
@ -166,7 +167,7 @@ public class AndroidMeetingRealtimeController {
|
|||
AndroidRequestLogHelper.logRequest(log, "Android实时会议", "暂停实时会议接口", "meetingId", id);
|
||||
AndroidAuthContext authContext = androidAuthService.authenticateHttp(request);
|
||||
Meeting meeting = meetingAccessService.requireMeeting(id);
|
||||
meetingAuthorizationService.assertCanControlRealtimeMeeting(meeting, authContext, MeetingConstants.SOURCE_ANDROID);
|
||||
meetingAuthorizationService.assertCanControlRealtimeMeeting(meeting, authContext, MeetingTerminalEnum.CUSTOM_TERMINAL.getCode());
|
||||
return ApiResponse.ok(realtimeMeetingSessionStateService.pause(id));
|
||||
}
|
||||
|
||||
|
|
@ -185,7 +186,7 @@ public class AndroidMeetingRealtimeController {
|
|||
AndroidRequestLogHelper.logRequest(log, "Android实时会议", "完成实时会议接口", "meetingId", id, "request", dto);
|
||||
AndroidAuthContext authContext = androidAuthService.authenticateHttp(request);
|
||||
Meeting meeting = meetingAccessService.requireMeeting(id);
|
||||
meetingAuthorizationService.assertCanControlRealtimeMeeting(meeting, authContext, MeetingConstants.SOURCE_ANDROID);
|
||||
meetingAuthorizationService.assertCanControlRealtimeMeeting(meeting, authContext, MeetingTerminalEnum.CUSTOM_TERMINAL.getCode());
|
||||
meetingCommandService.completeRealtimeMeeting(
|
||||
id,
|
||||
dto != null ? dto.getAudioUrl() : null,
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ import com.imeeting.dto.biz.UpdateMeetingSummaryCommand;
|
|||
import com.imeeting.dto.biz.UpdateMeetingTranscriptCommand;
|
||||
import com.imeeting.entity.biz.AiTask;
|
||||
import com.imeeting.entity.biz.Meeting;
|
||||
import com.imeeting.enums.MeetingTerminalEnum;
|
||||
import com.imeeting.service.biz.AiTaskService;
|
||||
import com.imeeting.service.biz.MeetingAccessService;
|
||||
import com.imeeting.service.biz.MeetingCommandService;
|
||||
|
|
@ -242,7 +243,7 @@ public class MeetingController {
|
|||
loginUser.getTenantId(),
|
||||
loginUser.getUserId(),
|
||||
resolveCreatorName(loginUser),
|
||||
MeetingConstants.SOURCE_WEB
|
||||
MeetingTerminalEnum.WEB.getCode()
|
||||
));
|
||||
}
|
||||
|
||||
|
|
@ -258,7 +259,7 @@ public class MeetingController {
|
|||
loginUser.getTenantId(),
|
||||
loginUser.getUserId(),
|
||||
resolveCreatorName(loginUser),
|
||||
MeetingConstants.SOURCE_WEB
|
||||
MeetingTerminalEnum.WEB.getCode()
|
||||
));
|
||||
}
|
||||
|
||||
|
|
@ -405,7 +406,7 @@ public class MeetingController {
|
|||
public ApiResponse<RealtimeMeetingSessionStatusVO> pauseRealtimeMeeting(@PathVariable Long id) {
|
||||
LoginUser loginUser = currentLoginUser();
|
||||
Meeting meeting = meetingAccessService.requireMeeting(id);
|
||||
meetingAccessService.assertCanControlRealtimeMeeting(meeting, loginUser, MeetingConstants.SOURCE_WEB);
|
||||
meetingAccessService.assertCanControlRealtimeMeeting(meeting, loginUser, MeetingTerminalEnum.WEB.getCode());
|
||||
return ApiResponse.ok(realtimeMeetingSessionStateService.pause(id));
|
||||
}
|
||||
|
||||
|
|
@ -436,7 +437,7 @@ public class MeetingController {
|
|||
public ApiResponse<Boolean> completeRealtimeMeeting(@PathVariable Long id, @RequestBody(required = false) RealtimeMeetingCompleteDTO dto) {
|
||||
LoginUser loginUser = currentLoginUser();
|
||||
Meeting meeting = meetingAccessService.requireMeeting(id);
|
||||
meetingAccessService.assertCanControlRealtimeMeeting(meeting, loginUser, MeetingConstants.SOURCE_WEB);
|
||||
meetingAccessService.assertCanControlRealtimeMeeting(meeting, loginUser, MeetingTerminalEnum.WEB.getCode());
|
||||
meetingCommandService.completeRealtimeMeeting(
|
||||
id,
|
||||
dto != null ? dto.getAudioUrl() : null,
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ public class CreateMeetingCommand {
|
|||
@NotBlank(message = "音频地址不能为空")
|
||||
private String audioUrl;
|
||||
|
||||
@NotNull(message = "asrModelId must not be null")
|
||||
// @NotNull(message = "asrModelId must not be null")
|
||||
private Long asrModelId;
|
||||
|
||||
@NotNull(message = "summaryModelId must not be null")
|
||||
|
|
|
|||
|
|
@ -13,6 +13,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.MeetingTerminalEnum;
|
||||
import com.imeeting.enums.MeetingStatusEnum;
|
||||
import com.imeeting.mapper.biz.LlmModelMapper;
|
||||
import com.imeeting.mapper.biz.MeetingTranscriptMapper;
|
||||
|
|
@ -137,7 +138,7 @@ public class LegacyMeetingAdapterServiceImpl implements LegacyMeetingAdapterServ
|
|||
normalizeTags(request.getTags()),
|
||||
null,
|
||||
MeetingConstants.TYPE_OFFLINE,
|
||||
MeetingConstants.SOURCE_ANDROID,
|
||||
MeetingTerminalEnum.CUSTOM_TERMINAL.getCode(),
|
||||
tenantId,
|
||||
creatorUserId,
|
||||
resolvedCreatorName,
|
||||
|
|
|
|||
|
|
@ -18,6 +18,14 @@ import java.util.List;
|
|||
public interface MeetingCommandService {
|
||||
MeetingVO createMeeting(CreateMeetingCommand command, Long tenantId, Long creatorId, String creatorName, String meetingSource);
|
||||
|
||||
MeetingVO createMeeting(CreateMeetingCommand command,
|
||||
Long tenantId,
|
||||
Long creatorId,
|
||||
String creatorName,
|
||||
String meetingSource,
|
||||
String sourceDeviceCode,
|
||||
String sourceDeviceMode);
|
||||
|
||||
MeetingVO createRealtimeMeeting(CreateRealtimeMeetingCommand command, Long tenantId, Long creatorId, String creatorName, String meetingSource);
|
||||
|
||||
MeetingVO createPublicDeviceMeeting(PublicDeviceMeetingCreateCommand command,
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ package com.imeeting.service.biz.impl;
|
|||
|
||||
import com.imeeting.common.MeetingConstants;
|
||||
import com.imeeting.entity.biz.Meeting;
|
||||
import com.imeeting.enums.MeetingTerminalEnum;
|
||||
import com.imeeting.mapper.biz.MeetingMapper;
|
||||
import com.imeeting.service.biz.MeetingAccessService;
|
||||
import com.unisbase.security.LoginUser;
|
||||
|
|
@ -106,6 +107,10 @@ public class MeetingAccessServiceImpl implements MeetingAccessService {
|
|||
if (meeting.getMeetingSource() == null || meeting.getMeetingSource().isBlank()) {
|
||||
return;
|
||||
}
|
||||
if (MeetingTerminalEnum.isCustomTerminalSource(meeting.getMeetingSource())
|
||||
&& MeetingTerminalEnum.isCustomTerminalSource(currentPlatform)) {
|
||||
return;
|
||||
}
|
||||
if (!meeting.getMeetingSource().equalsIgnoreCase(currentPlatform)) {
|
||||
throw new RuntimeException("不允许跨平台接管实时会议");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ package com.imeeting.service.biz.impl;
|
|||
import com.imeeting.common.MeetingConstants;
|
||||
import com.imeeting.dto.android.AndroidAuthContext;
|
||||
import com.imeeting.entity.biz.Meeting;
|
||||
import com.imeeting.enums.MeetingTerminalEnum;
|
||||
import com.imeeting.service.biz.MeetingAccessService;
|
||||
import com.imeeting.service.biz.MeetingAuthorizationService;
|
||||
import com.unisbase.security.LoginUser;
|
||||
|
|
@ -47,7 +48,7 @@ public class MeetingAuthorizationServiceImpl implements MeetingAuthorizationServ
|
|||
}
|
||||
if (meeting.getMeetingSource() != null
|
||||
&& !meeting.getMeetingSource().isBlank()
|
||||
&& !meeting.getMeetingSource().equalsIgnoreCase(currentPlatform)) {
|
||||
&& !isSameRealtimePlatform(meeting.getMeetingSource(), currentPlatform)) {
|
||||
throw new RuntimeException("不允许跨平台接管实时会议");
|
||||
}
|
||||
return;
|
||||
|
|
@ -74,4 +75,8 @@ public class MeetingAuthorizationServiceImpl implements MeetingAuthorizationServ
|
|||
loginUser.setDisplayName(authContext.getDisplayName());
|
||||
return loginUser;
|
||||
}
|
||||
|
||||
private boolean isSameRealtimePlatform(String meetingSource, String currentPlatform) {
|
||||
return MeetingTerminalEnum.isSameTerminal(meetingSource, currentPlatform);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ import com.imeeting.entity.biz.Meeting;
|
|||
import com.imeeting.entity.biz.MeetingTranscript;
|
||||
import com.imeeting.entity.biz.MeetingTranscriptChapterVersion;
|
||||
import com.imeeting.enums.BusinessErrorCodeEnum;
|
||||
import com.imeeting.enums.MeetingTerminalEnum;
|
||||
import com.imeeting.enums.MeetingStatusEnum;
|
||||
import com.imeeting.service.android.AndroidPendingMeetingDraftService;
|
||||
import com.imeeting.service.android.AndroidPushMessageService;
|
||||
|
|
@ -152,6 +153,18 @@ public class MeetingCommandServiceImpl implements MeetingCommandService {
|
|||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public MeetingVO createMeeting(CreateMeetingCommand command, Long tenantId, Long creatorId, String creatorName, String meetingSource) {
|
||||
return createMeeting(command, tenantId, creatorId, creatorName, meetingSource, null, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public MeetingVO createMeeting(CreateMeetingCommand command,
|
||||
Long tenantId,
|
||||
Long creatorId,
|
||||
String creatorName,
|
||||
String meetingSource,
|
||||
String sourceDeviceCode,
|
||||
String sourceDeviceMode) {
|
||||
RealtimeMeetingRuntimeProfile runtimeProfile = resolveCreateProfile(command, tenantId);
|
||||
Long hostUserId = resolveHostUserId(command.getHostUserId(), creatorId);
|
||||
String resolvedCreatorName = resolveMeetingUserName(creatorId, creatorName);
|
||||
|
|
@ -160,7 +173,7 @@ public class MeetingCommandServiceImpl implements MeetingCommandService {
|
|||
Meeting meeting = meetingDomainSupport.initMeeting(command.getTitle(), command.getMeetingTime(), command.getParticipants(), command.getTags(),
|
||||
command.getAudioUrl(), MeetingConstants.TYPE_OFFLINE, meetingSource, tenantId, creatorId, resolvedCreatorName,
|
||||
hostUserId, hostName, runtimeProfile.getResolvedSummaryModelId(), runtimeProfile.getResolvedPromptId(),
|
||||
runtimeProfile.getResolvedHotWordGroupId(), summaryDetailLevel, 0);
|
||||
runtimeProfile.getResolvedHotWordGroupId(), summaryDetailLevel, 0, sourceDeviceCode, sourceDeviceMode);
|
||||
meetingService.save(meeting);
|
||||
|
||||
AiTask asrTask = new AiTask();
|
||||
|
|
@ -310,7 +323,7 @@ public class MeetingCommandServiceImpl implements MeetingCommandService {
|
|||
command.getTags(),
|
||||
null,
|
||||
MeetingConstants.TYPE_OFFLINE,
|
||||
MeetingConstants.SOURCE_ANDROID,
|
||||
MeetingTerminalEnum.CUSTOM_TERMINAL.getCode(),
|
||||
tenantId,
|
||||
creatorId,
|
||||
resolvedCreatorName,
|
||||
|
|
|
|||
|
|
@ -11,6 +11,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.MeetingTerminalEnum;
|
||||
import com.imeeting.enums.MeetingStatusEnum;
|
||||
import com.imeeting.mapper.biz.AiTaskMapper;
|
||||
import com.imeeting.mapper.biz.MeetingMapper;
|
||||
|
|
@ -163,17 +164,23 @@ public class MeetingUnifiedStatusServiceImpl implements MeetingUnifiedStatusServ
|
|||
private boolean isAndroidOfflineEmptyUploadFailure(MeetingVO meeting) {
|
||||
return meeting != null
|
||||
&& MeetingConstants.TYPE_OFFLINE.equalsIgnoreCase(meeting.getMeetingType())
|
||||
&& MeetingConstants.SOURCE_ANDROID.equalsIgnoreCase(meeting.getMeetingSource())
|
||||
&& MeetingTerminalEnum.isCustomTerminalSource(meeting.getMeetingSource())
|
||||
&& hasNoAudioUrl(meeting)
|
||||
&& "FAILED".equalsIgnoreCase(meeting.getAudioSaveStatus());
|
||||
}
|
||||
|
||||
private boolean isAndroidOfflineMeetingWaitingUpload(MeetingVO meeting) {
|
||||
return meeting != null
|
||||
&& MeetingConstants.TYPE_OFFLINE.equalsIgnoreCase(meeting.getMeetingType())
|
||||
&& MeetingConstants.SOURCE_ANDROID.equalsIgnoreCase(meeting.getMeetingSource())
|
||||
&& MeetingTerminalEnum.isCustomTerminalSource(meeting.getMeetingSource())
|
||||
&& hasNoAudioUrl(meeting)
|
||||
&& !MeetingConstants.OFFLINE_RECORDING_UPLOAD_FINISHED.equalsIgnoreCase(meeting.getOfflineRecordingStatus());
|
||||
}
|
||||
|
||||
private boolean hasNoAudioUrl(MeetingVO meeting) {
|
||||
return meeting.getAudioUrl() == null || meeting.getAudioUrl().isBlank();
|
||||
}
|
||||
|
||||
private boolean isSummarizing(MeetingUnifiedStageContext context) {
|
||||
return isTaskRunning(context.summaryTask())
|
||||
|| isTaskRunning(context.chapterTask())
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import com.imeeting.dto.biz.RealtimeMeetingSessionStatusVO;
|
|||
import com.imeeting.dto.biz.RealtimeSocketSessionData;
|
||||
import com.imeeting.dto.biz.RealtimeSocketSessionVO;
|
||||
import com.imeeting.entity.biz.Meeting;
|
||||
import com.imeeting.enums.MeetingTerminalEnum;
|
||||
import com.imeeting.service.biz.AiModelService;
|
||||
import com.imeeting.service.biz.MeetingAccessService;
|
||||
import com.imeeting.service.biz.RealtimeMeetingSessionStateService;
|
||||
|
|
@ -49,7 +50,7 @@ public class RealtimeMeetingSocketSessionServiceImpl implements RealtimeMeetingS
|
|||
}
|
||||
|
||||
Meeting meeting = meetingAccessService.requireMeeting(meetingId);
|
||||
meetingAccessService.assertCanControlRealtimeMeeting(meeting, loginUser, MeetingConstants.SOURCE_WEB);
|
||||
meetingAccessService.assertCanControlRealtimeMeeting(meeting, loginUser, MeetingTerminalEnum.WEB.getCode());
|
||||
|
||||
realtimeMeetingSessionStateService.initSessionIfAbsent(meetingId, loginUser.getTenantId(), loginUser.getUserId());
|
||||
realtimeMeetingSessionStateService.assertCanOpenSession(meetingId);
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ package com.imeeting.service.biz.impl;
|
|||
|
||||
import com.imeeting.common.MeetingConstants;
|
||||
import com.imeeting.entity.biz.Meeting;
|
||||
import com.imeeting.enums.MeetingTerminalEnum;
|
||||
import com.imeeting.mapper.biz.MeetingMapper;
|
||||
import com.unisbase.security.LoginUser;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
|
@ -16,33 +17,41 @@ class MeetingAccessServiceImplTest {
|
|||
|
||||
@Test
|
||||
void allowsRealtimeControlFromSourcePlatform() {
|
||||
Meeting meeting = buildMeeting(MeetingConstants.TYPE_REALTIME, MeetingConstants.SOURCE_ANDROID);
|
||||
Meeting meeting = buildMeeting(MeetingConstants.TYPE_REALTIME, MeetingTerminalEnum.CUSTOM_TERMINAL.getCode());
|
||||
LoginUser loginUser = buildLoginUser();
|
||||
|
||||
assertDoesNotThrow(() -> service.assertCanControlRealtimeMeeting(meeting, loginUser, MeetingTerminalEnum.CUSTOM_TERMINAL.getCode()));
|
||||
}
|
||||
|
||||
@Test
|
||||
void allowsCustomTerminalToControlLegacyAndroidRealtimeMeeting() {
|
||||
Meeting meeting = buildMeeting(MeetingConstants.TYPE_REALTIME, "ANDROID");
|
||||
LoginUser loginUser = buildLoginUser();
|
||||
|
||||
assertDoesNotThrow(() -> service.assertCanControlRealtimeMeeting(meeting, loginUser, MeetingConstants.SOURCE_ANDROID));
|
||||
assertDoesNotThrow(() -> service.assertCanControlRealtimeMeeting(meeting, loginUser, MeetingTerminalEnum.CUSTOM_TERMINAL.getCode()));
|
||||
}
|
||||
|
||||
@Test
|
||||
void rejectsCrossPlatformRealtimeControl() {
|
||||
Meeting meeting = buildMeeting(MeetingConstants.TYPE_REALTIME, MeetingConstants.SOURCE_ANDROID);
|
||||
Meeting meeting = buildMeeting(MeetingConstants.TYPE_REALTIME, MeetingTerminalEnum.CUSTOM_TERMINAL.getCode());
|
||||
LoginUser loginUser = buildLoginUser();
|
||||
|
||||
assertThrows(RuntimeException.class,
|
||||
() -> service.assertCanControlRealtimeMeeting(meeting, loginUser, MeetingConstants.SOURCE_WEB));
|
||||
() -> service.assertCanControlRealtimeMeeting(meeting, loginUser, MeetingTerminalEnum.WEB.getCode()));
|
||||
}
|
||||
|
||||
@Test
|
||||
void rejectsRealtimeControlForOfflineMeeting() {
|
||||
Meeting meeting = buildMeeting(MeetingConstants.TYPE_OFFLINE, MeetingConstants.SOURCE_WEB);
|
||||
Meeting meeting = buildMeeting(MeetingConstants.TYPE_OFFLINE, MeetingTerminalEnum.WEB.getCode());
|
||||
LoginUser loginUser = buildLoginUser();
|
||||
|
||||
assertThrows(RuntimeException.class,
|
||||
() -> service.assertCanControlRealtimeMeeting(meeting, loginUser, MeetingConstants.SOURCE_WEB));
|
||||
() -> service.assertCanControlRealtimeMeeting(meeting, loginUser, MeetingTerminalEnum.WEB.getCode()));
|
||||
}
|
||||
|
||||
@Test
|
||||
void allowsParticipantToViewAndExportButNotEdit() {
|
||||
Meeting meeting = buildMeeting(MeetingConstants.TYPE_OFFLINE, MeetingConstants.SOURCE_WEB);
|
||||
Meeting meeting = buildMeeting(MeetingConstants.TYPE_OFFLINE, MeetingTerminalEnum.WEB.getCode());
|
||||
meeting.setParticipants("201,202,203");
|
||||
LoginUser participant = new LoginUser(202L, 100L, "participant", false, false, null);
|
||||
|
||||
|
|
@ -54,7 +63,7 @@ class MeetingAccessServiceImplTest {
|
|||
|
||||
@Test
|
||||
void allowsTenantAdminToEditMeeting() {
|
||||
Meeting meeting = buildMeeting(MeetingConstants.TYPE_OFFLINE, MeetingConstants.SOURCE_WEB);
|
||||
Meeting meeting = buildMeeting(MeetingConstants.TYPE_OFFLINE, MeetingTerminalEnum.WEB.getCode());
|
||||
LoginUser tenantAdmin = new LoginUser(300L, 100L, "tenant-admin", false, true, null);
|
||||
|
||||
assertDoesNotThrow(() -> service.assertCanEditMeeting(meeting, tenantAdmin));
|
||||
|
|
|
|||
|
|
@ -1,14 +1,33 @@
|
|||
<svg width="32" height="32" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect width="32" height="32" rx="10" fill="#2D6BFF"/>
|
||||
<g transform="translate(16 15.6) rotate(35)" stroke="white" fill="none" stroke-width="1.8">
|
||||
<rect x="-5.2" y="-10.2" width="10.4" height="10.4" rx="5.2"/>
|
||||
<path d="M-2.2 0.2 H2.2 L1.1 10.4 H-1.1 Z"/>
|
||||
<g clip-path="url(#clip0_441_732)">
|
||||
<rect width="32" height="32" rx="8" fill="url(#paint0_linear_441_732)"/>
|
||||
<path
|
||||
d="M20 22C20 19.7909 18.2091 18 16 18C13.7909 18 12 19.7909 12 22V11C12 13.2091 13.7909 15 16 15C18.2091 15 20 13.2091 20 11V22Z"
|
||||
fill="url(#paint1_linear_441_732)"/>
|
||||
<rect x="5" y="6" width="7" height="20" rx="3.5" fill="url(#paint2_linear_441_732)"/>
|
||||
<rect x="20" y="8" width="7" height="16" rx="3.5" fill="url(#paint3_linear_441_732)"/>
|
||||
</g>
|
||||
<path
|
||||
d="M12.5 22.6 C14.2 21.6 16 21.6 17.8 22.6 S21.4 23.8 23.2 22.6"
|
||||
stroke="white"
|
||||
stroke-width="1.8"
|
||||
stroke-linecap="round"
|
||||
fill="none"
|
||||
/>
|
||||
<defs>
|
||||
<linearGradient id="paint0_linear_441_732" x1="16" y1="2.45643e-07" x2="24.2424" y2="32"
|
||||
gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#FBFBFB"/>
|
||||
<stop offset="1" stop-color="#D7E4F0"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint1_linear_441_732" x1="19.625" y1="15.625" x2="12.125" y2="15.75"
|
||||
gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#0088FF"/>
|
||||
<stop offset="1" stop-color="#06CEEB"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint2_linear_441_732" x1="8.5" y1="6" x2="8.5" y2="26" gradientUnits="userSpaceOnUse">
|
||||
<stop offset="0.408628" stop-color="#0088FF"/>
|
||||
<stop offset="1" stop-color="#006AFF"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint3_linear_441_732" x1="23.5" y1="8" x2="23.5" y2="24" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#20E3FF"/>
|
||||
<stop offset="0.919108" stop-color="#00CAE7"/>
|
||||
</linearGradient>
|
||||
<clipPath id="clip0_441_732">
|
||||
<rect width="32" height="32" fill="white"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 543 B After Width: | Height: | Size: 1.6 KiB |
|
|
@ -5,6 +5,7 @@ const MEETING_UPLOAD_FLOW_TIMEOUT = 600000;
|
|||
const MEETING_DETAIL_TIMEOUT = 120000;
|
||||
|
||||
export type SummaryDetailLevel = "DETAILED" | "STANDARD" | "BRIEF";
|
||||
export type MeetingSource = "WINDOWS" | "MACOS" | "KYLIN" | "UOS" | "HARMONYOS" | "WEB" | "CUSTOM_TERMINAL" | "ANDROID";
|
||||
|
||||
export interface MeetingCreateConfig {
|
||||
offlineEnabled: boolean;
|
||||
|
|
@ -30,7 +31,7 @@ export interface MeetingVO {
|
|||
audioUrl: string;
|
||||
playbackAudioUrl?: string;
|
||||
meetingType?: "OFFLINE" | "REALTIME";
|
||||
meetingSource?: "WEB" | "ANDROID";
|
||||
meetingSource?: MeetingSource;
|
||||
sourceDeviceCode?: string;
|
||||
sourceDeviceMode?: "PUBLIC" | "PRIVATE";
|
||||
summaryDetailLevel?: SummaryDetailLevel;
|
||||
|
|
|
|||
|
|
@ -86,6 +86,16 @@ const DEFAULT_CREATE_CONFIG: MeetingCreateConfig = {
|
|||
realtimeEnabled: true,
|
||||
offlineAudioMaxSizeMb: 1024,
|
||||
};
|
||||
const MEETING_SOURCE_LABELS: Record<string, string> = {
|
||||
WINDOWS: "Windows",
|
||||
MACOS: "macOS",
|
||||
KYLIN: "麒麟",
|
||||
UOS: "统信",
|
||||
HARMONYOS: "鸿蒙",
|
||||
WEB: "Web端",
|
||||
CUSTOM_TERMINAL: "定制终端",
|
||||
ANDROID: "定制终端",
|
||||
};
|
||||
|
||||
const isRealtimeMeetingCandidate = (item: MeetingVO) =>
|
||||
item.meetingType === "REALTIME" || (!item.meetingType && item.status === 0 && !item.audioUrl);
|
||||
|
|
@ -94,7 +104,7 @@ const canControlRealtimeFromCurrentPlatform = (item: MeetingVO) =>
|
|||
!item.meetingSource || item.meetingSource === CURRENT_PLATFORM;
|
||||
|
||||
const getMeetingSourceLabel = (source?: MeetingVO["meetingSource"]) =>
|
||||
source === "ANDROID" ? "安卓端" : "Web端";
|
||||
source ? (MEETING_SOURCE_LABELS[source] ?? source) : MEETING_SOURCE_LABELS.WEB;
|
||||
|
||||
const getRealtimeSourceLabel = (item: MeetingVO) => getMeetingSourceLabel(item.meetingSource);
|
||||
|
||||
|
|
@ -313,7 +323,7 @@ const MeetingCardItem: React.FC<{
|
|||
? (progress?.message || progress?.unifiedStatus?.message || config.text)
|
||||
: (progress?.unifiedStatus?.message || progress?.message || "深度分析中...");
|
||||
|
||||
const sourceColor = item.meetingSource === "ANDROID" ? "#10b981" : "#3b82f6";
|
||||
const sourceColor = item.meetingSource === "CUSTOM_TERMINAL" || item.meetingSource === "ANDROID" ? "#10b981" : "#3b82f6";
|
||||
|
||||
return (
|
||||
<List.Item className="meeting-card-list-item">
|
||||
|
|
|
|||
|
|
@ -29,6 +29,16 @@ import {
|
|||
const SAMPLE_RATE = 16000;
|
||||
const CHUNK_SIZE = 1280;
|
||||
const CURRENT_PLATFORM = "WEB" as const;
|
||||
const MEETING_SOURCE_LABELS: Record<string, string> = {
|
||||
WINDOWS: "Windows",
|
||||
MACOS: "macOS",
|
||||
KYLIN: "麒麟",
|
||||
UOS: "统信",
|
||||
HARMONYOS: "鸿蒙",
|
||||
WEB: "Web端",
|
||||
CUSTOM_TERMINAL: "定制终端",
|
||||
ANDROID: "定制终端",
|
||||
};
|
||||
|
||||
type WsSpeaker = string | { name?: string; user_id?: string | number } | undefined;
|
||||
type WsMessage = {
|
||||
|
|
@ -283,7 +293,7 @@ export function RealtimeAsrSession() {
|
|||
return;
|
||||
}
|
||||
if (detail.meetingSource && detail.meetingSource !== CURRENT_PLATFORM) {
|
||||
const sourceLabel = detail.meetingSource === "ANDROID" ? "安卓端" : "Web 端";
|
||||
const sourceLabel = MEETING_SOURCE_LABELS[detail.meetingSource] ?? detail.meetingSource;
|
||||
message.warning(`该实时会议需在${sourceLabel}继续,当前仅支持查看详情`);
|
||||
navigate(`/meetings/${meetingId}`);
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -36,6 +36,16 @@ type RecentCard = {
|
|||
};
|
||||
|
||||
const RECENT_CARD_READ_STORAGE_KEY = "home_recent_card_read_ids";
|
||||
const MEETING_SOURCE_LABELS: Record<string, string> = {
|
||||
WINDOWS: "Windows",
|
||||
MACOS: "macOS",
|
||||
KYLIN: "麒麟",
|
||||
UOS: "统信",
|
||||
HARMONYOS: "鸿蒙",
|
||||
WEB: "Web端",
|
||||
CUSTOM_TERMINAL: "定制终端",
|
||||
ANDROID: "定制终端",
|
||||
};
|
||||
|
||||
const fallbackRecentCards: RecentCard[] = [
|
||||
{
|
||||
|
|
@ -314,7 +324,7 @@ export default function HomePage() {
|
|||
<div className="home-recent-card-tags">
|
||||
{recentTaskMap.get(String(card.id))?.meetingSource && (
|
||||
<Tag key={`${card.id}-source`} className="home-recent-card-tag" bordered={false}>
|
||||
{recentTaskMap.get(String(card.id))?.meetingSource === "ANDROID" ? "安卓端" : "Web端"}
|
||||
{MEETING_SOURCE_LABELS[recentTaskMap.get(String(card.id))?.meetingSource ?? "WEB"] ?? "Web端"}
|
||||
</Tag>
|
||||
)}
|
||||
{card.tags.slice(0, 4).map((tag) => (
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ export interface MeetingVO {
|
|||
playbackAudioUrl?: string;
|
||||
duration?: number;
|
||||
meetingType?: "OFFLINE" | "REALTIME";
|
||||
meetingSource?: "WEB" | "ANDROID";
|
||||
meetingSource?: "WINDOWS" | "MACOS" | "KYLIN" | "UOS" | "HARMONYOS" | "WEB" | "CUSTOM_TERMINAL" | "ANDROID";
|
||||
sourceDeviceCode?: string;
|
||||
sourceDeviceMode?: "PUBLIC" | "PRIVATE";
|
||||
summaryDetailLevel?: "DETAILED" | "STANDARD" | "BRIEF";
|
||||
|
|
|
|||
Loading…
Reference in New Issue