diff --git a/web/app/i18n.ts b/web/app/i18n.ts index 1ecde2e6c..a03216c55 100644 --- a/web/app/i18n.ts +++ b/web/app/i18n.ts @@ -2,6 +2,9 @@ import i18n from 'i18next'; import { initReactI18next } from 'react-i18next'; const en = { + UploadData: 'Upload Data', + CodeEditor: 'Code Editor:', + openCodeEditor:'Open Code Editor', Knowledge_Space: 'Knowledge', space: 'space', Vector: 'Vector', @@ -234,6 +237,9 @@ export interface Resources { } const zh: Resources['translation'] = { + UploadData: '上传数据', + CodeEditor: '代码编辑:', + openCodeEditor: '打开代码编辑器', Knowledge_Space: '知识库', space: '知识库', Vector: '向量', diff --git a/web/components/flow/node-param-handler.tsx b/web/components/flow/node-param-handler.tsx index 165eb59bb..b7553ac51 100644 --- a/web/components/flow/node-param-handler.tsx +++ b/web/components/flow/node-param-handler.tsx @@ -15,9 +15,10 @@ import { RenderTreeSelect, RenderTimePicker, RenderTextArea, + RenderUpload, + RenderCodeEditor, RenderPassword, } from './node-renderer'; -import { convertKeysToCamelCase } from '@/utils/flow'; interface NodeParamHandlerProps { node: IFlowNode; @@ -142,6 +143,10 @@ const NodeParamHandler: React.FC = ({ node, data, label, return ; case 'password': return ; + case 'upload': + return ; + case 'code_editor': + return ; default: return null; } diff --git a/web/components/flow/node-renderer/codeEditor.tsx b/web/components/flow/node-renderer/codeEditor.tsx new file mode 100644 index 000000000..03586f25c --- /dev/null +++ b/web/components/flow/node-renderer/codeEditor.tsx @@ -0,0 +1,67 @@ +import React, { useState, useMemo } from 'react'; +import { Button, Modal } from 'antd'; +import Editor from '@monaco-editor/react'; +import { IFlowNodeParameter } from '@/types/flow'; +import { convertKeysToCamelCase } from '@/utils/flow'; +import { useTranslation } from 'react-i18next'; + +type Props = { + data: IFlowNodeParameter; + defaultValue: any; + onChange: (value: any) => void; +}; + +export const RenderCodeEditor = (params: Props) => { + const { t } = useTranslation(); + + const { data, defaultValue, onChange } = params; + const attr = convertKeysToCamelCase(data.ui?.attr || {}); + + const [isModalOpen, setIsModalOpen] = useState(false); + const showModal = () => { + setIsModalOpen(true); + }; + + const handleOk = () => { + setIsModalOpen(false); + }; + + const handleCancel = () => { + setIsModalOpen(false); + }; + /** + * 设置弹窗宽度 + */ + const modalWidth = useMemo(() => { + if (data?.ui?.editor?.width) { + return data?.ui?.editor?.width + 100 + } + return '80%'; + }, [data?.ui?.editor?.width]); + + return ( +
+ + + + +
+ ); +}; diff --git a/web/components/flow/node-renderer/index.ts b/web/components/flow/node-renderer/index.ts index 59f1e44ef..98466e8eb 100644 --- a/web/components/flow/node-renderer/index.ts +++ b/web/components/flow/node-renderer/index.ts @@ -8,4 +8,6 @@ export * from './textarea'; export * from './slider'; export * from './time-picker'; export * from './tree-select'; +export * from './codeEditor'; +export * from './upload'; export * from './password'; diff --git a/web/components/flow/node-renderer/textarea.tsx b/web/components/flow/node-renderer/textarea.tsx index 4a2c40f20..47af5a53b 100644 --- a/web/components/flow/node-renderer/textarea.tsx +++ b/web/components/flow/node-renderer/textarea.tsx @@ -13,6 +13,7 @@ type TextAreaProps = { export const RenderTextArea = (params: TextAreaProps) => { const { data, defaultValue, onChange } = params; + const attr = convertKeysToCamelCase(data.ui?.attr || {}); return ( diff --git a/web/components/flow/node-renderer/tree-select.tsx b/web/components/flow/node-renderer/tree-select.tsx index 508407217..5db73438f 100644 --- a/web/components/flow/node-renderer/tree-select.tsx +++ b/web/components/flow/node-renderer/tree-select.tsx @@ -1,107 +1,28 @@ import React, { useState } from 'react'; import { TreeSelect } from 'antd'; -import type { TreeSelectProps } from 'antd'; import { IFlowNodeParameter } from '@/types/flow'; -import { Label } from '@mui/icons-material'; +import { convertKeysToCamelCase } from '@/utils/flow'; type TextAreaProps = { data: IFlowNodeParameter; defaultValue: any; onChange: (value: any) => void; }; -const treeData = [ - { - value: 'parent 1', - title: 'parent 1', - children: [ - { - value: 'parent 1-0', - title: 'parent 1-0', - children: [ - { - value: 'leaf1', - title: 'leaf1', - }, - { - value: 'leaf2', - title: 'leaf2', - }, - { - value: 'leaf3', - title: 'leaf3', - }, - { - value: 'leaf4', - title: 'leaf4', - }, - { - value: 'leaf5', - title: 'leaf5', - }, - { - value: 'leaf6', - title: 'leaf6', - }, - ], - }, - { - value: 'parent 1-1', - title: 'parent 1-1', - children: [ - { - value: 'leaf11', - title: leaf11, - }, - ], - }, - ], - }, -]; export const RenderTreeSelect = (params: TextAreaProps) => { const { data, defaultValue, onChange } = params; - // console.log(data.options); - // const [value, setValue] = useState(); - - // const onChange = (newValue: string) => { - // setValue(newValue); - // }; - const [dropdownVisible, setDropdownVisible] = useState(false); - - const handleDropdownVisibleChange = (visible: boolean | ((prevState: boolean) => boolean)) => { - setDropdownVisible(visible); - - // 你可以在这里执行更多的逻辑,比如发送请求、更新状态等 - console.log('Dropdown is now:', visible ? 'visible' : 'hidden'); - }; - - const focus = () => { - // console.log('focus=========='); - }; + const attr = convertKeysToCamelCase(data.ui?.attr || {}); return ( - - - // TODO: Implement the TreeSelect component - // document.body} - // /> +
+ +
); }; diff --git a/web/components/flow/node-renderer/upload.tsx b/web/components/flow/node-renderer/upload.tsx new file mode 100644 index 000000000..35e1ddd75 --- /dev/null +++ b/web/components/flow/node-renderer/upload.tsx @@ -0,0 +1,40 @@ +import React from 'react'; +import { UploadOutlined } from '@ant-design/icons'; +import type { UploadProps } from 'antd'; +import { Button, message, Upload } from 'antd'; +import { convertKeysToCamelCase } from '@/utils/flow'; +import { IFlowNodeParameter } from '@/types/flow'; +import { useTranslation } from 'react-i18next'; + +const props: UploadProps = { + name: 'file', + action: 'https://660d2bd96ddfa2943b33731c.mockapi.io/api/upload', + headers: { + authorization: 'authorization-text', + }, +}; + +type Props = { + data: IFlowNodeParameter; + defaultValue: any; + onChange: (value: any) => void; +}; + +export const RenderUpload = (params: Props) => { + const { t } = useTranslation(); + + const { data, defaultValue, onChange } = params; + + const attr = convertKeysToCamelCase(data.ui?.attr || {}); + + return ( +
+ + + +
+ ) + + +} + diff --git a/web/types/flow.ts b/web/types/flow.ts index b62df1840..175047e31 100644 --- a/web/types/flow.ts +++ b/web/types/flow.ts @@ -54,10 +54,15 @@ export type IFlowNodeParameter = { export type IFlowNodeParameterUI = { ui_type: string; + language: string; attr: { disabled: boolean; [key: string]: any; }; + editor: { + width: Number; + height: Number; + }; show_input: boolean; }; diff --git a/web/utils/request.ts b/web/utils/request.ts index 102b7fdbd..8a490bfb5 100644 --- a/web/utils/request.ts +++ b/web/utils/request.ts @@ -1,7 +1,6 @@ import { message } from 'antd'; import axios from './ctx-axios'; import { isPlainObject } from 'lodash'; - const DEFAULT_HEADERS = { 'content-type': 'application/json', };