diff --git a/package.json b/package.json index 1b31ae6..a18f41f 100644 --- a/package.json +++ b/package.json @@ -33,6 +33,7 @@ "quill-image-uploader": "^1.3.0", "quill-mention": "^4.1.0", "sortablejs": "^1.15.6", + "viewerjs": "^1.11.7", "vue": "^3.3.11", "vue-cropper": "^1.1.1", "vue-router": "^4.2.5", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 83df2e9..b3609b0 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -65,6 +65,9 @@ importers: sortablejs: specifier: ^1.15.6 version: 1.15.6 + viewerjs: + specifier: ^1.11.7 + version: 1.11.7 vue: specifier: ^3.3.11 version: 3.5.13(typescript@5.2.2) @@ -3217,6 +3220,9 @@ packages: peerDependencies: vue: ^3.0.11 + viewerjs@1.11.7: + resolution: {integrity: sha512-0JuVqOmL5v1jmEAlG5EBDR3XquxY8DWFQbFMprOXgaBB0F7Q/X9xWdEaQc59D8xzwkdUgXEMSSknTpriq95igg==} + vite-hot-client@2.0.4: resolution: {integrity: sha512-W9LOGAyGMrbGArYJN4LBCdOC5+Zwh7dHvOHC0KmGKkJhsOzaKbpo/jEjpPKVHIW0/jBWj8RZG0NUxfgA8BxgAg==} peerDependencies: @@ -6816,6 +6822,8 @@ snapshots: evtd: 0.2.4 vue: 3.5.13(typescript@5.2.2) + viewerjs@1.11.7: {} + vite-hot-client@2.0.4(vite@4.5.14(@types/node@18.19.99)(less@4.3.0)(sass@1.88.0)(terser@5.39.0)): dependencies: vite: 4.5.14(@types/node@18.19.99)(less@4.3.0)(sass@1.88.0)(terser@5.39.0) diff --git a/src/components/x-naive-ui/x-preview-img/index-1.ts b/src/components/x-naive-ui/x-preview-img/index-1.ts deleted file mode 100644 index 8719020..0000000 --- a/src/components/x-naive-ui/x-preview-img/index-1.ts +++ /dev/null @@ -1,144 +0,0 @@ -import { createApp, h, ref } from 'vue' -import { NImage, NImageGroup } from 'naive-ui' - -interface PreviewOptions { - onStart?: () => void - onError?: (e: Event) => void - showToolbar?: boolean -} - -class ImagePreview { - private static instance: { - app: any - container: HTMLElement - } | null = null - - static async preview( - sources: string | File | (string | File)[], - index = 0, - options: PreviewOptions = {}, - ) { - try { - const urls = await this.normalizeImageSources( - Array.isArray(sources) ? sources : [sources] - ) - - if (!urls.length) { - console.warn('[ImagePreview] No valid image sources') - return - } - - this.destroy() - options.onStart?.() - - const container = document.createElement('div') - container.style.display = 'none' - document.body.appendChild(container) - - const app = createApp({ - setup() { - const imageRef = ref | null>(null) - - return () => { - if (urls.length === 1) { - return h(NImage, { - ref: imageRef, - src: urls[0], - previewDisabled: false, - preview: true, - showToolbar: options.showToolbar ?? true, - style: { - display: 'none' - }, - onLoad: () => { - imageRef.value?.click() - } - }) - } else { - return h(NImageGroup, { - showToolbar: options.showToolbar ?? true, - currentIndex: index - }, { - default: () => urls.map((url, i) => { - const imgRef = ref | null>(null) - return h(NImage, { - ref: i === index ? imgRef : undefined, - src: url, - previewDisabled: false, - preview: true, - style: { - display: 'none' - }, - onLoad: i === index ? () => { - imgRef.value?.click() - } : undefined - }) - }) - }) - } - } - } - }) - - app.mount(container) - this.instance = { app, container } - - } catch (error) { - console.error('[ImagePreview] Error:', error) - options.onError?.(error as Event) - } - } - - private static async normalizeImageSources(sources: (string | File)[]): Promise { - const urls: string[] = [] - - for (const source of sources) { - try { - if (typeof source === 'string') { - if (source.startsWith('data:') || source.startsWith('http')) { - urls.push(source) - } else { - console.warn('[ImagePreview] Invalid image source:', source) - } - } else if (source instanceof File) { - const url = await this.fileToUrl(source) - urls.push(url) - } - } catch (error) { - console.warn('[ImagePreview] Failed to process source:', source, error) - } - } - - return urls - } - - private static fileToUrl(file: File): Promise { - return new Promise((resolve, reject) => { - if (!file.type.startsWith('image/')) { - reject(new Error('Not an image file')) - return - } - - const reader = new FileReader() - reader.onload = () => resolve(reader.result as string) - reader.onerror = reject - reader.readAsDataURL(file) - }) - } - - private static destroy() { - if (this.instance) { - const { app, container } = this.instance - app.unmount() - container.remove() - this.instance = null - } - } - - static close() { - this.destroy() - } -} - -export const previewImage = ImagePreview.preview.bind(ImagePreview) -export const closePreview = ImagePreview.close.bind(ImagePreview) \ No newline at end of file