From 4ac633d295ed631f58acfd20a06b4a7328731972 Mon Sep 17 00:00:00 2001 From: dengqichen Date: Mon, 30 Dec 2024 16:06:49 +0800 Subject: [PATCH] 1 --- frontend/src/components/ui/sheet.tsx | 138 ++++++++++++++ .../Design/components/NodeConfigModal.tsx | 174 +++++++++++------- 2 files changed, 248 insertions(+), 64 deletions(-) create mode 100644 frontend/src/components/ui/sheet.tsx diff --git a/frontend/src/components/ui/sheet.tsx b/frontend/src/components/ui/sheet.tsx new file mode 100644 index 00000000..477bc982 --- /dev/null +++ b/frontend/src/components/ui/sheet.tsx @@ -0,0 +1,138 @@ +import * as React from "react" +import * as SheetPrimitive from "@radix-ui/react-dialog" +import { cva, type VariantProps } from "class-variance-authority" +import { X } from "lucide-react" + +import { cn } from "@/lib/utils" + +const Sheet = SheetPrimitive.Root + +const SheetTrigger = SheetPrimitive.Trigger + +const SheetClose = SheetPrimitive.Close + +const SheetPortal = SheetPrimitive.Portal + +const SheetOverlay = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +SheetOverlay.displayName = SheetPrimitive.Overlay.displayName + +const sheetVariants = cva( + "fixed z-50 gap-4 bg-background p-6 shadow-lg transition ease-in-out data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:duration-300 data-[state=open]:duration-500", + { + variants: { + side: { + top: "inset-x-0 top-0 border-b data-[state=closed]:slide-out-to-top data-[state=open]:slide-in-from-top", + bottom: + "inset-x-0 bottom-0 border-t data-[state=closed]:slide-out-to-bottom data-[state=open]:slide-in-from-bottom", + left: "inset-y-0 left-0 h-full w-3/4 border-r data-[state=closed]:slide-out-to-left data-[state=open]:slide-in-from-left sm:max-w-sm", + right: + "inset-y-0 right-0 h-full w-3/4 border-l data-[state=closed]:slide-out-to-right data-[state=open]:slide-in-from-right sm:max-w-sm", + }, + }, + defaultVariants: { + side: "right", + }, + } +) + +interface SheetContentProps + extends React.ComponentPropsWithoutRef, + VariantProps {} + +const SheetContent = React.forwardRef< + React.ElementRef, + SheetContentProps +>(({ side = "right", className, children, ...props }, ref) => ( + + + + {children} + + + Close + + + +)) +SheetContent.displayName = SheetPrimitive.Content.displayName + +const SheetHeader = ({ + className, + ...props +}: React.HTMLAttributes) => ( +
+) +SheetHeader.displayName = "SheetHeader" + +const SheetFooter = ({ + className, + ...props +}: React.HTMLAttributes) => ( +
+) +SheetFooter.displayName = "SheetFooter" + +const SheetTitle = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +SheetTitle.displayName = SheetPrimitive.Title.displayName + +const SheetDescription = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +SheetDescription.displayName = SheetPrimitive.Description.displayName + +export { + Sheet, + SheetPortal, + SheetOverlay, + SheetTrigger, + SheetClose, + SheetContent, + SheetHeader, + SheetFooter, + SheetTitle, + SheetDescription, +} \ No newline at end of file diff --git a/frontend/src/pages/Workflow/Definition/Design/components/NodeConfigModal.tsx b/frontend/src/pages/Workflow/Definition/Design/components/NodeConfigModal.tsx index 75ab602e..9b156500 100644 --- a/frontend/src/pages/Workflow/Definition/Design/components/NodeConfigModal.tsx +++ b/frontend/src/pages/Workflow/Definition/Design/components/NodeConfigModal.tsx @@ -1,9 +1,27 @@ -import React, {useEffect} from 'react'; -import {Drawer, Space, Tabs, TabsProps} from 'antd'; +import React from 'react'; +import {Tabs, TabsProps} from 'antd'; import {Cell} from '@antv/x6'; import {NodeDefinitionResponse} from "@/pages/Workflow/NodeDesign/types"; -import {BetaSchemaForm} from '@ant-design/pro-form'; -import {convertJsonSchemaToColumns} from '@/utils/jsonSchemaUtils'; +import { + Sheet, + SheetContent, + SheetHeader, + SheetTitle, + SheetFooter, +} from "@/components/ui/sheet"; +import {Button} from "@/components/ui/button"; +import { + Form, + FormControl, + FormField, + FormItem, + FormLabel, + FormMessage, +} from "@/components/ui/form"; +import {Input} from "@/components/ui/input"; +import {useForm} from "react-hook-form"; +import {zodResolver} from "@hookform/resolvers/zod"; +import * as z from "zod"; interface NodeConfigDrawerProps { visible: boolean; @@ -24,38 +42,51 @@ const NodeConfigDrawer: React.FC = ({ onOk, onCancel, }) => { - const handleSubmit = async (values: any) => { + // 创建动态的 schema + const createFormSchema = (schema: any) => { + if (!schema?.properties) return z.object({}); + + const schemaFields: Record = {}; + Object.entries(schema.properties).forEach(([key, property]: [string, any]) => { + switch (property.type) { + case 'string': + schemaFields[key] = property.required ? z.string() : z.string().optional(); + break; + case 'number': + schemaFields[key] = property.required ? z.number() : z.number().optional(); + break; + case 'boolean': + schemaFields[key] = property.required ? z.boolean() : z.boolean().optional(); + break; + default: + schemaFields[key] = z.any(); + } + }); + return z.object(schemaFields); + }; + + const panelFormSchema = createFormSchema(nodeDefinition?.panelVariablesSchema); + const localFormSchema = createFormSchema(nodeDefinition?.localVariablesSchema); + + const panelForm = useForm>({ + resolver: zodResolver(panelFormSchema), + defaultValues: nodeDefinition?.panelVariables || {}, + }); + + const localForm = useForm>({ + resolver: zodResolver(localFormSchema), + defaultValues: nodeDefinition?.localVariables || {}, + }); + + const handleSubmit = async () => { try { - // 将表单数据分离为 panelVariables 和 localVariables - const panelVariables: Variables = {}; - const localVariables: Variables = {}; - - // 处理 panelVariablesSchema 中定义的字段 - if (nodeDefinition?.panelVariablesSchema?.properties) { - Object.entries(nodeDefinition.panelVariablesSchema.properties).forEach(([key, property]) => { - if (values[key] !== undefined) { - panelVariables[key] = values[key]; - } else if (property.default !== undefined) { - panelVariables[key] = property.default; - } - }); - } - - // 处理 localVariablesSchema 中定义的字段 - if (nodeDefinition?.localVariablesSchema?.properties) { - Object.entries(nodeDefinition.localVariablesSchema.properties).forEach(([key, property]) => { - if (values[key] !== undefined) { - localVariables[key] = values[key]; - } else if (property.default !== undefined) { - localVariables[key] = property.default; - } - }); - } + const panelValues = await panelForm.handleSubmit((data) => data)(); + const localValues = await localForm.handleSubmit((data) => data)(); const updatedNodeDefinition = { ...nodeDefinition, - panelVariables, - localVariables + panelVariables: panelValues, + localVariables: localValues }; onOk(updatedNodeDefinition); } catch (error) { @@ -63,56 +94,71 @@ const NodeConfigDrawer: React.FC = ({ } }; + const renderFormFields = (schema: any, form: any) => { + if (!schema?.properties) return null; + + return Object.entries(schema.properties).map(([key, property]: [string, any]) => ( + ( + + {property.title || key} + + + + + + )} + /> + )); + }; + const items: TabsProps['items'] = [ nodeDefinition?.panelVariablesSchema && { key: 'panel', label: '面板变量', children: ( - +
+ + {renderFormFields(nodeDefinition.panelVariablesSchema, panelForm)} +
+ ) }, nodeDefinition?.localVariablesSchema && { key: 'local', label: '环境变量', children: ( - +
+ + {renderFormFields(nodeDefinition.localVariablesSchema, localForm)} +
+ ) } ].filter(Boolean) as TabsProps['items']; return ( - - -
- - - + - -
-
+ + + + ); };