UNPKG

barneo-file-service

Version:

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

675 lines (561 loc) 21.5 kB
# Barneo File Service Комплексная библиотека Vue 3 для работы с файлами в приложениях Barneo. Предоставляет мощную функциональность для загрузки, управления и обработки файлов с валидацией, отслеживанием прогресса и поддержкой localStorage. > **Версия:** 1.1.1 > **Дата релиза:** 2 сентября 2025 > **Лицензия:** MIT ## 🚀 Основные возможности - **Загрузка файлов**: Поддержка drag & drop, множественной загрузки - **Валидация**: Проверка размера, типа и количества файлов - **Отслеживание прогресса**: Детальная информация о процессе загрузки - **Управление состоянием**: Реактивное состояние файлов и ошибок - **Хранилище**: Сохранение файлов в localStorage для повторного использования - **Обработка ошибок**: Возможность повтора неудачных загрузок - **Кастомизация**: Гибкая настройка через props, slots и события ## 📦 Установка ```bash npm install barneo-file-service ``` ## 🔧 Быстрый старт ### 1. Подключение плагина ```typescript import { createApp } from "vue"; import BarneoFileService from "barneo-file-service"; import { AppName } from "barneo-file-service"; import "barneo-file-service/style"; const app = createApp(App); app.use(BarneoFileService, { apiUrl: "https://api.example.com/upload", appName: AppName.PIM, maxFiles: 10, maxFileSize: 50 * 1024 * 1024, // 50MB allowedTypes: ["image/jpeg", "image/png", "application/pdf"], onUploadSuccess: (results) => console.log("Файлы загружены:", results), }); app.mount("#app"); ``` ### 2. Базовое использование компонента ```vue <template> <FileUploader title="Загрузить документы" @upload-success="handleUploadSuccess" @upload-error="handleUploadError" /> </template> <script setup> const handleUploadSuccess = (files) => { console.log("Загружено файлов:", files.length); }; const handleUploadError = (error) => { console.error("Ошибка загрузки:", error); }; </script> ``` ## 🎯 Сценарии использования ### 1. Загрузка документов с валидацией ```vue <template> <FileUploader title="Загрузить документы" :max-files="5" :max-file-size="10 * 1024 * 1024" :allowed-types="['application/pdf', 'application/msword']" @upload-success="handleDocumentsUpload" /> </template> <script setup> const handleDocumentsUpload = (files) => { // Обработка загруженных документов files.forEach((file) => { console.log(`Документ загружен: ${file.originalName}`); }); }; </script> ``` ### 2. Загрузка изображений с предпросмотром ```vue <template> <FileUploader button-type="input" title="Загрузить изображения" :allowed-types="['image/jpeg', 'image/png', 'image/webp']" :multiple="true" @upload-success="handleImagesUpload" /> </template> <script setup> const handleImagesUpload = (files) => { // Создание предпросмотра изображений files.forEach((file) => { const img = new Image(); img.src = file.url; // Добавление в галерею }); }; </script> ``` ### 3. Использование с кастомным UI ```vue <template> <FileUploader button-type="default" button-text="Выбрать файлы" button-variant="primary" @upload-success="handleUpload" > <template #button="{ openModal, buttonText }"> <button @click="openModal" class="custom-button"> {{ buttonText }} </button> </template> <template #modal-header="{ title, closeModal }"> <div class="custom-header"> <h2>{{ title }}</h2> <button @click="closeModal"></button> </div> </template> </FileUploader> </template> ``` ### 4. Работа с сохраненными файлами ```vue <template> <FileUploader title="Управление файлами" @upload-success="handleUpload" /> </template> <script setup> import { useFileService } from "barneo-file-service"; const fileService = useFileService(); const handleUpload = (files) => { // Файлы автоматически сохраняются в localStorage console.log("Файлы сохранены в хранилище"); // Получение сохраненных файлов const storedFiles = fileService.storedFiles.value; console.log("Сохраненные файлы:", storedFiles); }; </script> ``` ### 5. Управление загруженными файлами через props ```vue <template> <FileUploader button-type="input" :uploaded-files="myUploadedFiles" @files-cleared="handleFilesCleared" @upload-success="handleUploadSuccess" /> </template> <script setup> import { ref } from "vue"; const myUploadedFiles = ref([ { id: 1, originalName: "document.pdf", name: "document.pdf", size: 1024000, type: "application/pdf", url: "https://example.com/document.pdf", }, ]); const handleFilesCleared = () => { // Файлы были очищены пользователем console.log("Файлы очищены"); // Здесь можно обновить состояние в родительском компоненте myUploadedFiles.value = []; }; const handleUploadSuccess = (files) => { // Добавляем новые загруженные файлы к существующим myUploadedFiles.value.push(...files); }; </script> ``` ### 6. Вызов методов компонента из родительского компонента ```vue <template> <div> <button @click="clearFiles">Очистить файлы</button> <button @click="openModal">Открыть модальное окно</button> <button @click="closeModal">Закрыть модальное окно</button> <FileUploader ref="fileUploaderRef" button-type="input" :uploaded-files="myUploadedFiles" @files-cleared="handleFilesCleared" /> </div> </template> <script setup> import { ref } from "vue"; const fileUploaderRef = ref(); const myUploadedFiles = ref([ { id: 1, originalName: "document.pdf", name: "document.pdf", size: 1024000, type: "application/pdf", url: "https://example.com/document.pdf", }, ]); const clearFiles = () => { // Вызываем метод clearUploadedFiles из дочернего компонента fileUploaderRef.value?.clearUploadedFiles(); }; const openModal = () => { // Открываем модальное окно программно fileUploaderRef.value?.openModal(); }; const closeModal = () => { // Закрываем модальное окно программно fileUploaderRef.value?.closeModal(); }; const handleFilesCleared = () => { console.log("Файлы очищены"); myUploadedFiles.value = []; }; </script> ``` ## 📋 API Reference ### FileUploader Component #### Props | Prop | Type | Default | Description | | --------------------- | -------------------------------------------------- | ------------------- | -------------------------------------------------------------- | | `title` | `string` | `'Загрузка файлов'` | Заголовок модального окна | | `buttonText` | `string` | `'Загрузить файлы'` | Текст кнопки | | `buttonSize` | `'small' \| 'medium' \| 'large'` | `'medium'` | Размер кнопки | | `buttonVariant` | `'primary' \| 'secondary' \| 'outline' \| 'ghost'` | `'primary'` | Стиль кнопки | | `buttonType` | `'default' \| 'input'` | `'default'` | Тип отображения кнопки | | `buttonIcon` | `string` | `undefined` | CSS класс иконки | | `autoCloseOnSuccess` | `boolean` | `true` | Автоматически закрывать модальное окно после успешной загрузки | | `showCancelButton` | `boolean` | `true` | Показывать ли кнопку отмены | | `cancelButtonText` | `string` | `'Отмена'` | Текст кнопки отмены | | `modalMaxWidth` | `string` | `'600px'` | Максимальная ширина модального окна | | `modalPosition` | `'center' \| 'top' \| 'bottom'` | `'center'` | Позиция модального окна | | `closeOnOverlayClick` | `boolean` | `true` | Закрывать ли модальное окно при клике вне его | | `showAnimations` | `boolean` | `true` | Показывать ли анимации | | `uploadedFiles` | `FileUploadResponse[]` | `undefined` | Список загруженных файлов для отображения | #### Events | Event | Payload | Description | | ----------------- | ---------------------------------- | ------------------------------------------- | | `upload-success` | `FileUploadResponse[]` | Файлы успешно загружены | | `upload-complete` | `[FileUploadResponse[], string[]]` | Загрузка завершена (успешно или с ошибками) | | `upload-error` | `Error` | Ошибка загрузки | | `files-selected` | `File[]` | Файлы выбраны (но еще не загружены) | | `modal-open` | `void` | Модальное окно открыто | | `modal-close` | `void` | Модальное окно закрыто | | `files-cleared` | `void` | Загруженные файлы очищены | #### Exposed Methods Методы, которые можно вызывать из родительского компонента через ref: | Method | Parameters | Return Type | Description | | ----------------------- | ---------- | ----------- | ---------------------------- | | `clearUploadedFiles` | - | `void` | Очищает загруженные файлы | | `openModal` | - | `void` | Открывает модальное окно | | `closeModal` | - | `void` | Закрывает модальное окно | | `uploadSelectedFiles` | - | `Promise` | Загружает выбранные файлы | | `clearFiles` | - | `void` | Очищает выбранные файлы | | `clearErrors` | - | `void` | Очищает ошибки валидации | | `clearCompletedUploads` | - | `void` | Очищает завершенные загрузки | | `retryFailedUploads` | - | `void` | Повторяет неудачные загрузки | #### Slots ##### `button` - Слот для кнопки (по умолчанию) ```vue <template #button="{ openModal, buttonText, buttonSize, buttonVariant, buttonIcon }" > <button @click="openModal" class="custom-button"> {{ buttonText }} </button> </template> ``` ##### `button-input` - Слот для input типа кнопки ```vue <template #button-input="{ openModal, title, uploadedFiles, clearUploadedFiles, formatFileSize, allowedTypes, }" > <div class="custom-input"> <span>{{ title }}</span> <button @click="openModal">Выбрать</button> <button @click="clearUploadedFiles">Очистить</button> </div> </template> ``` ##### `modal-header` - Слот для заголовка модального окна ```vue <template #modal-header="{ title, closeModal }"> <div class="custom-header"> <h2>{{ title }}</h2> <button @click="closeModal">Закрыть</button> </div> </template> ``` ##### `file-drop-zone` - Слот для области выбора файлов ```vue <template #file-drop-zone="{ selectFiles, isDragOver, selectedFiles, errors, triggerFileInput, formatFileSize, config, }" > <div @drop="selectFiles" @dragover.prevent :class="{ 'drag-over': isDragOver }" > <p>Перетащите файлы сюда</p> <button @click="triggerFileInput">Выбрать файлы</button> </div> </template> ``` ##### `file-list` - Слот для списка выбранных файлов ```vue <template #file-list="{ selectedFiles, removeFile, clearFiles, isFileUploading, formatFileSize, isUploading, }" > <div class="file-list"> <div v-for="(file, index) in selectedFiles" :key="index"> <span>{{ file.name }}</span> <span>{{ formatFileSize(file.size) }}</span> <button @click="removeFile(index)" :disabled="isFileUploading(file)"> Удалить </button> </div> </div> </template> ``` ##### `stored-files` - Слот для списка сохраненных файлов ```vue <template #stored-files="{ storedFiles, selectedStoredFiles, toggleStoredFileSelection, isStoredFileSelected, removeStoredFile, formatFileSize, formatDate, hasStoredFiles, }" > <div v-if="hasStoredFiles" class="stored-files"> <div v-for="file in storedFiles" :key="file.id"> <input type="checkbox" :checked="isStoredFileSelected(file.id)" @change="toggleStoredFileSelection(file.id)" /> <span>{{ file.originalName }}</span> <span>{{ formatFileSize(file.size) }}</span> <span>{{ formatDate(file.uploadedAt) }}</span> <button @click="removeStoredFile(file.id)">Удалить</button> </div> </div> </template> ``` ##### `action-buttons` - Слот для кнопок действий ```vue <template #action-buttons="{ uploadFiles, selectStoredFiles, clearFiles, retryFailedUploads, isUploading, hasSelectedFiles, hasErrors, activeMode, hasSelectedStoredFiles, closeModal, showCancelButton, cancelButtonText, }" > <div class="action-buttons"> <button v-if="showCancelButton" @click="closeModal"> {{ cancelButtonText }} </button> <button v-if="activeMode === 'upload'" @click="uploadFiles" :disabled="!hasSelectedFiles || isUploading" > {{ isUploading ? "Загрузка..." : "Загрузить" }} </button> <button v-else-if="activeMode === 'select'" @click="selectStoredFiles" :disabled="!hasSelectedStoredFiles" > Выбрать </button> </div> </template> ``` ### Composables #### `useFileService()` Основной composable для работы с файлами. ```typescript import { useFileService } from "barneo-file-service"; const fileService = useFileService(); // Состояние const selectedFiles = fileService.selectedFiles; const errors = fileService.errors; const isUploading = fileService.isUploading; const totalProgress = fileService.totalProgress; // Методы const results = await fileService.uploadSelectedFiles(); fileService.selectFiles(files); fileService.clearFiles(); fileService.clearErrors(); ``` #### `useFileInput(options)` Composable для управления выбором файлов. ```typescript import { useFileInput } from "barneo-file-service"; const { selectedFiles, errors, selectFiles, removeFile, clearFiles, isFileSelected, totalSize, } = useFileInput({ maxFiles: 5, maxFileSize: 10 * 1024 * 1024, // 10MB allowedTypes: ["image/jpeg", "image/png"], multiple: true, }); ``` #### `useFileUploader(options)` Composable для управления загрузкой файлов. ```typescript import { useFileUploader } from "barneo-file-service"; const { uploads, isUploading, totalProgress, uploadFile, uploadFiles, retryUpload, clearUploads, } = useFileUploader({ apiUrl: "https://api.example.com/upload", appName: AppName.PIM, onProgress: (progress) => console.log(`Progress: ${progress}%`), onError: (error) => console.error("Upload failed:", error), }); ``` #### `useFileStorage()` Composable для управления хранилищем файлов. ```typescript import { useFileStorage } from "barneo-file-service"; const { storedFiles, selectedStoredFiles, addStoredFile, removeStoredFile, clearStoredFiles, addSelectedStoredFile, clearSelectedStoredFiles, } = useFileStorage(); ``` ### Сервисы #### `FileUploadService` Сервис для загрузки файлов на сервер. ```typescript import { FileUploadService } from "barneo-file-service"; const service = new FileUploadService({ apiUrl: "https://api.example.com/upload", appName: AppName.PIM, headers: { Authorization: "Bearer token" }, timeout: 30000, }); // Загрузка одного файла const result = await service.uploadFile(file, { appName: AppName.PIM, onProgress: (progress) => console.log(`Progress: ${progress}%`), onError: (error) => console.error("Upload failed:", error), }); // Загрузка нескольких файлов const results = await service.uploadFiles([file1, file2], { appName: AppName.PIM, }); ``` ## 🎨 Кастомизация ### CSS переменные Библиотека использует CSS переменные для кастомизации стилей: ```css :root { --primary-color: #0091ea; --primary-hover: #0077cc; --gray-50: #fafafa; --gray-100: #f9fafb; --gray-200: #f3f4f6; --gray-300: #e5e7eb; --gray-400: #d1d5db; --gray-500: #9ca3af; --gray-600: #6b7280; --gray-700: #374151; --gray-900: #111827; --error-color: #ef4444; --success-color: #10b981; --border-radius-sm: 6px; --border-radius-md: 8px; --border-radius-lg: 10px; --border-radius-xl: 12px; --transition: all 0.15s ease; --shadow-sm: 0 1px 3px 0 rgba(0, 0, 0, 0.1); --shadow-lg: 0 25px 50px -12px rgba(0, 0, 0, 0.15); } ``` ### Кастомные стили ```vue <template> <FileUploader class="custom-uploader" /> </template> <style> .custom-uploader { --primary-color: #ff6b6b; --border-radius-md: 12px; } .custom-uploader .file-uploader__button { background: linear-gradient(45deg, #ff6b6b, #ee5a24); border: none; color: white; font-weight: bold; } </style> ``` ## 🔧 Разработка ```bash # Установка зависимостей npm install # Разработка npm run dev # Сборка npm run build # Проверка типов npm run type-check # Линтинг npm run lint ``` ## 📄 Лицензия MIT