| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798 |
- import { ref } from 'vue';
- import dayjs from 'dayjs';
- import { message } from 'ant-design-vue';
- import type { AttachedFile } from '/@/views/ventAI/manageAssistent/types/index';
- import { isAudioFile, isCsvFile, isDxfFile, isExcelFile, isTextFile, isVideoFile, isWordFile } from '/@/views/ventAI/manageAssistent/lib/index';
- import type ChatInputArea from '/@/views/ventAI/manageAssistent/components/chat/ChatInputArea.vue';
- /**
- * 输入区附件:文件选择 / 拖拽 / 粘贴三条入口统一走 addFile —— 校验 → 按类型读取(文本/二进制/预览)
- * → 落到待发送状态。三条入口的差别只在「文件从哪来」,校验与分流必须共用一份,否则会各自漂移。
- */
- export const useChatFiles = (getChatInput: () => InstanceType<typeof ChatInputArea> | undefined) => {
- const pendingFile = ref<AttachedFile | null>(null);
- const activeFileReader = ref<FileReader | null>(null);
- const triggerFileUpload = () => {
- getChatInput()?.fileInputRef?.click();
- };
- /**
- * 校验并读入一个文件作为待发送附件。
- * 待发附件是单值(pendingFile),多选/多文件场景由调用方取第一个后再进来。
- */
- const addFile = (file: File): void => {
- // 剪贴板里取到的文件可能没有文件名(部分浏览器的截图项),补一个仅用于展示与分流的名字
- const name = file.name || `粘贴附件_${dayjs().format('HHmmss')}`;
- if (isVideoFile(name) || isAudioFile(name)) {
- message.warning('不支持上传音频和视频文件');
- return;
- }
- try {
- const newFile: AttachedFile = {
- id: `file-${Date.now()}`,
- name,
- size: file.size,
- type: file.type,
- uploadTime: dayjs().format('YYYY-MM-DD HH:mm'),
- originalFile: file,
- };
- // 换附件时中断上一次仍在读取的 FileReader
- if (activeFileReader.value) {
- activeFileReader.value.abort();
- activeFileReader.value = null;
- }
- const reader = new FileReader();
- activeFileReader.value = reader;
- // 读取方式只判断一次:onload 与 readAs* 两处各写一遍条件容易走偏。
- // .dxf 必须在此显式分流到文本:否则会落到 dataURL 分支,附件里只有 preview、拿不到 content,
- // DXF 预览面板只能显示空白。
- const readMode = isTextFile(name) || isCsvFile(name) || isDxfFile(name) ? 'text' : isWordFile(name) || isExcelFile(name) ? 'binary' : 'dataurl';
- reader.onload = (e) => {
- activeFileReader.value = null;
- if (readMode === 'text') {
- newFile.content = e.target?.result as string;
- } else if (readMode === 'binary') {
- newFile.arrayBuffer = e.target?.result as ArrayBuffer;
- } else {
- newFile.preview = e.target?.result as string;
- }
- };
- if (readMode === 'text') {
- reader.readAsText(file);
- } else if (readMode === 'binary') {
- reader.readAsArrayBuffer(file);
- } else {
- reader.readAsDataURL(file);
- }
- pendingFile.value = newFile;
- message.success(`文件 "${name}" 已添加,点击发送按钮提交`);
- } catch (error) {
- console.error('文件处理失败:', error);
- message.error('文件处理失败,请重试');
- }
- };
- const handleFileUpload = (event: Event) => {
- const target = event.target as HTMLInputElement;
- const file = target.files?.[0];
- // 无论是否取到文件都复位,否则再次选择同一个文件不会再触发 change
- target.value = '';
- if (!file) return;
- addFile(file);
- };
- const removePendingFile = () => {
- pendingFile.value = null;
- };
- return { pendingFile, activeFileReader, triggerFileUpload, handleFileUpload, addFile, removePendingFile };
- };
|