UNPKG

barneo-file-service

Version:

Комплексная библиотека Vue 3 для работы с файлами в приложениях Barneo. Предоставляет мощную функциональность для загрузки, управления и обработки файлов с валидацией, отслеживанием прогресса и поддержкой localStorage.

212 lines (175 loc) 5.65 kB
import { ref, computed } from "vue"; import type { FileUploadResponse, FileUploadOptions, AppName, FileUploadState, FileUploaderOptions, } from "../types"; import { FileUploadService } from "../services/FileUploadService"; export function useFileUploader(options: FileUploaderOptions) { const uploadService = new FileUploadService({ apiUrl: options.apiUrl, appName: options.appName, headers: options.headers, timeout: options.timeout, }); // Состояние загрузок const uploads = ref<Map<string, FileUploadState>>(new Map()); const isUploading = ref(false); const totalProgress = ref(0); // Computed свойства const pendingUploads = computed(() => Array.from(uploads.value.values()).filter( (upload) => upload.status === "pending" ) ); const uploadingFiles = computed(() => Array.from(uploads.value.values()).filter( (upload) => upload.status === "uploading" ) ); const completedUploads = computed(() => Array.from(uploads.value.values()).filter( (upload) => upload.status === "success" ) ); const failedUploads = computed(() => Array.from(uploads.value.values()).filter( (upload) => upload.status === "error" ) ); const hasUploads = computed(() => uploads.value.size > 0); const hasErrors = computed(() => failedUploads.value.length > 0); // Методы const createUploadState = (file: File): FileUploadState => ({ id: generateId(), file, status: "pending", progress: 0, }); const uploadFile = async (file: File): Promise<FileUploadResponse[]> => { const uploadState = createUploadState(file); uploads.value.set(uploadState.id, uploadState); try { uploadState.status = "uploading"; uploadState.progress = 0; isUploading.value = true; // Принудительно обновляем Map для реактивности uploads.value = new Map(uploads.value); const response = await uploadService.uploadFile(file, { appName: options.appName, onProgress: (progress) => { uploadState.progress = progress; updateTotalProgress(); }, onError: (error) => { uploadState.status = "error"; uploadState.error = error.message; if (options.onError) { options.onError(error); } }, }); uploadState.status = "success"; uploadState.response = response; uploadState.progress = 100; updateTotalProgress(); // Принудительно обновляем Map для реактивности uploads.value = new Map(uploads.value); return response; } catch (error) { uploadState.status = "error"; uploadState.error = error instanceof Error ? error.message : "Unknown error occurred"; // Принудительно обновляем Map для реактивности uploads.value = new Map(uploads.value); throw error; } finally { isUploading.value = false; } }; const uploadFiles = async (files: File[]): Promise<FileUploadResponse[]> => { try { isUploading.value = true; // Загружаем все файлы параллельно const uploadPromises = files.map((file) => uploadFile(file)); const results = await Promise.all(uploadPromises); return results.flat(); } finally { isUploading.value = false; } }; const retryUpload = async ( uploadId: string ): Promise<FileUploadResponse[]> => { const uploadState = uploads.value.get(uploadId); if (!uploadState || uploadState.status !== "error") { throw new Error("Upload not found or not in error state"); } // Очищаем предыдущую ошибку uploadState.error = undefined; return await uploadFile(uploadState.file); }; const removeUpload = (uploadId: string) => { uploads.value.delete(uploadId); updateTotalProgress(); }; const clearUploads = () => { uploads.value.clear(); totalProgress.value = 0; isUploading.value = false; }; const clearCompletedUploads = () => { for (const [id, upload] of uploads.value.entries()) { if (upload.status === "success") { uploads.value.delete(id); } } updateTotalProgress(); }; const clearFailedUploads = () => { for (const [id, upload] of uploads.value.entries()) { if (upload.status === "error") { uploads.value.delete(id); } } updateTotalProgress(); }; const updateTotalProgress = () => { if (uploads.value.size === 0) { totalProgress.value = 0; return; } const total = Array.from(uploads.value.values()).reduce((sum, upload) => { return sum + upload.progress; }, 0); totalProgress.value = Math.round(total / uploads.value.size); }; const generateId = (): string => { return Math.random().toString(36).substr(2, 9); }; return { // Состояние uploads, isUploading, totalProgress, // Computed pendingUploads, uploadingFiles, completedUploads, failedUploads, hasUploads, hasErrors, // Методы uploadFile, uploadFiles, retryUpload, removeUpload, clearUploads, clearCompletedUploads, clearFailedUploads, // Сервис uploadService, }; }