refactor(core): 统一代码格式并更新前端图标

统一前后端代码换行符及 import 语句格式,更新前端项目 logo 图标样式。
dev_na
chenhao 2026-07-28 11:16:16 +08:00
parent 22aefae6cf
commit c296600060
18 changed files with 141 additions and 43 deletions

View File

@ -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";

View File

@ -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,

View File

@ -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,

View File

@ -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")

View File

@ -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,

View File

@ -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,

View File

@ -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("不允许跨平台接管实时会议");
}

View File

@ -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);
}
}

View File

@ -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,

View File

@ -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())

View File

@ -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);

View File

@ -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));

View File

@ -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

View File

@ -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;

View File

@ -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">

View File

@ -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;

View File

@ -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) => (

View File

@ -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";