diff --git a/packages/editor-app/src/adapters/TauriFileAPI.ts b/packages/editor-app/src/adapters/TauriFileAPI.ts index 7aaa800f..325da64e 100644 --- a/packages/editor-app/src/adapters/TauriFileAPI.ts +++ b/packages/editor-app/src/adapters/TauriFileAPI.ts @@ -38,4 +38,8 @@ export class TauriFileAPI implements IFileAPI { public async pathExists(path: string): Promise { return await TauriAPI.pathExists(path); } + + public async getFileMtime(path: string): Promise { + return await TauriAPI.getFileMtime(path); + } } diff --git a/packages/editor-app/src/components/ExternalModificationDialog.tsx b/packages/editor-app/src/components/ExternalModificationDialog.tsx new file mode 100644 index 00000000..304c884a --- /dev/null +++ b/packages/editor-app/src/components/ExternalModificationDialog.tsx @@ -0,0 +1,58 @@ +import { AlertTriangle, X, RefreshCw, Save } from 'lucide-react'; +import '../styles/ConfirmDialog.css'; + +interface ExternalModificationDialogProps { + sceneName: string; + onReload: () => void; + onOverwrite: () => void; + onCancel: () => void; +} + +/** + * 外部修改对话框 + * External Modification Dialog + * + * 当场景文件被外部修改时显示,让用户选择操作 + * Shown when scene file is modified externally, let user choose action + */ +export function ExternalModificationDialog({ + sceneName, + onReload, + onOverwrite, + onCancel +}: ExternalModificationDialogProps) { + return ( +
+
e.stopPropagation()}> +
+ +

文件已被外部修改

+ +
+
+

+ 场景 {sceneName} 已在编辑器外部被修改。 +

+

+ 请选择如何处理: +

+
+
+ + + +
+
+
+ ); +} diff --git a/packages/editor-app/src/styles/ConfirmDialog.css b/packages/editor-app/src/styles/ConfirmDialog.css index 85d022dd..2470f184 100644 --- a/packages/editor-app/src/styles/ConfirmDialog.css +++ b/packages/editor-app/src/styles/ConfirmDialog.css @@ -126,3 +126,52 @@ .confirm-dialog-btn:active { transform: scale(0.98); } + +/* External Modification Dialog | 外部修改对话框 */ +.external-modification-dialog .warning-icon { + color: #f0ad4e; + margin-right: 8px; + flex-shrink: 0; +} + +.external-modification-dialog .confirm-dialog-header { + gap: 0; +} + +.external-modification-dialog .confirm-dialog-header h2 { + flex: 1; +} + +.external-modification-dialog .hint-text { + margin-top: 12px; + color: var(--text-secondary, #999); + font-size: 13px; +} + +.external-modification-footer { + flex-wrap: wrap; +} + +.confirm-dialog-btn.reload { + background: #5bc0de; + color: white; + display: flex; + align-items: center; + gap: 6px; +} + +.confirm-dialog-btn.reload:hover { + background: #7cd0e8; +} + +.confirm-dialog-btn.overwrite { + background: #f0ad4e; + color: white; + display: flex; + align-items: center; + gap: 6px; +} + +.confirm-dialog-btn.overwrite:hover { + background: #f4be6e; +}