This commit is contained in:
Typer_Body
2026-05-27 00:24:07 +08:00
parent 5d4e40459f
commit 804448b6cd
3 changed files with 2154 additions and 164 deletions

2290
web/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -45,6 +45,7 @@
"@radix-ui/react-tooltip": "^1.2.7",
"@tailwindcss/postcss": "^4.1.5",
"@tanstack/react-table": "^8.21.3",
"@types/js-yaml": "^4.0.9",
"@vitejs/plugin-react": "^6.0.1",
"@xyflow/react": "^12.10.2",
"axios": "^1.15.0",
@@ -54,6 +55,7 @@
"i18next": "^25.1.2",
"i18next-browser-languagedetector": "^8.1.0",
"input-otp": "^1.4.2",
"js-yaml": "^4.1.1",
"lodash": "^4.18.0",
"lucide-react": "^0.507.0",
"postcss": "^8.5.3",

View File

@@ -32,6 +32,7 @@ import { Workflow } from '@/app/infra/entities/api';
import { useWorkflowStore } from './store/useWorkflowStore';
import { toast } from 'sonner';
import EmojiPicker from '@/components/ui/emoji-picker';
import yaml from 'js-yaml';
export default function WorkflowDetailContent({ id }: { id: string }) {
const isCreateMode = id === 'new';
@@ -174,7 +175,7 @@ export default function WorkflowDetailContent({ id }: { id: string }) {
basicInfo,
]);
// Export workflow handler
// Export workflow handler - exports as YAML
const handleExport = useCallback(() => {
const { nodes, edges } = toWorkflowDefinition();
@@ -190,13 +191,12 @@ export default function WorkflowDetailContent({ id }: { id: string }) {
exportedAt: new Date().toISOString(),
};
const blob = new Blob([JSON.stringify(exportData, null, 2)], {
type: 'application/json',
});
const yamlStr = yaml.dump(exportData, { indent: 2, lineWidth: -1 });
const blob = new Blob([yamlStr], { type: 'text/yaml' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = `${workflow?.name || 'workflow'}.json`;
a.download = `${workflow?.name || 'workflow'}.yaml`;
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
@@ -205,13 +205,21 @@ export default function WorkflowDetailContent({ id }: { id: string }) {
toast.success(t('workflows.exportSuccess'));
}, [workflow, toWorkflowDefinition, t]);
// Import workflow handler
// Import workflow handler - supports both JSON and YAML
const handleImport = useCallback(
(file: File) => {
const reader = new FileReader();
reader.onload = (e) => {
try {
const importData = JSON.parse(e.target?.result as string);
const content = e.target?.result as string;
let importData: any;
// Try YAML first, then JSON
try {
importData = yaml.load(content);
} catch {
importData = JSON.parse(content);
}
// Validate imported data structure
if (!importData.nodes || !Array.isArray(importData.nodes)) {
@@ -339,7 +347,7 @@ export default function WorkflowDetailContent({ id }: { id: string }) {
<div className="flex gap-2">
<input
type="file"
accept=".json"
accept=".yaml,.yml,.json"
onChange={handleFileChange}
style={{ display: 'none' }}
ref={fileInputRef}
@@ -419,7 +427,7 @@ export default function WorkflowDetailContent({ id }: { id: string }) {
{/* Hidden file input for import */}
<input
type="file"
accept=".json"
accept=".yaml,.yml,.json"
onChange={handleFileChange}
style={{ display: 'none' }}
ref={fileInputRef}