refactor: agent config refactor

This commit is contained in:
zhaoying
2026-01-16 15:48:02 +08:00
parent a6a18b7304
commit c2c2b306a2
18 changed files with 501 additions and 443 deletions

View File

@@ -0,0 +1,96 @@
import { forwardRef, useImperativeHandle, useState } from 'react';
import { Form, Input } from 'antd';
import { useTranslation } from 'react-i18next';
import type { ApiExtensionModalData, ApiExtensionModalRef } from './types'
import RbModal from '@/components/RbModal'
const FormItem = Form.Item;
interface ApiExtensionModalProps {
refresh: () => void;
}
const ApiExtensionModal = forwardRef<ApiExtensionModalRef, ApiExtensionModalProps>(({
refresh
}, ref) => {
const { t } = useTranslation();
const [visible, setVisible] = useState(false);
const [form] = Form.useForm<ApiExtensionModalData>();
const [loading, setLoading] = useState(false)
const values = Form.useWatch([], form);
// 封装取消方法,添加关闭弹窗逻辑
const handleClose = () => {
setVisible(false);
form.resetFields();
setLoading(false)
};
const handleOpen = () => {
form.resetFields();
setVisible(true);
};
// 封装保存方法,添加提交逻辑
const handleSave = () => {
form
.validateFields()
.then(() => {
setLoading(true)
console.log('values', values)
refresh()
})
.catch((err) => {
console.log('err', err)
});
}
// 暴露给父组件的方法
useImperativeHandle(ref, () => ({
handleOpen,
handleClose
}));
return (
<RbModal
title={t('application.addApiExtension')}
open={visible}
onCancel={handleClose}
okText={t('common.save')}
onOk={handleSave}
confirmLoading={loading}
>
<Form
form={form}
layout="vertical"
>
<FormItem
name="name"
label={t('application.name')}
rules={[{ required: true, message: t('common.pleaseEnter') }]}
>
<Input placeholder={t('common.enter')} />
</FormItem>
<FormItem
name="apiEndpoint"
label={t('application.apiEndpoint')}
rules={[{ required: true, message: t('common.pleaseEnter') }]}
>
<Input placeholder={t('common.enter')} />
</FormItem>
<FormItem
name="apiKey"
label={t('application.apiKey')}
rules={[{ required: true, message: t('common.pleaseEnter') }]}
>
<Input placeholder={t('common.enter')} />
</FormItem>
</Form>
</RbModal>
);
});
export default ApiExtensionModal;

View File

