Barneo File Service
Комплексная библиотека Vue 3 для работы с файлами в приложениях Barneo. Предоставляет мощную функциональность для загрузки, управления и обработки файлов с валидацией, отслеживанием прогресса и поддержкой localStorage.
Версия: 1.1.1
Дата релиза: 2 сентября 2025
Лицензия: MIT
🚀 Основные возможности
- Загрузка файлов: Поддержка drag & drop, множественной загрузки
- Валидация: Проверка размера, типа и количества файлов
- Отслеживание прогресса: Детальная информация о процессе загрузки
- Управление состоянием: Реактивное состояние файлов и ошибок
- Хранилище: Сохранение файлов в localStorage для повторного использования
- Обработка ошибок: Возможность повтора неудачных загрузок
- Кастомизация: Гибкая настройка через props, slots и события
📦 Установка
npm install barneo-file-service
🔧 Быстрый старт
1. Подключение плагина
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. Базовое использование компонента
<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. Загрузка документов с валидацией
<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. Загрузка изображений с предпросмотром
<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
<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. Работа с сохраненными файлами
<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
<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. Вызов методов компонента из родительского компонента
<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
- Слот для кнопки (по умолчанию)
<template
#button="{ openModal, buttonText, buttonSize, buttonVariant, buttonIcon }"
>
<button @click="openModal" class="custom-button">
{{ buttonText }}
</button>
</template>
button-input
- Слот для input типа кнопки
<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
- Слот для заголовка модального окна
<template #modal-header="{ title, closeModal }">
<div class="custom-header">
<h2>{{ title }}</h2>
<button @click="closeModal">Закрыть</button>
</div>
</template>
file-drop-zone
- Слот для области выбора файлов
<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
- Слот для списка выбранных файлов
<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
- Слот для списка сохраненных файлов
<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
- Слот для кнопок действий
<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 для работы с файлами.
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 для управления выбором файлов.
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 для управления загрузкой файлов.
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 для управления хранилищем файлов.
import { useFileStorage } from "barneo-file-service";
const {
storedFiles,
selectedStoredFiles,
addStoredFile,
removeStoredFile,
clearStoredFiles,
addSelectedStoredFile,
clearSelectedStoredFiles,
} = useFileStorage();
Сервисы
FileUploadService
Сервис для загрузки файлов на сервер.
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 переменные для кастомизации стилей:
: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);
}
Кастомные стили
<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>
🔧 Разработка
# Установка зависимостей
npm install
# Разработка
npm run dev
# Сборка
npm run build
# Проверка типов
npm run type-check
# Линтинг
npm run lint
📄 Лицензия
MIT