fix: resolve image download errors, update export and image services
This commit is contained in:
+101
-41
@@ -1,55 +1,115 @@
|
||||
import pkg from "file-saver";
|
||||
import type { Stage } from "konva/lib/Stage";
|
||||
import { ImageError } from "../lib/types/errors";
|
||||
import type { Panel } from "../lib/types/panel";
|
||||
import { exportService as exportPanelService } from "../lib/services/exportService";
|
||||
import { setLoading } from "../stores/uiStore";
|
||||
import { handleError, logError } from "../lib/utils/errorHandler";
|
||||
const { saveAs } = pkg;
|
||||
|
||||
export interface ExportResult {
|
||||
success: boolean;
|
||||
error?: string;
|
||||
}
|
||||
|
||||
export class ExportService {
|
||||
private static instance: ExportService;
|
||||
private errorMessage: string | undefined = undefined;
|
||||
|
||||
private constructor() {}
|
||||
|
||||
static getInstance(): ExportService {
|
||||
if (!ExportService.instance) {
|
||||
ExportService.instance = new ExportService();
|
||||
}
|
||||
return ExportService.instance;
|
||||
}
|
||||
|
||||
getErrorMessage(): string | undefined {
|
||||
return this.errorMessage;
|
||||
}
|
||||
|
||||
setErrorMessage(message: string | undefined): void {
|
||||
this.errorMessage = message;
|
||||
}
|
||||
|
||||
async handleDownload(panel: Panel): Promise<void> {
|
||||
/**
|
||||
* Экспортирует панель в изображение и сохраняет её
|
||||
*/
|
||||
async exportPanel(panel: Panel, konvaStage: Stage, filename?: string): Promise<ExportResult> {
|
||||
try {
|
||||
setLoading(true);
|
||||
const result = await exportPanelService.exportPanel(panel);
|
||||
|
||||
if (!result.success) {
|
||||
this.errorMessage = result.error || "Ошибка экспорта панели";
|
||||
if (!konvaStage) {
|
||||
throw new ImageError("Konva Stage не передан для экспорта");
|
||||
}
|
||||
|
||||
// Используем toBlob метод Konva Stage напрямую
|
||||
const blob = await this.exportKonvaStageToBlob(konvaStage);
|
||||
|
||||
if (!blob) {
|
||||
throw new ImageError("Не удалось создать изображение");
|
||||
}
|
||||
|
||||
const defaultFilename = `twitch-panel-${panel.id}.png`;
|
||||
saveAs(blob, filename || defaultFilename);
|
||||
|
||||
return {
|
||||
success: true,
|
||||
};
|
||||
} catch (error) {
|
||||
this.errorMessage = error instanceof Error ? error.message : "Ошибка экспорта панели";
|
||||
} finally {
|
||||
setLoading(false);
|
||||
logError(error, "Panel export failed");
|
||||
return {
|
||||
success: false,
|
||||
error: handleError(error, "Ошибка экспорта панели"),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Экспортирует Konva Stage в Blob используя встроенный метод toBlob
|
||||
*/
|
||||
private async exportKonvaStageToBlob(konvaStage: Stage): Promise<Blob | null> {
|
||||
if (!konvaStage || typeof konvaStage.toBlob !== "function") {
|
||||
throw new ImageError("Konva Stage не найден или не поддерживает toBlob");
|
||||
}
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
konvaStage.toBlob({
|
||||
callback: (blob: Blob | null) => {
|
||||
if (blob) {
|
||||
resolve(blob);
|
||||
} else {
|
||||
reject(new ImageError("Не удалось создать изображение из Konva Stage"));
|
||||
}
|
||||
},
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Экспортирует несколько панелей в ZIP архив
|
||||
* (будет реализовано позже для batch download)
|
||||
*/
|
||||
async exportPanels(panels: Panel[]): Promise<ExportResult> {
|
||||
// TODO: Реализовать пакетный экспорт с использованием JSZip
|
||||
return {
|
||||
success: false,
|
||||
error: "Пакетный экспорт еще не реализован",
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Обработчик для скачивания одной панели
|
||||
* Этот метод должен быть вызван из компонента PanelPreview с передачей konvaStage
|
||||
*/
|
||||
async handleDownload(panel: Panel, konvaStage: Stage): Promise<void> {
|
||||
const result = await this.exportPanel(panel, konvaStage);
|
||||
if (!result.success) {
|
||||
throw new Error(result.error || "Ошибка экспорта панели");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Обработчик для скачивания всех панелей
|
||||
*/
|
||||
async handleDownloadAll(panels: Panel[]): Promise<void> {
|
||||
try {
|
||||
setLoading(true);
|
||||
for (const panel of panels) {
|
||||
await exportPanelService.exportPanel(panel);
|
||||
}
|
||||
} catch (error) {
|
||||
this.errorMessage = error instanceof Error ? error.message : "Ошибка экспорта панелей";
|
||||
} finally {
|
||||
setLoading(false);
|
||||
const result = await this.exportPanels(panels);
|
||||
if (!result.success) {
|
||||
throw new Error(result.error || "Ошибка экспорта панелей");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Получить сообщение об ошибке
|
||||
*/
|
||||
getErrorMessage(): string | null {
|
||||
return null; // Реализовать при необходимости
|
||||
}
|
||||
|
||||
/**
|
||||
* Установить сообщение об ошибке
|
||||
*/
|
||||
setErrorMessage(message: string): void {
|
||||
// Реализовать при необходимости
|
||||
console.error("ExportService error:", message);
|
||||
}
|
||||
}
|
||||
|
||||
export const exportService = ExportService.getInstance();
|
||||
export const exportService = new ExportService();
|
||||
|
||||
Reference in New Issue
Block a user