import { onMounted, onUnmounted } from 'vue' import { storeToRefs } from 'pinia' import { useMainStore } from '@/store' import { getImageDataURL } from '@/utils/image' import usePasteTextClipboardData from './usePasteTextClipboardData' import useCreateElement from './useCreateElement' /** * 上传 File 到 S3,返回公开访问的 URL */ const uploadFileToS3 = (file: File): Promise => { return new Promise((resolve, reject) => { if (typeof window === 'undefined' || !window.AWS) { reject(new Error('AWS SDK not available')) return } const credentials = { accessKeyId: 'AKIATLPEDU37QV5CHLMH', secretAccessKey: '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', } window.AWS.config.update(credentials) window.AWS.config.region = 'cn-northwest-1' const bucket = new window.AWS.S3({ params: { Bucket: 'ccrb' }, httpOptions: { timeout: 600000 // 10分钟超时 } }) const ext = file.name.split('.').pop() || 'bin' const key = `${file.name.split('.')[0]}_${Date.now()}.${ext}` const params = { Key: 'pptto/' + key, ContentType: file.type, Body: file, ACL: 'public-read', } const options = { partSize: 5 * 1024 * 1024, // 2GB 分片,可酌情调小 queueSize: 2, leavePartsOnError: true, } bucket .upload(params, options) .promise() .then(data => resolve(data.Location)) .catch(err => reject(err)) }) } export default () => { const { editorAreaFocus, thumbnailsFocus, disableHotkeys } = storeToRefs(useMainStore()) const { pasteTextClipboardData } = usePasteTextClipboardData() const { createImageElement } = useCreateElement() // 粘贴图片到幻灯片元素 const pasteImageFile = (imageFile: File) => { // getImageDataURL(imageFile).then(dataURL => createImageElement(dataURL)) uploadFileToS3(imageFile).then(url => createImageElement(url)) } /** * 粘贴事件监听 * @param e ClipboardEvent */ const pasteListener = (e: ClipboardEvent) => { if (!editorAreaFocus.value && !thumbnailsFocus.value) return if (disableHotkeys.value) return if (!e.clipboardData) return const clipboardDataItems = e.clipboardData.items const clipboardDataFirstItem = clipboardDataItems[0] if (!clipboardDataFirstItem) return // 如果剪贴板内有图片,优先尝试读取图片 let isImage = false for (const item of clipboardDataItems) { if (item.kind === 'file' && item.type.indexOf('image') !== -1) { const imageFile = item.getAsFile() if (imageFile) pasteImageFile(imageFile) isImage = true } } if (isImage) return // 如果剪贴板内没有图片,但有文字内容,尝试解析文字内容 if (clipboardDataFirstItem.kind === 'string' && clipboardDataFirstItem.type === 'text/plain') { clipboardDataFirstItem.getAsString(text => pasteTextClipboardData(text)) } } onMounted(() => { document.addEventListener('paste', pasteListener) }) onUnmounted(() => { document.removeEventListener('paste', pasteListener) }) }