/** * Demo存储控制器 - 协调存储层和UI层 */ import type { AnalysisData } from '../api/GLTR_API'; import type { IDemoStorage, SaveOptions, SaveResult } from '../storage/demoStorage'; import { showConfirmDialog, showAlertDialog } from '../ui/dialog'; import { tr, trf } from '../lang/i18n-lite'; export interface StorageCallbacks { onStart?: () => void; onSuccess?: (name?: string, result?: SaveResult) => void; onError?: (error: Error) => void; setLoading?: (loading: boolean) => void; showToast?: (message: string, type: 'success' | 'error') => void; /** * 是否显示成功提示(使用 toast) * 默认为 true,设置为 false 时成功提示由调用者自行处理 * 注意:错误提示统一使用 alert,不受此参数影响 */ showSuccessToast?: boolean; } /** * Demo存储控制器 */ export class DemoStorageController { constructor( private storage: IDemoStorage, private callbacks: StorageCallbacks = {} ) {} /** * 保存demo */ async save(data: AnalysisData, options: SaveOptions): Promise { const { onStart, onSuccess, onError, setLoading, showToast, showSuccessToast = true } = this.callbacks; onStart?.(); setLoading?.(true); try { const result = await this._doSave(data, options, false); setLoading?.(false); if (result) { onSuccess?.(options.name, result); // 成功提示:根据 showSuccessToast 决定是否显示 if (showSuccessToast) { const hint = this.storage.type === 'local' ? tr('Downloaded to local') : tr('Upload successful'); showToast?.(`Demo "${options.name}" ${hint}!`, 'success'); } } return result; } catch (error) { setLoading?.(false); const err = error instanceof Error ? error : new Error(String(error)); onError?.(err); // 错误提示:统一使用 alert showAlertDialog(tr('Error'), trf('Save failed: {message}', { message: err.message })); return null; } } /** * 内部保存逻辑,处理覆盖 */ private async _doSave( data: AnalysisData, options: SaveOptions, overwrite: boolean ): Promise { const result = await this.storage.save(data, { ...options, overwrite }); // 文件已存在 - 仅服务器需要确认覆盖 if (!result.success && result.exists && this.storage.type === 'server') { return new Promise((resolve) => { this.callbacks.setLoading?.(false); showConfirmDialog( tr('File already exists'), trf('File "{name}.json" already exists, overwrite?', { name: options.name }), async () => { this.callbacks.setLoading?.(true); const saved = await this._doSave(data, options, true); resolve(saved); }, () => { this.callbacks.onError?.(new Error(tr('User cancelled save'))); resolve(null); }, tr('Overwrite'), tr('Cancel') ); }); } if (!result.success) { throw new Error(result.message || 'Save failed'); } return result; } /** * 加载demo */ async load(path?: string): Promise { const { onStart, onSuccess, onError, setLoading } = this.callbacks; onStart?.(); setLoading?.(true); try { const result = await this.storage.load(path); setLoading?.(false); if (result.success && result.data) { onSuccess?.(); return result.data; } else { // 显示错误(这里不涉及用户取消操作) if (result.message) { const err = new Error(result.message || 'Load failed'); onError?.(err); showAlertDialog(tr('Error'), tr(err.message)); } return null; } } catch (error) { setLoading?.(false); const err = error instanceof Error ? error : new Error(String(error)); onError?.(err); showAlertDialog(tr('Error'), trf('Load failed: {message}', { message: err.message })); return null; } } }