| | |
| | | import { useEventListener, useFileDialog } from '@vueuse/core'; |
| | | import { ref, type Ref } from 'vue'; |
| | | import { type Ref } from 'vue'; |
| | | import type { Attach } from './useAttach'; |
| | | import { convertFileSize } from '/@/utils/file'; |
| | | |
| | | export type UseUploadFileOptions = { |
| | | pastTarget: Ref<HTMLElement | null>; |
| | | attachFileList: Ref<Attach<UploadFile>[]>; |
| | | }; |
| | | |
| | | export type FileType = 'doc' | 'docx' | 'pdf' | 'md' | 'xls' | 'xlsx' | 'png' | 'jpg' | 'jpeg' | 'gif' | 'json'; |
| | | export type FileGroupType = 'word' | 'pdf' | 'excel' | 'image' | 'json' | 'md'; |
| | | const compareFiles = (file1: File, file2: File) => { |
| | | if (file1.type !== file2.type) return false; |
| | | if (file1.name !== file2.name) return false; |
| | | if (file1.size !== file2.size) return false; |
| | | if (file1.lastModified !== file2.lastModified) return false; |
| | | return true; |
| | | }; |
| | | |
| | | export type FileType = 'doc' | 'docx' | 'pdf' | 'md' | 'xls' | 'xlsx' | 'png' | 'jpg' | 'jpeg' | 'gif' | 'json' | 'txt' | 'csv'; |
| | | export type FileGroupType = 'word' | 'pdf' | 'excel' | 'image' | 'json' | 'md' | 'csv' | 'txt'; |
| | | export type UploadFile = { |
| | | name: string; |
| | | type: FileType; |
| | | groupType: FileGroupType; |
| | | size: string; |
| | | file: File; |
| | | |
| | | icon?: string; |
| | | iconClass?: string; |
| | | previewUrl?: string; |
| | | }; |
| | | |
| | | const getGroupType = (type: FileType): FileGroupType => { |
| | | export const getFileGroupType = (type: FileType): FileGroupType => { |
| | | switch (type) { |
| | | case 'doc': |
| | | case 'docx': |
| | | return 'word'; |
| | | case 'csv': |
| | | return 'csv'; |
| | | case 'txt': |
| | | return 'txt'; |
| | | |
| | | case 'md': |
| | | return 'md'; |
| | |
| | | } |
| | | }; |
| | | |
| | | const getIconByGroupType = (groupType: FileGroupType) => { |
| | | export const getIconByGroupType = (groupType: FileGroupType) => { |
| | | switch (groupType) { |
| | | case 'word': |
| | | return 'word'; |
| | |
| | | return 'pdf'; |
| | | case 'excel': |
| | | return 'excel'; |
| | | case 'csv': |
| | | return 'csv'; |
| | | case 'txt': |
| | | return 'txt'; |
| | | |
| | | case 'json': |
| | | return 'json'; |
| | |
| | | } |
| | | }; |
| | | |
| | | const getIconClassByGroupType = (groupType: FileGroupType) => { |
| | | export const getIconClassByGroupType = (groupType: FileGroupType) => { |
| | | switch (groupType) { |
| | | case 'word': |
| | | return 'text-blue-400'; |
| | |
| | | return 'text-red-400'; |
| | | case 'excel': |
| | | return 'text-green-400'; |
| | | case 'csv': |
| | | return 'text-green-500'; |
| | | case 'txt': |
| | | return 'text-cyan-400'; |
| | | |
| | | case 'json': |
| | | return 'text-yellow-400'; |
| | |
| | | return ''; |
| | | } |
| | | }; |
| | | // const supportFileType = ['doc', 'docx', 'md', 'xls', 'xlsx', 'png', 'jpg', 'jpeg', 'gif', 'json', 'pdf']; |
| | | const supportFileType = ['csv', 'txt']; |
| | | |
| | | export const getFileSuffix = (name: string): FileType => { |
| | | if (!name) return 'txt'; |
| | | const suffix = name.split('.').pop() as FileType; |
| | | return suffix; |
| | | }; |
| | | export const useUploadFile = (options: UseUploadFileOptions) => { |
| | | const supportFileType = ['doc', 'docx', 'md', 'xls', 'xlsx', 'png', 'jpg', 'jpeg', 'gif', 'json', 'pdf']; |
| | | const attachFileList = ref<UploadFile[]>([]); |
| | | |
| | | const parseFiles = (files:FileList) => { |
| | | const { attachFileList } = options; |
| | | const parseFiles = (files: FileList) => { |
| | | const filterFiles: UploadFile[] = []; |
| | | for (const file of files) { |
| | | const suffix = file.name.split('.').pop() as FileType; |
| | | if (attachFileList.value.find((item) => compareFiles(item.model.file, file))) { |
| | | continue; |
| | | } |
| | | const suffix = getFileSuffix(file.name); |
| | | if (supportFileType.includes(suffix)) { |
| | | const groupType = getGroupType(suffix); |
| | | const groupType = getFileGroupType(suffix); |
| | | const uploadFile: UploadFile = { |
| | | type: suffix, |
| | | groupType: groupType, |
| | |
| | | filterFiles.push(uploadFile); |
| | | } |
| | | } |
| | | attachFileList.value.push(...filterFiles); |
| | | } |
| | | attachFileList.value.push( |
| | | ...filterFiles.map( |
| | | (item) => |
| | | ({ |
| | | get title() { |
| | | return item.name; |
| | | }, |
| | | type: 'file', |
| | | model: item, |
| | | get icon() { |
| | | return item.icon; |
| | | }, |
| | | get iconClass() { |
| | | return item.iconClass; |
| | | }, |
| | | } as Attach<UploadFile>) |
| | | ) |
| | | ); |
| | | }; |
| | | |
| | | /** |
| | | * 解析粘贴板文件 |
| | |
| | | event.stopPropagation(); |
| | | const data = event.clipboardData || window.clipboardData; |
| | | const files = data.files as FileList; |
| | | parseFiles(files) |
| | | parseFiles(files); |
| | | }; |
| | | |
| | | const clearFileList = () => { |
| | | attachFileList.value = []; |
| | | }; |
| | | const { |
| | | files, |
| | | open:openFileDialog, |
| | | reset:resetOpenFileDialog, |
| | | open: openFileDialog, |
| | | reset: resetOpenFileDialog, |
| | | onChange: onPickFileChange, |
| | | } = useFileDialog({ |
| | | accept: |
| | | 'application/msword,application/vnd.openxmlformats-officedocument.wordprocessingml.document,text/markdown,application/vnd.ms-excel,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,image/png,image/jpeg,image/gif,application/json,application/pdf', // Set to accept only image files |
| | | reset:true |
| | | accept: 'text/csv,text/plain', // Only accept csv and txt files |
| | | reset: true, |
| | | }); |
| | | |
| | | |
| | | const openFileClick = () =>{ |
| | | const openFileClick = () => { |
| | | openFileDialog(); |
| | | } |
| | | }; |
| | | onPickFileChange((files) => { |
| | | if(!files) return; |
| | | parseFiles(files) |
| | | if (!files) return; |
| | | parseFiles(files); |
| | | }); |
| | | const deleteIndexFile = (index) => { |
| | | const file = attachFileList.value[index]; |
| | | // Revoke object URL for image files |
| | | const deleteUploadFile = (file: UploadFile) => { |
| | | if (file.previewUrl) { |
| | | URL.revokeObjectURL(file.previewUrl); |
| | | } |
| | | attachFileList.value.splice(index, 1); |
| | | }; |
| | | |
| | | useEventListener(options.pastTarget, 'paste', pasteUpload); |
| | | |
| | | return { |
| | | attachFileList, |
| | | clearFileList, |
| | | deleteIndexFile, |
| | | openFileClick |
| | | deleteUploadFile, |
| | | openFileClick, |
| | | }; |
| | | }; |