diff --git a/src/views/im/home/composables/useMediaUploader.ts b/src/views/im/home/composables/useMediaUploader.ts index abeade319..bbff4fc9b 100644 --- a/src/views/im/home/composables/useMediaUploader.ts +++ b/src/views/im/home/composables/useMediaUploader.ts @@ -35,7 +35,7 @@ export interface MediaTypeContext { videoCoverUrl?: string } -interface MediaTypeHandler { +export interface MediaTypeHandler { /** 中文名,仅日志用(替代之前散落 9 处的 kind 字符串) */ kind: string /** 由 file + url + context 生成 payload;占位时 url 是 blob URL,commit 时是真实 url */ @@ -201,6 +201,20 @@ export const useMediaUploader = () => { /** 取媒体类型中文名(仅日志用);未注册 type 退化为通用「媒体」 */ const getMediaKind = (type: number): string => mediaTypeHandlers[type]?.kind ?? '媒体' + /** + * 按 type 取 handler,缺则抛错(程序错误集中在这一处) + * + * 调用方拿到的是 `MediaTypeHandler`(非 undefined),不再需要 `!` 断言。 + * 仅给「确定 type 在表里」的调用方用 —— image/file/voice/video 四类入口;通用 dispatcher 仍可用 `mediaTypeHandlers[type]?.` optional chain + */ + const requireMediaHandler = (type: number): MediaTypeHandler => { + const handler = mediaTypeHandlers[type] + if (!handler) { + throw new Error(`[IM] 未注册的媒体类型 ${type}`) + } + return handler + } + /** * 上传完成后的收口校验:会话仍是占位时锁定的那个 + 当前未被禁言;任一不满足 markMediaFailed + 返回 false * @@ -317,6 +331,7 @@ export const useMediaUploader = () => { commitMediaPlaceholder, createUploadProgressHandler, verifyMediaUploadStillAllowed, - getMediaKind + getMediaKind, + requireMediaHandler } } diff --git a/src/views/im/home/pages/conversation/components/input/MessageInput.vue b/src/views/im/home/pages/conversation/components/input/MessageInput.vue index 95d9de8c7..992617b7b 100644 --- a/src/views/im/home/pages/conversation/components/input/MessageInput.vue +++ b/src/views/im/home/pages/conversation/components/input/MessageInput.vue @@ -170,10 +170,7 @@ import { useFriendStore } from '@/views/im/home/store/friendStore' import { useDraftStore } from '@/views/im/home/store/draftStore' import { getMemberDisplayName } from '@/views/im/utils/user' import { useMessageSender } from '@/views/im/home/composables/useMessageSender' -import { - mediaTypeHandlers, - useMediaUploader -} from '@/views/im/home/composables/useMediaUploader' +import { useMediaUploader } from '@/views/im/home/composables/useMediaUploader' import { useMuteOverlay } from '@/views/im/home/composables/useMuteOverlay' import { getConversationKey } from '@/views/im/utils/conversation' import { ImConversationType, ImMessageType } from '@/views/im/utils/constants' @@ -203,7 +200,8 @@ const { markMediaFailed, commitMediaPlaceholder, createUploadProgressHandler, - verifyMediaUploadStillAllowed + verifyMediaUploadStillAllowed, + requireMediaHandler } = useMediaUploader() const editorRef = useTemplateRef('editorRef') @@ -997,13 +995,13 @@ async function uploadAndSendVideo(file: File) { const replyQuote = context.quote const startKey = getConversationKey(conversation) - // 1. 立即占位:blob URL 同时作 url + coverUrl 让