mirror of
https://git.mirrors.martin98.com/https://github.com/infiniflow/ragflow.git
synced 2025-06-30 06:45:10 +08:00
### What problem does this PR solve? feat: Add component Invoke #2908 ### Type of change - [x] New Feature (non-breaking change which adds functionality)
This commit is contained in:
parent
d133cc043b
commit
497bc1438a
36
web/package-lock.json
generated
36
web/package-lock.json
generated
@ -11,6 +11,7 @@
|
|||||||
"@ant-design/pro-layout": "^7.17.16",
|
"@ant-design/pro-layout": "^7.17.16",
|
||||||
"@antv/g6": "^5.0.10",
|
"@antv/g6": "^5.0.10",
|
||||||
"@js-preview/excel": "^1.7.8",
|
"@js-preview/excel": "^1.7.8",
|
||||||
|
"@monaco-editor/react": "^4.6.0",
|
||||||
"@tanstack/react-query": "^5.40.0",
|
"@tanstack/react-query": "^5.40.0",
|
||||||
"@tanstack/react-query-devtools": "^5.51.5",
|
"@tanstack/react-query-devtools": "^5.51.5",
|
||||||
"ahooks": "^3.7.10",
|
"ahooks": "^3.7.10",
|
||||||
@ -3843,6 +3844,30 @@
|
|||||||
"resolved": "https://registry.npmmirror.com/react-is/-/react-is-16.13.1.tgz",
|
"resolved": "https://registry.npmmirror.com/react-is/-/react-is-16.13.1.tgz",
|
||||||
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
|
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
|
||||||
},
|
},
|
||||||
|
"node_modules/@monaco-editor/loader": {
|
||||||
|
"version": "1.4.0",
|
||||||
|
"resolved": "https://registry.npmmirror.com/@monaco-editor/loader/-/loader-1.4.0.tgz",
|
||||||
|
"integrity": "sha512-00ioBig0x642hytVspPl7DbQyaSWRaolYie/UFNjoTdvoKPzo6xrXLhTk9ixgIKcLH5b5vDOjVNiGyY+uDCUlg==",
|
||||||
|
"dependencies": {
|
||||||
|
"state-local": "^1.0.6"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"monaco-editor": ">= 0.21.0 < 1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@monaco-editor/react": {
|
||||||
|
"version": "4.6.0",
|
||||||
|
"resolved": "https://registry.npmmirror.com/@monaco-editor/react/-/react-4.6.0.tgz",
|
||||||
|
"integrity": "sha512-RFkU9/i7cN2bsq/iTkurMWOEErmYcY6JiQI3Jn+WeR/FGISH8JbHERjpS9oRuSOPvDMJI0Z8nJeKkbOs9sBYQw==",
|
||||||
|
"dependencies": {
|
||||||
|
"@monaco-editor/loader": "^1.4.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"monaco-editor": ">= 0.25.0 < 1",
|
||||||
|
"react": "^16.8.0 || ^17.0.0 || ^18.0.0",
|
||||||
|
"react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@mrmlnc/readdir-enhanced": {
|
"node_modules/@mrmlnc/readdir-enhanced": {
|
||||||
"version": "2.2.1",
|
"version": "2.2.1",
|
||||||
"resolved": "https://registry.npmmirror.com/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz",
|
"resolved": "https://registry.npmmirror.com/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz",
|
||||||
@ -19956,6 +19981,12 @@
|
|||||||
"node": "*"
|
"node": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/monaco-editor": {
|
||||||
|
"version": "0.52.0",
|
||||||
|
"resolved": "https://registry.npmmirror.com/monaco-editor/-/monaco-editor-0.52.0.tgz",
|
||||||
|
"integrity": "sha512-OeWhNpABLCeTqubfqLMXGsqf6OmPU6pHM85kF3dhy6kq5hnhuVS1p3VrEW/XhWHc71P2tHyS5JFySD8mgs1crw==",
|
||||||
|
"peer": true
|
||||||
|
},
|
||||||
"node_modules/mri": {
|
"node_modules/mri": {
|
||||||
"version": "1.2.0",
|
"version": "1.2.0",
|
||||||
"resolved": "https://registry.npmmirror.com/mri/-/mri-1.2.0.tgz",
|
"resolved": "https://registry.npmmirror.com/mri/-/mri-1.2.0.tgz",
|
||||||
@ -25827,6 +25858,11 @@
|
|||||||
"resolved": "https://registry.npmmirror.com/stackframe/-/stackframe-1.3.4.tgz",
|
"resolved": "https://registry.npmmirror.com/stackframe/-/stackframe-1.3.4.tgz",
|
||||||
"integrity": "sha512-oeVtt7eWQS+Na6F//S4kJ2K2VbRlS9D43mAlMyVpVWovy9o+jfgH8O9agzANzaiLjclA0oYzUXEM4PurhSUChw=="
|
"integrity": "sha512-oeVtt7eWQS+Na6F//S4kJ2K2VbRlS9D43mAlMyVpVWovy9o+jfgH8O9agzANzaiLjclA0oYzUXEM4PurhSUChw=="
|
||||||
},
|
},
|
||||||
|
"node_modules/state-local": {
|
||||||
|
"version": "1.0.7",
|
||||||
|
"resolved": "https://registry.npmmirror.com/state-local/-/state-local-1.0.7.tgz",
|
||||||
|
"integrity": "sha512-HTEHMNieakEnoe33shBYcZ7NX83ACUjCu8c40iOGEZsngj9zRnkqS9j1pqQPXwobB0ZcVTk27REb7COQ0UR59w=="
|
||||||
|
},
|
||||||
"node_modules/static-extend": {
|
"node_modules/static-extend": {
|
||||||
"version": "0.1.2",
|
"version": "0.1.2",
|
||||||
"resolved": "https://registry.npmmirror.com/static-extend/-/static-extend-0.1.2.tgz",
|
"resolved": "https://registry.npmmirror.com/static-extend/-/static-extend-0.1.2.tgz",
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
"@ant-design/pro-layout": "^7.17.16",
|
"@ant-design/pro-layout": "^7.17.16",
|
||||||
"@antv/g6": "^5.0.10",
|
"@antv/g6": "^5.0.10",
|
||||||
"@js-preview/excel": "^1.7.8",
|
"@js-preview/excel": "^1.7.8",
|
||||||
|
"@monaco-editor/react": "^4.6.0",
|
||||||
"@tanstack/react-query": "^5.40.0",
|
"@tanstack/react-query": "^5.40.0",
|
||||||
"@tanstack/react-query-devtools": "^5.51.5",
|
"@tanstack/react-query-devtools": "^5.51.5",
|
||||||
"ahooks": "^3.7.10",
|
"ahooks": "^3.7.10",
|
||||||
|
15
web/src/assets/svg/invoke-ai.svg
Normal file
15
web/src/assets/svg/invoke-ai.svg
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||||
|
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px"
|
||||||
|
y="0px" width="200" height="200" viewBox="0 0 1024 1024" enable-background="new 0 0 200 200" xml:space="preserve">
|
||||||
|
<image id="image0" width="1024" height="1024" x="0" y="0" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAMAAABg3Am1AAAAIGNIUk0AAHomAACAhAAA+gAAAIDo
|
||||||
|
AAB1MAAA6mAAADqYAAAXcJy6UTwAAABvUExUReb9E6S0FHJ8FbHDFCwuF1hfFomWFRgYGFFYFrLD
|
||||||
|
FM7jE7zPFLXGFCcpF4uYFNvxE9PoE6KyFBwcF8LVE1deFkRJFuT7E83hEyMkF42bFMndEyUmF8nc
|
||||||
|
E+L5E5uqFDI1F9nuE0VKFrHDE7zOE/////VUQJUAAAABYktHRCS0BvmZAAAAB3RJTUUH6AocBw8U
|
||||||
|
/rEd/gAAAIVJREFUSMftkkkKgDAMRZ3qPFvnWe9/Rxtd2U0bEEHsW71CP4GfaJpC8Rt0g8MUBAyL
|
||||||
|
3LBsUYDc3+T5gAO4oN6pooAfMMIoZpqABqlUV1leINulZYUL1E2LHNE2NS5QlRQ5ouszqX+DB4zM
|
||||||
|
pvlUXxC4FreArlKLe+GWsOe92Rw7sl2F4sMcX94Fwx5NOjAAAAAldEVYdGRhdGU6Y3JlYXRlADIw
|
||||||
|
MjQtMTAtMjhUMDc6MTU6MjArMDA6MDCKhNSdAAAAJXRFWHRkYXRlOm1vZGlmeQAyMDI0LTEwLTI4
|
||||||
|
VDA3OjE1OjIwKzAwOjAw+9lsIQAAACh0RVh0ZGF0ZTp0aW1lc3RhbXAAMjAyNC0xMC0yOFQwNzox
|
||||||
|
NToyMCswMDowMKzMTf4AAAAASUVORK5CYII=" />
|
||||||
|
</svg>
|
After Width: | Height: | Size: 1.2 KiB |
@ -29,6 +29,7 @@ export default {
|
|||||||
move: 'Move',
|
move: 'Move',
|
||||||
warn: 'Warn',
|
warn: 'Warn',
|
||||||
action: 'Action',
|
action: 'Action',
|
||||||
|
s: 'S',
|
||||||
},
|
},
|
||||||
login: {
|
login: {
|
||||||
login: 'Sign in',
|
login: 'Sign in',
|
||||||
@ -1016,6 +1017,13 @@ The above is the content you need to summarize.`,
|
|||||||
note: 'Note',
|
note: 'Note',
|
||||||
noteDescription: 'Note',
|
noteDescription: 'Note',
|
||||||
notePlaceholder: 'Please enter a note',
|
notePlaceholder: 'Please enter a note',
|
||||||
|
invoke: 'Invoke',
|
||||||
|
invokeDescription:
|
||||||
|
'This component can invoke remote end point call. Put the output of other components as parameters or set constant parameters to call remote functions.',
|
||||||
|
url: 'Url',
|
||||||
|
method: 'Method',
|
||||||
|
timeout: 'Timeout',
|
||||||
|
headers: 'Headers',
|
||||||
},
|
},
|
||||||
footer: {
|
footer: {
|
||||||
profile: 'All rights reserved @ React',
|
profile: 'All rights reserved @ React',
|
||||||
|
@ -29,6 +29,7 @@ export default {
|
|||||||
move: '移動',
|
move: '移動',
|
||||||
warn: '提醒',
|
warn: '提醒',
|
||||||
action: '操作',
|
action: '操作',
|
||||||
|
s: '秒',
|
||||||
},
|
},
|
||||||
login: {
|
login: {
|
||||||
login: '登入',
|
login: '登入',
|
||||||
@ -965,6 +966,13 @@ export default {
|
|||||||
note: '註解',
|
note: '註解',
|
||||||
noteDescription: '註解',
|
noteDescription: '註解',
|
||||||
notePlaceholder: '請輸入註釋',
|
notePlaceholder: '請輸入註釋',
|
||||||
|
invoke: 'Invoke',
|
||||||
|
invokeDescription:
|
||||||
|
'此元件可以呼叫遠端端點呼叫。將其他元件的輸出作為參數或設定常數參數來呼叫遠端函數。',
|
||||||
|
url: '網址',
|
||||||
|
method: '方法',
|
||||||
|
timeout: '超時',
|
||||||
|
headers: '請求頭',
|
||||||
},
|
},
|
||||||
footer: {
|
footer: {
|
||||||
profile: '“保留所有權利 @ react”',
|
profile: '“保留所有權利 @ react”',
|
||||||
|
@ -29,6 +29,7 @@ export default {
|
|||||||
move: '移动',
|
move: '移动',
|
||||||
warn: '提醒',
|
warn: '提醒',
|
||||||
action: '操作',
|
action: '操作',
|
||||||
|
s: '秒',
|
||||||
},
|
},
|
||||||
login: {
|
login: {
|
||||||
login: '登录',
|
login: '登录',
|
||||||
@ -985,6 +986,13 @@ export default {
|
|||||||
note: '注释',
|
note: '注释',
|
||||||
noteDescription: '注释',
|
noteDescription: '注释',
|
||||||
notePlaceholder: '请输入注释',
|
notePlaceholder: '请输入注释',
|
||||||
|
invoke: 'Invoke',
|
||||||
|
invokeDescription:
|
||||||
|
'该组件可以调用远程端点调用。将其他组件的输出作为参数或设置常量参数来调用远程函数。',
|
||||||
|
url: 'Url',
|
||||||
|
method: '方法',
|
||||||
|
timeout: '超时',
|
||||||
|
headers: '请求头',
|
||||||
},
|
},
|
||||||
footer: {
|
footer: {
|
||||||
profile: 'All rights reserved @ React',
|
profile: 'All rights reserved @ React',
|
||||||
|
@ -12,6 +12,7 @@ import { ReactComponent as ExeSqlIcon } from '@/assets/svg/exesql.svg';
|
|||||||
import { ReactComponent as GithubIcon } from '@/assets/svg/github.svg';
|
import { ReactComponent as GithubIcon } from '@/assets/svg/github.svg';
|
||||||
import { ReactComponent as GoogleScholarIcon } from '@/assets/svg/google-scholar.svg';
|
import { ReactComponent as GoogleScholarIcon } from '@/assets/svg/google-scholar.svg';
|
||||||
import { ReactComponent as GoogleIcon } from '@/assets/svg/google.svg';
|
import { ReactComponent as GoogleIcon } from '@/assets/svg/google.svg';
|
||||||
|
import { ReactComponent as InvokeIcon } from '@/assets/svg/invoke-ai.svg';
|
||||||
import { ReactComponent as Jin10Icon } from '@/assets/svg/jin10.svg';
|
import { ReactComponent as Jin10Icon } from '@/assets/svg/jin10.svg';
|
||||||
import { ReactComponent as KeywordIcon } from '@/assets/svg/keyword.svg';
|
import { ReactComponent as KeywordIcon } from '@/assets/svg/keyword.svg';
|
||||||
import { ReactComponent as NoteIcon } from '@/assets/svg/note.svg';
|
import { ReactComponent as NoteIcon } from '@/assets/svg/note.svg';
|
||||||
@ -75,6 +76,7 @@ export enum Operator {
|
|||||||
TuShare = 'TuShare',
|
TuShare = 'TuShare',
|
||||||
Note = 'Note',
|
Note = 'Note',
|
||||||
Crawler = 'Crawler',
|
Crawler = 'Crawler',
|
||||||
|
Invoke = 'Invoke',
|
||||||
}
|
}
|
||||||
|
|
||||||
export const CommonOperatorList = Object.values(Operator).filter(
|
export const CommonOperatorList = Object.values(Operator).filter(
|
||||||
@ -113,6 +115,7 @@ export const operatorIconMap = {
|
|||||||
[Operator.TuShare]: TuShareIcon,
|
[Operator.TuShare]: TuShareIcon,
|
||||||
[Operator.Note]: NoteIcon,
|
[Operator.Note]: NoteIcon,
|
||||||
[Operator.Crawler]: CrawlerIcon,
|
[Operator.Crawler]: CrawlerIcon,
|
||||||
|
[Operator.Invoke]: InvokeIcon,
|
||||||
};
|
};
|
||||||
|
|
||||||
export const operatorMap: Record<
|
export const operatorMap: Record<
|
||||||
@ -239,6 +242,9 @@ export const operatorMap: Record<
|
|||||||
[Operator.Crawler]: {
|
[Operator.Crawler]: {
|
||||||
backgroundColor: '#dee0e2',
|
backgroundColor: '#dee0e2',
|
||||||
},
|
},
|
||||||
|
[Operator.Invoke]: {
|
||||||
|
backgroundColor: '#dee0e2',
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export const componentMenuList = [
|
export const componentMenuList = [
|
||||||
@ -332,6 +338,9 @@ export const componentMenuList = [
|
|||||||
{
|
{
|
||||||
name: Operator.Crawler,
|
name: Operator.Crawler,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: Operator.Invoke,
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
export const initialRetrievalValues = {
|
export const initialRetrievalValues = {
|
||||||
@ -509,6 +518,18 @@ export const initialCrawlerValues = {
|
|||||||
extract_type: 'markdown',
|
extract_type: 'markdown',
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const initialInvokeValues = {
|
||||||
|
url: 'http://',
|
||||||
|
method: 'GET',
|
||||||
|
timeout: 60,
|
||||||
|
headers: `{
|
||||||
|
"Accept": "*/*",
|
||||||
|
"Cache-Control": "no-cache",
|
||||||
|
"Connection": "keep-alive"
|
||||||
|
}`,
|
||||||
|
proxy: 'http://',
|
||||||
|
};
|
||||||
|
|
||||||
export const CategorizeAnchorPointPositions = [
|
export const CategorizeAnchorPointPositions = [
|
||||||
{ top: 1, right: 34 },
|
{ top: 1, right: 34 },
|
||||||
{ top: 8, right: 18 },
|
{ top: 8, right: 18 },
|
||||||
@ -621,6 +642,7 @@ export const NodeMap = {
|
|||||||
[Operator.TuShare]: 'ragNode',
|
[Operator.TuShare]: 'ragNode',
|
||||||
[Operator.Note]: 'noteNode',
|
[Operator.Note]: 'noteNode',
|
||||||
[Operator.Crawler]: 'ragNode',
|
[Operator.Crawler]: 'ragNode',
|
||||||
|
[Operator.Invoke]: 'ragNode',
|
||||||
};
|
};
|
||||||
|
|
||||||
export const LanguageOptions = [
|
export const LanguageOptions = [
|
||||||
|
@ -20,6 +20,7 @@ import GenerateForm from '../form/generate-form';
|
|||||||
import GithubForm from '../form/github-form';
|
import GithubForm from '../form/github-form';
|
||||||
import GoogleForm from '../form/google-form';
|
import GoogleForm from '../form/google-form';
|
||||||
import GoogleScholarForm from '../form/google-scholar-form';
|
import GoogleScholarForm from '../form/google-scholar-form';
|
||||||
|
import InvokeForm from '../form/invoke-form';
|
||||||
import Jin10Form from '../form/jin10-form';
|
import Jin10Form from '../form/jin10-form';
|
||||||
import KeywordExtractForm from '../form/keyword-extract-form';
|
import KeywordExtractForm from '../form/keyword-extract-form';
|
||||||
import MessageForm from '../form/message-form';
|
import MessageForm from '../form/message-form';
|
||||||
@ -74,6 +75,9 @@ const FormMap = {
|
|||||||
[Operator.Jin10]: Jin10Form,
|
[Operator.Jin10]: Jin10Form,
|
||||||
[Operator.TuShare]: TuShareForm,
|
[Operator.TuShare]: TuShareForm,
|
||||||
[Operator.Crawler]: CrawlerForm,
|
[Operator.Crawler]: CrawlerForm,
|
||||||
|
[Operator.Invoke]: InvokeForm,
|
||||||
|
[Operator.Concentrator]: <></>,
|
||||||
|
[Operator.Note]: <></>,
|
||||||
};
|
};
|
||||||
|
|
||||||
const EmptyContent = () => <div></div>;
|
const EmptyContent = () => <div></div>;
|
||||||
|
119
web/src/pages/flow/form/invoke-form/dynamic-variables.tsx
Normal file
119
web/src/pages/flow/form/invoke-form/dynamic-variables.tsx
Normal file
@ -0,0 +1,119 @@
|
|||||||
|
import { EditableCell, EditableRow } from '@/components/editable-cell';
|
||||||
|
import { useTranslate } from '@/hooks/common-hooks';
|
||||||
|
import { DeleteOutlined } from '@ant-design/icons';
|
||||||
|
import { Button, Flex, Input, Select, Table, TableProps } from 'antd';
|
||||||
|
import { useBuildComponentIdSelectOptions } from '../../hooks';
|
||||||
|
import { IInvokeVariable } from '../../interface';
|
||||||
|
import { useHandleOperateParameters } from './hooks';
|
||||||
|
|
||||||
|
import { trim } from 'lodash';
|
||||||
|
import styles from './index.less';
|
||||||
|
|
||||||
|
interface IProps {
|
||||||
|
nodeId?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const components = {
|
||||||
|
body: {
|
||||||
|
row: EditableRow,
|
||||||
|
cell: EditableCell,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const DynamicVariables = ({ nodeId }: IProps) => {
|
||||||
|
const { t } = useTranslate('flow');
|
||||||
|
|
||||||
|
const options = useBuildComponentIdSelectOptions(nodeId);
|
||||||
|
const {
|
||||||
|
dataSource,
|
||||||
|
handleAdd,
|
||||||
|
handleRemove,
|
||||||
|
handleSave,
|
||||||
|
handleComponentIdChange,
|
||||||
|
handleValueChange,
|
||||||
|
} = useHandleOperateParameters(nodeId!);
|
||||||
|
|
||||||
|
const columns: TableProps<IInvokeVariable>['columns'] = [
|
||||||
|
{
|
||||||
|
title: t('key'),
|
||||||
|
dataIndex: 'key',
|
||||||
|
key: 'key',
|
||||||
|
// width: 40,
|
||||||
|
onCell: (record: IInvokeVariable) => ({
|
||||||
|
record,
|
||||||
|
editable: true,
|
||||||
|
dataIndex: 'key',
|
||||||
|
title: 'key',
|
||||||
|
handleSave,
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: t('componentId'),
|
||||||
|
dataIndex: 'component_id',
|
||||||
|
key: 'component_id',
|
||||||
|
align: 'center',
|
||||||
|
width: 140,
|
||||||
|
render(text, record) {
|
||||||
|
return (
|
||||||
|
<Select
|
||||||
|
style={{ width: '100%' }}
|
||||||
|
allowClear
|
||||||
|
options={options}
|
||||||
|
value={text}
|
||||||
|
disabled={trim(record.value) !== ''}
|
||||||
|
onChange={handleComponentIdChange(record)}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: t('value'),
|
||||||
|
dataIndex: 'value',
|
||||||
|
key: 'value',
|
||||||
|
align: 'center',
|
||||||
|
width: 140,
|
||||||
|
render(text, record) {
|
||||||
|
return (
|
||||||
|
<Input
|
||||||
|
value={text}
|
||||||
|
disabled={!!record.component_id}
|
||||||
|
onChange={handleValueChange(record)}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: t('operation'),
|
||||||
|
dataIndex: 'operation',
|
||||||
|
width: 20,
|
||||||
|
key: 'operation',
|
||||||
|
align: 'center',
|
||||||
|
fixed: 'right',
|
||||||
|
render(_, record) {
|
||||||
|
return <DeleteOutlined onClick={handleRemove(record.id)} />;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
return (
|
||||||
|
<section>
|
||||||
|
<Flex justify="end">
|
||||||
|
<Button size="small" onClick={handleAdd}>
|
||||||
|
{t('add')}
|
||||||
|
</Button>
|
||||||
|
</Flex>
|
||||||
|
<Table
|
||||||
|
dataSource={dataSource}
|
||||||
|
columns={columns}
|
||||||
|
rowKey={'id'}
|
||||||
|
className={styles.variableTable}
|
||||||
|
components={components}
|
||||||
|
rowClassName={() => styles.editableRow}
|
||||||
|
scroll={{ x: true }}
|
||||||
|
bordered
|
||||||
|
/>
|
||||||
|
</section>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default DynamicVariables;
|
87
web/src/pages/flow/form/invoke-form/hooks.ts
Normal file
87
web/src/pages/flow/form/invoke-form/hooks.ts
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
import get from 'lodash/get';
|
||||||
|
import { ChangeEventHandler, useCallback, useMemo } from 'react';
|
||||||
|
import { v4 as uuid } from 'uuid';
|
||||||
|
import { IGenerateParameter, IInvokeVariable } from '../../interface';
|
||||||
|
import useGraphStore from '../../store';
|
||||||
|
|
||||||
|
export const useHandleOperateParameters = (nodeId: string) => {
|
||||||
|
const { getNode, updateNodeForm } = useGraphStore((state) => state);
|
||||||
|
const node = getNode(nodeId);
|
||||||
|
const dataSource: IGenerateParameter[] = useMemo(
|
||||||
|
() => get(node, 'data.form.variables', []) as IGenerateParameter[],
|
||||||
|
[node],
|
||||||
|
);
|
||||||
|
|
||||||
|
const changeValue = useCallback(
|
||||||
|
(row: IInvokeVariable, field: string, value: string) => {
|
||||||
|
const newData = [...dataSource];
|
||||||
|
const index = newData.findIndex((item) => row.id === item.id);
|
||||||
|
const item = newData[index];
|
||||||
|
newData.splice(index, 1, {
|
||||||
|
...item,
|
||||||
|
[field]: value,
|
||||||
|
});
|
||||||
|
|
||||||
|
updateNodeForm(nodeId, { variables: newData });
|
||||||
|
},
|
||||||
|
[dataSource, nodeId, updateNodeForm],
|
||||||
|
);
|
||||||
|
|
||||||
|
const handleComponentIdChange = useCallback(
|
||||||
|
(row: IInvokeVariable) => (value: string) => {
|
||||||
|
changeValue(row, 'component_id', value);
|
||||||
|
},
|
||||||
|
[changeValue],
|
||||||
|
);
|
||||||
|
|
||||||
|
const handleValueChange = useCallback(
|
||||||
|
(row: IInvokeVariable): ChangeEventHandler<HTMLInputElement> =>
|
||||||
|
(e) => {
|
||||||
|
changeValue(row, 'value', e.target.value);
|
||||||
|
},
|
||||||
|
[changeValue],
|
||||||
|
);
|
||||||
|
|
||||||
|
const handleRemove = useCallback(
|
||||||
|
(id?: string) => () => {
|
||||||
|
const newData = dataSource.filter((item) => item.id !== id);
|
||||||
|
updateNodeForm(nodeId, { variables: newData });
|
||||||
|
},
|
||||||
|
[updateNodeForm, nodeId, dataSource],
|
||||||
|
);
|
||||||
|
|
||||||
|
const handleAdd = useCallback(() => {
|
||||||
|
updateNodeForm(nodeId, {
|
||||||
|
variables: [
|
||||||
|
...dataSource,
|
||||||
|
{
|
||||||
|
id: uuid(),
|
||||||
|
key: '',
|
||||||
|
component_id: undefined,
|
||||||
|
value: '',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
}, [dataSource, nodeId, updateNodeForm]);
|
||||||
|
|
||||||
|
const handleSave = (row: IGenerateParameter) => {
|
||||||
|
const newData = [...dataSource];
|
||||||
|
const index = newData.findIndex((item) => row.id === item.id);
|
||||||
|
const item = newData[index];
|
||||||
|
newData.splice(index, 1, {
|
||||||
|
...item,
|
||||||
|
...row,
|
||||||
|
});
|
||||||
|
|
||||||
|
updateNodeForm(nodeId, { variables: newData });
|
||||||
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
handleAdd,
|
||||||
|
handleRemove,
|
||||||
|
handleComponentIdChange,
|
||||||
|
handleValueChange,
|
||||||
|
handleSave,
|
||||||
|
dataSource,
|
||||||
|
};
|
||||||
|
};
|
21
web/src/pages/flow/form/invoke-form/index.less
Normal file
21
web/src/pages/flow/form/invoke-form/index.less
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
.variableTable {
|
||||||
|
margin-top: 14px;
|
||||||
|
}
|
||||||
|
.editableRow {
|
||||||
|
:global(.editable-cell) {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
:global(.editable-cell-value-wrap) {
|
||||||
|
padding: 5px 12px;
|
||||||
|
cursor: pointer;
|
||||||
|
height: 30px !important;
|
||||||
|
}
|
||||||
|
&:hover {
|
||||||
|
:global(.editable-cell-value-wrap) {
|
||||||
|
padding: 4px 11px;
|
||||||
|
border: 1px solid #d9d9d9;
|
||||||
|
border-radius: 2px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
72
web/src/pages/flow/form/invoke-form/index.tsx
Normal file
72
web/src/pages/flow/form/invoke-form/index.tsx
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
import Editor from '@monaco-editor/react';
|
||||||
|
import { Form, Input, InputNumber, Select, Space } from 'antd';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
|
import { useSetLlmSetting } from '../../hooks';
|
||||||
|
import { IOperatorForm } from '../../interface';
|
||||||
|
import DynamicVariables from './dynamic-variables';
|
||||||
|
|
||||||
|
enum Method {
|
||||||
|
GET = 'GET',
|
||||||
|
POST = 'POST',
|
||||||
|
PUT = 'PUT',
|
||||||
|
}
|
||||||
|
|
||||||
|
const MethodOptions = [Method.GET, Method.POST, Method.PUT].map((x) => ({
|
||||||
|
label: x,
|
||||||
|
value: x,
|
||||||
|
}));
|
||||||
|
|
||||||
|
interface TimeoutInputProps {
|
||||||
|
value?: number;
|
||||||
|
onChange?: (value: number | null) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
const TimeoutInput = ({ value, onChange }: TimeoutInputProps) => {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
return (
|
||||||
|
<Space>
|
||||||
|
<InputNumber value={value} onChange={onChange} /> {t('common.s')}
|
||||||
|
</Space>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const InvokeForm = ({ onValuesChange, form, node }: IOperatorForm) => {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
|
||||||
|
useSetLlmSetting(form);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Form
|
||||||
|
name="basic"
|
||||||
|
autoComplete="off"
|
||||||
|
form={form}
|
||||||
|
onValuesChange={onValuesChange}
|
||||||
|
layout={'vertical'}
|
||||||
|
>
|
||||||
|
<Form.Item name={'url'} label={t('flow.url')}>
|
||||||
|
<Input />
|
||||||
|
</Form.Item>
|
||||||
|
<Form.Item
|
||||||
|
name={'method'}
|
||||||
|
label={t('flow.method')}
|
||||||
|
initialValue={Method.GET}
|
||||||
|
>
|
||||||
|
<Select options={MethodOptions} />
|
||||||
|
</Form.Item>
|
||||||
|
<Form.Item name={'timeout'} label={t('flow.timeout')}>
|
||||||
|
<TimeoutInput></TimeoutInput>
|
||||||
|
</Form.Item>
|
||||||
|
<Form.Item name={'headers'} label={t('flow.headers')}>
|
||||||
|
<Editor height={200} defaultLanguage="json" theme="vs-dark" />
|
||||||
|
</Form.Item>
|
||||||
|
<Form.Item name={'proxy'} label={t('flow.proxy')}>
|
||||||
|
<Input />
|
||||||
|
</Form.Item>
|
||||||
|
<DynamicVariables nodeId={node?.id}></DynamicVariables>
|
||||||
|
</Form>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default InvokeForm;
|
@ -49,6 +49,7 @@ import {
|
|||||||
initialGithubValues,
|
initialGithubValues,
|
||||||
initialGoogleScholarValues,
|
initialGoogleScholarValues,
|
||||||
initialGoogleValues,
|
initialGoogleValues,
|
||||||
|
initialInvokeValues,
|
||||||
initialJin10Values,
|
initialJin10Values,
|
||||||
initialKeywordExtractValues,
|
initialKeywordExtractValues,
|
||||||
initialMessageValues,
|
initialMessageValues,
|
||||||
@ -132,6 +133,7 @@ export const useInitializeOperatorParams = () => {
|
|||||||
[Operator.TuShare]: initialTuShareValues,
|
[Operator.TuShare]: initialTuShareValues,
|
||||||
[Operator.Note]: initialNoteValues,
|
[Operator.Note]: initialNoteValues,
|
||||||
[Operator.Crawler]: initialCrawlerValues,
|
[Operator.Crawler]: initialCrawlerValues,
|
||||||
|
[Operator.Invoke]: initialInvokeValues,
|
||||||
};
|
};
|
||||||
}, [llmId]);
|
}, [llmId]);
|
||||||
|
|
||||||
|
@ -51,6 +51,10 @@ export interface IGenerateParameter {
|
|||||||
component_id?: string;
|
component_id?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface IInvokeVariable extends IGenerateParameter {
|
||||||
|
value?: string;
|
||||||
|
}
|
||||||
|
|
||||||
export type ICategorizeItemResult = Record<
|
export type ICategorizeItemResult = Record<
|
||||||
string,
|
string,
|
||||||
Omit<ICategorizeItem, 'name'>
|
Omit<ICategorizeItem, 'name'>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user