mirror of
https://github.com/Tencent/WeKnora.git
synced 2026-09-19 02:18:25 +08:00
fix(frontend): route chat drag-and-drop uploads correctly
This commit is contained in:
@@ -124,6 +124,7 @@ const getFileIcon = (fileName: string): string => {
|
||||
defineExpose({
|
||||
attachments,
|
||||
triggerFileSelect,
|
||||
addFiles,
|
||||
clear: () => {
|
||||
attachments.value = [];
|
||||
emit('update:files', []);
|
||||
|
||||
@@ -45,6 +45,41 @@ const imageUploading = ref(false);
|
||||
// Attachment upload state
|
||||
const attachmentUploadRef = ref<InstanceType<typeof AttachmentUpload>>();
|
||||
const uploadedAttachments = ref<AttachmentFile[]>([]);
|
||||
const CHAT_FILE_DROP_EVENT = 'weknora:chat-file-drop';
|
||||
|
||||
const isImageFile = (file: File) => {
|
||||
if (file.type.startsWith('image/')) {
|
||||
return true;
|
||||
}
|
||||
const fileName = file.name.toLowerCase();
|
||||
return ['.jpg', '.jpeg', '.png', '.gif', '.webp', '.bmp'].some(ext => fileName.endsWith(ext));
|
||||
};
|
||||
|
||||
const handleDroppedFiles = (files: File[]) => {
|
||||
if (!files.length) return;
|
||||
|
||||
const imageFiles = files.filter(isImageFile);
|
||||
const attachmentFiles = files.filter(file => !isImageFile(file));
|
||||
|
||||
if (imageFiles.length > 0) {
|
||||
if (isImageUploadEnabledByAgent.value) {
|
||||
addImageFiles(imageFiles);
|
||||
} else {
|
||||
MessagePlugin.warning(t('input.imageUploadDisabledByAgent'));
|
||||
}
|
||||
}
|
||||
|
||||
if (attachmentFiles.length > 0) {
|
||||
attachmentUploadRef.value?.addFiles(attachmentFiles);
|
||||
}
|
||||
};
|
||||
|
||||
const handleChatFileDrop = (event: Event) => {
|
||||
const customEvent = event as CustomEvent<{ files?: File[] }>;
|
||||
const files = customEvent.detail?.files;
|
||||
if (!files || files.length === 0) return;
|
||||
handleDroppedFiles(files);
|
||||
};
|
||||
|
||||
const handleImageSelect = (event: Event) => {
|
||||
const input = event.target as HTMLInputElement;
|
||||
@@ -1372,6 +1407,7 @@ onMounted(() => {
|
||||
loadConversationConfig();
|
||||
loadChatModels();
|
||||
loadAgents();
|
||||
window.addEventListener(CHAT_FILE_DROP_EVENT, handleChatFileDrop as EventListener);
|
||||
|
||||
// 从持久化恢复 fileId -> kbId,刷新后共享知识库文件可带 kb_id 拉取(仅保留当前仍选中的文件)
|
||||
const persisted = settingsStore.settings.selectedFileKbMap;
|
||||
@@ -1427,6 +1463,7 @@ onMounted(() => {
|
||||
});
|
||||
|
||||
onUnmounted(() => {
|
||||
window.removeEventListener(CHAT_FILE_DROP_EVENT, handleChatFileDrop as EventListener);
|
||||
document.removeEventListener('click', closeAgentModeSelector);
|
||||
document.removeEventListener('click', closeModelSelector);
|
||||
document.removeEventListener('click', closeMentionSelector);
|
||||
@@ -1768,11 +1805,8 @@ const onPaste = (e: ClipboardEvent) => {
|
||||
const onDrop = (e: DragEvent) => {
|
||||
e.preventDefault();
|
||||
const files = e.dataTransfer?.files;
|
||||
if (!files) return;
|
||||
const imageFiles = Array.from(files).filter(f => f.type.startsWith('image/'));
|
||||
if (imageFiles.length > 0 && isImageUploadEnabledByAgent.value) {
|
||||
addImageFiles(imageFiles);
|
||||
}
|
||||
if (!files || files.length === 0) return;
|
||||
handleDroppedFiles(Array.from(files));
|
||||
};
|
||||
|
||||
const onDragOver = (e: DragEvent) => {
|
||||
|
||||
@@ -61,6 +61,35 @@ const getCurrentKbId = (): string | null => {
|
||||
return (route.params as any)?.kbId as string || null
|
||||
}
|
||||
|
||||
const CHAT_DROP_ROUTE_NAMES = new Set(['chat', 'globalCreatChat', 'kbCreatChat']);
|
||||
|
||||
const isChatDropRoute = () => {
|
||||
return CHAT_DROP_ROUTE_NAMES.has(String(route.name || ''));
|
||||
}
|
||||
|
||||
const collectDroppedFiles = async (event: DragEvent): Promise<File[]> => {
|
||||
const dataTransferFiles = event.dataTransfer?.files ? Array.from(event.dataTransfer.files) : [];
|
||||
if (dataTransferFiles.length > 0) {
|
||||
return dataTransferFiles;
|
||||
}
|
||||
|
||||
const dataTransferItems = event.dataTransfer?.items ? Array.from(event.dataTransfer.items) : [];
|
||||
if (dataTransferItems.length === 0) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const files = await Promise.all(dataTransferItems.map(item => new Promise<File | null>((resolve) => {
|
||||
const fileEntry = (item as any).webkitGetAsEntry?.();
|
||||
if (fileEntry?.isFile && typeof fileEntry.file === 'function') {
|
||||
fileEntry.file((file: File) => resolve(file), () => resolve(null));
|
||||
return;
|
||||
}
|
||||
resolve(null);
|
||||
})));
|
||||
|
||||
return files.filter((file): file is File => file instanceof File);
|
||||
}
|
||||
|
||||
// 检查知识库初始化状态
|
||||
const checkKnowledgeBaseInitialization = async (): Promise<boolean> => {
|
||||
const currentKbId = getCurrentKbId();
|
||||
@@ -121,27 +150,27 @@ const handleGlobalDrop = async (event: DragEvent) => {
|
||||
event.preventDefault();
|
||||
dragCounter = 0;
|
||||
ismask.value = false;
|
||||
|
||||
const DataTransferFiles = event.dataTransfer?.files ? Array.from(event.dataTransfer.files) : [];
|
||||
const DataTransferItemList = event.dataTransfer?.items ? Array.from(event.dataTransfer.items) : [];
|
||||
|
||||
const droppedFiles = await collectDroppedFiles(event);
|
||||
if (droppedFiles.length === 0) {
|
||||
MessagePlugin.warning(t('knowledgeBase.dragFileNotText'));
|
||||
return;
|
||||
}
|
||||
|
||||
if (isChatDropRoute()) {
|
||||
event.stopPropagation();
|
||||
window.dispatchEvent(new CustomEvent('weknora:chat-file-drop', {
|
||||
detail: { files: droppedFiles }
|
||||
}));
|
||||
return;
|
||||
}
|
||||
|
||||
const isInitialized = await checkKnowledgeBaseInitialization();
|
||||
if (!isInitialized) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (DataTransferFiles.length > 0) {
|
||||
DataTransferFiles.forEach(file => requestMethod(file, uploadInput));
|
||||
} else if (DataTransferItemList.length > 0) {
|
||||
DataTransferItemList.forEach(dataTransferItem => {
|
||||
const fileEntry = dataTransferItem.webkitGetAsEntry() as FileSystemFileEntry | null;
|
||||
if (fileEntry) {
|
||||
fileEntry.file((file: File) => requestMethod(file, uploadInput));
|
||||
}
|
||||
});
|
||||
} else {
|
||||
MessagePlugin.warning(t('knowledgeBase.dragFileNotText'));
|
||||
}
|
||||
|
||||
droppedFiles.forEach(file => requestMethod(file, uploadInput));
|
||||
}
|
||||
|
||||
// 组件挂载时添加全局事件监听器
|
||||
|
||||
Reference in New Issue
Block a user