@@ -0,0 +1,239 @@
import { forwardRef, useImperativeHandle, useState, useRef } from 'react';
import { Form, Input, Select, InputNumber, Checkbox, Tag, Divider, Button } from 'antd';
import { useTranslation } from 'react-i18next';
import type { ApiExtensionModalRef, Variable, VariableEditModalRef } from './types'
import RbModal from '@/components/RbModal'
import SortableList from '@/components/SortableList'
import ApiExtensionModal from './ApiExtensionModal'
const FormItem = Form.Item;
interface VariableEditModalProps {
refreshTable: (values: Variable) => void;
}
const types = [
'text',
'paragraph',
// 'dropdownOptions',
'number',
// 'checkbox',
// 'apiVariable'
]
const variableType = {
text: 'string',
paragraph: 'string',
dropdownOptions: 'string',
number: 'number',
checkbox: 'boolean',
apiVariable: 'string',
}
const VariableEditModal = forwardRef<VariableEditModalRef, VariableEditModalProps>(({
refreshTable
}, ref) => {
const { t } = useTranslation();
const [visible, setVisible] = useState(false);
const [form] = Form.useForm<Variable>();
const [loading, setLoading] = useState(false)
const [editVo, setEditVo] = useState<Variable | null>(null)
const apiExtensionModalRef = useRef<ApiExtensionModalRef>(null)
const values = Form.useWatch([], form);
// 封装取消方法,添加关闭弹窗逻辑
const handleClose = () => {
setVisible(false);
form.resetFields();
setLoading(false)
setEditVo(null)
};
const handleOpen = (variable?: Variable) => {
setVisible(true);
if (variable) {
setEditVo(variable || null)
form.setFieldsValue(variable)
} else {
form.resetFields();
}
};
// 封装保存方法,添加提交逻辑
const handleSave = () => {
form.validateFields().then((values) => {
refreshTable({
...(editVo || {}),
...values,
})
handleClose()
})
}
// 暴露给父组件的方法
useImperativeHandle(ref, () => ({
handleOpen,
handleClose
}));
// 变量类型改变时,更新初始化其他字段值
const handleChangeType = (value: Variable['type']) => {
if (value) {
form.setFieldsValue({
type: value,
name: undefined,
display_name: undefined,
description: undefined,
max_length: undefined,
options: undefined,
api_extension: undefined,
// default_value: undefined
})
}
}
// 添加 API 扩展
const addApiExtension = () => {
apiExtensionModalRef.current?.handleOpen()
}
const refreshApiExtensionList = () => {}
return (
<>
<RbModal
title={t('application.editVariable')}
open={visible}
onCancel={handleClose}
okText={t('common.save')}
onOk={handleSave}
confirmLoading={loading}
>
<Form
form={form}
layout="vertical"
scrollToFirstError={{ behavior: 'instant', block: 'end', focus: true }}
>
{/* 变量类型 */}
<FormItem
name="type"
label={t('application.variableType')}
rules={[{ required: true, message: t('common.pleaseSelect') }]}
>
<Select
placeholder={t('common.pleaseSelect')}
options={types.map(key => ({
value: key,
label: t(`application.${key}`),
}))}
onChange={handleChangeType}
labelRender={(props) => <div className="rb:flex rb:justify-between rb:items-center">{props.label} <Tag color="blue">{variableType[props.value as keyof typeof variableType]}</Tag></div>}
optionRender={(props) => <div className="rb:flex rb:justify-between rb:items-center">{props.label} <Tag color="blue">{variableType[props.value as keyof typeof variableType]}</Tag></div>}
/>
</FormItem>
{/* 变量名称 */}
<FormItem
name="name"
label={t('application.variableName')}
rules={[
{ required: true, message: t('common.pleaseEnter') },
{ pattern: /^[a-zA-Z_][a-zA-Z0-9_]*$/, message: t('application.invalidVariableName') },
]}
>
<Input
placeholder={t('common.enter')}
onBlur={(e) => {
if (!form.getFieldValue('display_name')) {
form.setFieldValue('display_name', e.target.value)
}
}}
/>
</FormItem>
{/* 显示名称 */}
<FormItem
name="display_name"
label={t('application.displayName')}
rules={[{ required: true, message: t('common.pleaseEnter') }]}
>
<Input placeholder={t('common.enter')} />
</FormItem>
{/* 描述 */}
<FormItem
name="description"
label={t('application.description')}
>
<Input placeholder={t('common.enter')} />
</FormItem>
{/* 最大长度 */}
{['text', 'paragraph'].includes(values?.type) && (
<FormItem
name="max_length"
label={t('application.maxLength')}
>
<InputNumber placeholder={t('common.enter')} style={{ width: '100%' }} />
</FormItem>
)}
{/* 默认值 */}
{/* {['text', 'paragraph', 'number', 'checkbox'].includes(values?.type) && (
<FormItem
name="default_value"
label={t('application.defaultValue')}
>
{['text'].includes(values.type) && <Input placeholder={t('common.enter')} />}
{['paragraph'].includes(values.type) && <Input.TextArea placeholder={t('common.enter')} />}
{['number'].includes(values.type) && <InputNumber placeholder={t('common.enter')} style={{ width: '100%' }} />}
{['checkbox'].includes(values.type) && <Select options={[{ value: true, label: t('application.defaultChecked') }, { value: false, label: t('application.notDefaultChecked') }]} />}
</FormItem>
)} */}
{/* 选项 */}
{['dropdownOptions'].includes(values?.type) && (
<FormItem
name="options"
label={t('application.options')}
>
<SortableList />
</FormItem>
)}
{/* API 扩展 */}
{['apiVariable'].includes(values?.type) && (
<FormItem
name="api_extension"
label={t('application.apiExtension')}
>
<Select
placeholder={t('common.pleaseSelect')}
popupRender={(menu) => (
<>
{menu}
<Divider style={{ margin: '8px 0' }} />
<Button type="text" block onClick={addApiExtension}>
Add item
</Button>
</>
)}
/>
</FormItem>
)}
{/* 是否必填 */}
<FormItem
name="required"
valuePropName="checked"
>
<Checkbox>{t('application.required')}</Checkbox>
</FormItem>
{/* 是否隐藏 */}
{/* <FormItem
name="hidden"
valuePropName="checked"
>
<Checkbox>{t('application.hidden')}</Checkbox>
</FormItem> */}
</Form>
</RbModal>
<ApiExtensionModal
ref={apiExtensionModalRef}
refresh={refreshApiExtensionList}
/>
</>
);
});
export default VariableEditModal;

View File

@@ -0,0 +1,110 @@
import { type FC, useRef } from 'react'
import { useTranslation } from 'react-i18next'
import { Space, Button, Switch, Form } from 'antd'
import variablesEmpty from '@/assets/images/application/variablesEmpty.svg'
import Card from '../Card'
import Table from '@/components/Table';
import type { Variable, VariableEditModalRef } from './types'
import Empty from '@/components/Empty'
import VariableEditModal from './VariableEditModal'
interface VariableListProps {
value?: Variable[];
onChange?: (value: Variable[]) => void;
}
const VariableList: FC<VariableListProps> = ({value = [], onChange}) => {
const { t } = useTranslation()
const variableEditModalRef = useRef<VariableEditModalRef>(null)
const handleAddVariable = () => {
variableEditModalRef.current?.handleOpen()
}
const handleSaveVariable = (variable: Variable) => {
const newList = [...(value || [])]
if (variable.index !== undefined && variable.index >= 0) {
const index = newList.findIndex(item => item.index === variable.index)
if (index !== -1) {
newList[index] = variable
}
} else {
newList.push({ ...variable, index: Date.now() })
}
onChange?.(newList)
}
return (
<Card
title={<>
{t('application.variableConfiguration')}
<span className="rb:font-regular rb:text-[12px] rb:text-[#5B6167]"> ({t('application.VariableManagementDesc')})</span>
</>}
extra={<Button style={{ padding: '0 8px', height: '24px' }} onClick={handleAddVariable}>+ {t('application.addVariables')}</Button>}
>
<Form.List name="variables" initialValue={value}>
{(fields, { remove }) => {
return (
<>
{fields.length > 0 ? (
<div className="rb:mt-3">
<Table
rowKey="index"
pagination={false}
columns={[
{
title: t('application.variableType'),
dataIndex: 'type',
key: 'type',
render: (type) => t(`application.${type}`)
},
{
title: t('application.variableKey'),
dataIndex: 'name',
key: 'name',
},
{
title: t('application.variableName'),
dataIndex: 'display_name',
key: 'display_name',
},
{
title: t('application.optional'),
dataIndex: 'required',
key: 'required',
render: (required) => <Switch checked={!required} disabled />
},
{
title: t('common.operation'),
key: 'action',
render: (_, record, index: number) => (
<Space size="middle">
<Button
type="link"
onClick={() => variableEditModalRef.current?.handleOpen(record as Variable)}
>
{t('common.edit')}
</Button>
<Button type="link" danger onClick={() => remove(index)}>
{t('common.delete')}
</Button>
</Space>
),
},
]}
initialData={value as unknown as Record<string, unknown>[]}
emptySize={88}
/>
</div>
) : (
<Empty url={variablesEmpty} size={88} subTitle={t('application.variablesEmpty')} />
)}
</>
)
}}
</Form.List>
<VariableEditModal
ref={variableEditModalRef}
refreshTable={handleSaveVariable}
/>
</Card>
)
}
export default VariableList

View File

@@ -0,0 +1,28 @@
export interface Variable {
index?: number;
name: string;
display_name: string;
type: string;
required: boolean;
max_length?: number;
description?: string;
key?: string;
default_value?: string;
options?: string[];
api_extension?: string;
hidden?: boolean;
value?: any;
}
export interface VariableEditModalRef {
handleOpen: (values?: Variable) => void;
}
export interface ApiExtensionModalData {
name: string;
apiEndpoint: string;
apiKey: string;
}
export interface ApiExtensionModalRef {
handleOpen: () => void;
}