mirror of
https://github.com/csunny/DB-GPT.git
synced 2025-09-25 03:20:41 +00:00
feat(web): Unified frontend code style (#1923)
Co-authored-by: Fangyin Cheng <staneyffer@gmail.com> Co-authored-by: 谨欣 <echo.cmy@antgroup.com> Co-authored-by: 严志勇 <yanzhiyong@tiansuixiansheng.com> Co-authored-by: yanzhiyong <932374019@qq.com>
This commit is contained in:
@@ -1,13 +1,17 @@
|
||||
import React, { useEffect, useMemo } from 'react';
|
||||
import cls from 'classnames';
|
||||
import { Form, Select } from 'antd';
|
||||
import PreviewFlow from '@/components/flow/preview-flow';
|
||||
import { useRequest } from 'ahooks';
|
||||
import { apiInterceptors, getFlows } from '@/client/api';
|
||||
import PreviewFlow from '@/components/flow/preview-flow';
|
||||
import { IFlowResponse } from '@/types/flow';
|
||||
import { useRequest } from 'ahooks';
|
||||
import { Form, Select } from 'antd';
|
||||
import cls from 'classnames';
|
||||
import React, { useEffect, useMemo } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
const AwelLayout: React.FC<{ initValue: any; updateData: (data: any) => void; classNames?: string }> = ({ initValue, updateData, classNames }) => {
|
||||
const AwelLayout: React.FC<{
|
||||
initValue: any;
|
||||
updateData: (data: any) => void;
|
||||
classNames?: string;
|
||||
}> = ({ initValue, updateData, classNames }) => {
|
||||
const { t } = useTranslation();
|
||||
const [form] = Form.useForm();
|
||||
const flow = Form.useWatch('flow', form);
|
||||
@@ -24,7 +28,12 @@ const AwelLayout: React.FC<{ initValue: any; updateData: (data: any) => void; cl
|
||||
});
|
||||
|
||||
const flowOptions = useMemo(() => {
|
||||
return data?.items?.map((item: any) => ({ label: item.label, value: item.name })) || [];
|
||||
return (
|
||||
data?.items?.map((item: any) => ({
|
||||
label: item.label,
|
||||
value: item.name,
|
||||
})) || []
|
||||
);
|
||||
}, [data]);
|
||||
|
||||
const flowData = useMemo(() => {
|
||||
@@ -38,11 +47,11 @@ const AwelLayout: React.FC<{ initValue: any; updateData: (data: any) => void; cl
|
||||
return (
|
||||
<div className={cls(classNames, 'mb-6')}>
|
||||
<Form form={form} style={{ width: '100%' }}>
|
||||
<Form.Item label={t('select_workflow')} name="flow">
|
||||
<Select className="w-1/4" placeholder={t("please_select_workflow")} options={flowOptions} allowClear />
|
||||
<Form.Item label={t('select_workflow')} name='flow'>
|
||||
<Select className='w-1/4' placeholder={t('please_select_workflow')} options={flowOptions} allowClear />
|
||||
</Form.Item>
|
||||
{flowData && (
|
||||
<div className="w-full h-[600px] mx-auto border-[0.5px] border-dark-gray">
|
||||
<div className='w-full h-[600px] mx-auto border-[0.5px] border-dark-gray'>
|
||||
<PreviewFlow flowData={flowData} />
|
||||
</div>
|
||||
)}
|
||||
|
@@ -1,8 +1,8 @@
|
||||
import AppDefaultIcon from '@/new-components/common/AppDefaultIcon';
|
||||
import { apiInterceptors, getAppStrategyValues, getNativeAppScenes, getResource } from '@/client/api';
|
||||
import AppDefaultIcon from '@/new-components/common/AppDefaultIcon';
|
||||
import { ParamNeed } from '@/types/app';
|
||||
import { useRequest } from 'ahooks';
|
||||
import { Form, InputNumber, Select, Tooltip, Typography } from 'antd';
|
||||
import { Form, InputNumber, Select, Tooltip } from 'antd';
|
||||
import cls from 'classnames';
|
||||
import React, { useEffect, useMemo } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
@@ -39,12 +39,15 @@ const NativeApp: React.FC<{
|
||||
|
||||
// 获取应用类型&模型
|
||||
const { data, loading } = useRequest(async () => {
|
||||
const res = await Promise.all([apiInterceptors(getNativeAppScenes()), apiInterceptors(getAppStrategyValues('priority'))]);
|
||||
const res = await Promise.all([
|
||||
apiInterceptors(getNativeAppScenes()),
|
||||
apiInterceptors(getAppStrategyValues('priority')),
|
||||
]);
|
||||
const [types, models] = res;
|
||||
form.setFieldValue('chat_scene', team_context?.chat_scene);
|
||||
form.setFieldValue('model', param_need?.find((param) => param.type === 'model')?.value);
|
||||
form.setFieldValue('temperature', param_need?.find((param) => param.type === 'temperature')?.value);
|
||||
await run(param_need?.find((param) => param.type === 'resource')?.value || '');
|
||||
form.setFieldValue('model', param_need?.find(param => param.type === 'model')?.value);
|
||||
form.setFieldValue('temperature', param_need?.find(param => param.type === 'temperature')?.value);
|
||||
await run(param_need?.find(param => param.type === 'resource')?.value || '');
|
||||
return [types, models] ?? [];
|
||||
});
|
||||
|
||||
@@ -56,12 +59,14 @@ const NativeApp: React.FC<{
|
||||
} = useRequest(
|
||||
async (type: string) => {
|
||||
const [, res] = await apiInterceptors(getResource({ type }));
|
||||
if (chatScene === team_context?.chat_scene && param_need?.find((param) => param.type === 'resource')?.bind_value) {
|
||||
form.setFieldsValue({ bind_value: param_need?.find((param) => param.type === 'resource')?.bind_value });
|
||||
if (chatScene === team_context?.chat_scene && param_need?.find(param => param.type === 'resource')?.bind_value) {
|
||||
form.setFieldsValue({
|
||||
bind_value: param_need?.find(param => param.type === 'resource')?.bind_value,
|
||||
});
|
||||
}
|
||||
|
||||
return (
|
||||
res?.map((item) => {
|
||||
res?.map(item => {
|
||||
return {
|
||||
...item,
|
||||
value: item.key,
|
||||
@@ -80,10 +85,10 @@ const NativeApp: React.FC<{
|
||||
return {
|
||||
...type,
|
||||
label: (
|
||||
<div className="flex items-center gap-1">
|
||||
<div className='flex items-center gap-1'>
|
||||
<AppDefaultIcon width={4} height={4} scene={type.chat_scene} />
|
||||
<Tooltip title={`资源类型${type.param_need.find((param: any) => param.type === 'resource')?.value}`}>
|
||||
<span className="text-[#525964] dark:text-[rgba(255,255,255,0.65)] ml-1">{type.scene_name}</span>
|
||||
<span className='text-[#525964] dark:text-[rgba(255,255,255,0.65)] ml-1'>{type.scene_name}</span>
|
||||
</Tooltip>
|
||||
</div>
|
||||
),
|
||||
@@ -102,15 +107,16 @@ const NativeApp: React.FC<{
|
||||
[
|
||||
{
|
||||
chat_scene: rawVal.chat_scene,
|
||||
scene_name: appTypeOptions.find((type) => type.chat_scene === rawVal.chat_scene)?.scene_name,
|
||||
scene_name: appTypeOptions.find(type => type.chat_scene === rawVal.chat_scene)?.scene_name,
|
||||
},
|
||||
[
|
||||
{ type: 'model', value: rawVal.model },
|
||||
{ type: 'temperature', value: rawVal.temperature },
|
||||
{
|
||||
type: 'resource',
|
||||
value: appTypeOptions.find((type) => type.chat_scene === rawVal.chat_scene)?.param_need?.find((param: any) => param.type === 'resource')
|
||||
?.value,
|
||||
value: appTypeOptions
|
||||
.find(type => type.chat_scene === rawVal.chat_scene)
|
||||
?.param_need?.find((param: any) => param.type === 'resource')?.value,
|
||||
bind_value: rawVal.bind_value,
|
||||
},
|
||||
],
|
||||
@@ -127,25 +133,45 @@ const NativeApp: React.FC<{
|
||||
|
||||
return (
|
||||
<div className={cls(classNames)}>
|
||||
<Form<FormProps> form={form} autoComplete="off" style={{ width: '100%' }} labelCol={{ span: 3 }} wrapperCol={{ span: 21 }}>
|
||||
<Form.Item label={t('native_type')} tooltip name="chat_scene">
|
||||
<Form<FormProps>
|
||||
form={form}
|
||||
autoComplete='off'
|
||||
style={{ width: '100%' }}
|
||||
labelCol={{ span: 3 }}
|
||||
wrapperCol={{ span: 21 }}
|
||||
>
|
||||
<Form.Item label={t('native_type')} tooltip name='chat_scene'>
|
||||
<Select
|
||||
className="w-1/2"
|
||||
className='w-1/2'
|
||||
options={appTypeOptions}
|
||||
placeholder={t('app_type_select')}
|
||||
onChange={() => form.setFieldsValue({ bind_value: undefined })}
|
||||
/>
|
||||
</Form.Item>
|
||||
{chatScene !== 'chat_excel' && (
|
||||
<Form.Item label={t('Arguments')} name="bind_value">
|
||||
<Select placeholder={t('please_select_param')} allowClear className="w-1/2" options={options} loading={paramsLoading} />
|
||||
<Form.Item label={t('Arguments')} name='bind_value'>
|
||||
<Select
|
||||
placeholder={t('please_select_param')}
|
||||
allowClear
|
||||
className='w-1/2'
|
||||
options={options}
|
||||
loading={paramsLoading}
|
||||
/>
|
||||
</Form.Item>
|
||||
)}
|
||||
<Form.Item label={t("model")} tooltip name="model">
|
||||
<Select placeholder={t("please_select_model")} allowClear options={data?.[1]?.[1]?.map((item) => ({ label: item, value: item }))} className="w-1/2" />
|
||||
<Form.Item label={t('model')} tooltip name='model'>
|
||||
<Select
|
||||
placeholder={t('please_select_model')}
|
||||
allowClear
|
||||
options={data?.[1]?.[1]?.map(item => ({
|
||||
label: item,
|
||||
value: item,
|
||||
}))}
|
||||
className='w-1/2'
|
||||
/>
|
||||
</Form.Item>
|
||||
<Form.Item label={t("temperature")} tooltip name="temperature">
|
||||
<InputNumber className="w-1/5 h-8" max={1} min={0} step={0.1} placeholder={t('please_input_temperature')} />
|
||||
<Form.Item label={t('temperature')} tooltip name='temperature'>
|
||||
<InputNumber className='w-1/5 h-8' max={1} min={0} step={0.1} placeholder={t('please_input_temperature')} />
|
||||
</Form.Item>
|
||||
</Form>
|
||||
</div>
|
||||
|
@@ -26,7 +26,7 @@ const RecommendQuestions: React.FC<{
|
||||
|
||||
// 将数据实时返回给消费组件
|
||||
useEffect(() => {
|
||||
updateData(recommendQuestions?.filter((question) => !!question.question));
|
||||
updateData(recommendQuestions?.filter(question => !!question.question));
|
||||
}, [recommendQuestions, updateData]);
|
||||
|
||||
return (
|
||||
@@ -34,22 +34,28 @@ const RecommendQuestions: React.FC<{
|
||||
<Form<FormRecommendQuestion>
|
||||
style={{ width: '100%' }}
|
||||
form={form}
|
||||
initialValues={{ recommend_questions: initValue || [{ question: '', valid: false }] }}
|
||||
autoComplete="off"
|
||||
initialValues={{
|
||||
recommend_questions: initValue || [{ question: '', valid: false }],
|
||||
}}
|
||||
autoComplete='off'
|
||||
wrapperCol={{ span: 20 }}
|
||||
{...(labelCol && { labelCol: { span: 4 } })}
|
||||
>
|
||||
<Form.Item label={t('recommended_questions')}>
|
||||
<Form.List name="recommend_questions">
|
||||
<Form.List name='recommend_questions'>
|
||||
{(fields, { add, remove }) => (
|
||||
<>
|
||||
{fields.map(({ key, name }, index) => (
|
||||
<div key={key} className={cls('flex flex-1 items-center gap-8 mb-6', formStyle)}>
|
||||
<Form.Item label={`${t('question')} ${index + 1}`} name={[name, 'question']} className="grow">
|
||||
<Form.Item label={`${t('question')} ${index + 1}`} name={[name, 'question']} className='grow'>
|
||||
<Input placeholder={t('please_input_recommended_questions')} />
|
||||
</Form.Item>
|
||||
<Form.Item label={t('is_effective')} name={[name, 'valid']}>
|
||||
<Switch style={{ background: recommendQuestions?.[index]?.valid ? '#1677ff' : '#ccc' }} />
|
||||
<Switch
|
||||
style={{
|
||||
background: recommendQuestions?.[index]?.valid ? '#1677ff' : '#ccc',
|
||||
}}
|
||||
/>
|
||||
</Form.Item>
|
||||
<Form.Item>
|
||||
<MinusCircleOutlined
|
||||
@@ -62,7 +68,7 @@ const RecommendQuestions: React.FC<{
|
||||
))}
|
||||
<Form.Item className={cls(formStyle)}>
|
||||
<Button
|
||||
type="dashed"
|
||||
type='dashed'
|
||||
onClick={() => {
|
||||
add({ question: '', valid: false });
|
||||
}}
|
||||
|
@@ -1,14 +1,14 @@
|
||||
import MarkDownContext from '@/new-components/common/MarkdownContext';
|
||||
import { apiInterceptors, getAppStrategyValues } from '@/client/api';
|
||||
import MarkDownContext from '@/new-components/common/MarkdownContext';
|
||||
import { IResource } from '@/types/app';
|
||||
import { ExclamationCircleOutlined } from '@ant-design/icons';
|
||||
import { useRequest } from 'ahooks';
|
||||
import { Form, Modal, Select } from 'antd';
|
||||
import cls from 'classnames';
|
||||
import React, { useEffect, useMemo, useRef, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { v4 as uuid } from 'uuid';
|
||||
import ResourcesCard from './ResourcesCard';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
type PromptSelectType = {
|
||||
promptList: Record<string, any>[];
|
||||
@@ -22,20 +22,20 @@ const PromptSelect: React.FC<PromptSelectType> = ({ value, onChange, promptList
|
||||
const { t } = useTranslation();
|
||||
useEffect(() => {
|
||||
if (value) {
|
||||
const filterPrompt = promptList?.filter((item) => item.prompt_code === value)[0];
|
||||
const filterPrompt = promptList?.filter(item => item.prompt_code === value)[0];
|
||||
setCurPrompt(filterPrompt);
|
||||
}
|
||||
}, [promptList, value]);
|
||||
|
||||
return (
|
||||
<div className="w-2/5 flex items-center gap-2">
|
||||
<div className='w-2/5 flex items-center gap-2'>
|
||||
<Select
|
||||
className="w-1/2"
|
||||
className='w-1/2'
|
||||
placeholder={t('please_select_prompt')}
|
||||
options={promptList}
|
||||
fieldNames={{ label: 'prompt_name', value: 'prompt_code' }}
|
||||
onChange={(value) => {
|
||||
const filterPrompt = promptList?.filter((item) => item.prompt_code === value)[0];
|
||||
onChange={value => {
|
||||
const filterPrompt = promptList?.filter(item => item.prompt_code === value)[0];
|
||||
setCurPrompt(filterPrompt);
|
||||
onChange?.(value);
|
||||
}}
|
||||
@@ -44,12 +44,18 @@ const PromptSelect: React.FC<PromptSelectType> = ({ value, onChange, promptList
|
||||
showSearch
|
||||
/>
|
||||
{curPrompt && (
|
||||
<span className="text-sm text-blue-500 cursor-pointer" onClick={() => setShowPrompt(true)}>
|
||||
<ExclamationCircleOutlined className="mr-1" />
|
||||
<span className='text-sm text-blue-500 cursor-pointer' onClick={() => setShowPrompt(true)}>
|
||||
<ExclamationCircleOutlined className='mr-1' />
|
||||
{t('View_details')}
|
||||
</span>
|
||||
)}
|
||||
<Modal title={`Prompt ${t('details')}`} open={showPrompt} footer={false} width={'60%'} onCancel={() => setShowPrompt(false)}>
|
||||
<Modal
|
||||
title={`Prompt ${t('details')}`}
|
||||
open={showPrompt}
|
||||
footer={false}
|
||||
width={'60%'}
|
||||
onCancel={() => setShowPrompt(false)}
|
||||
>
|
||||
<MarkDownContext>{curPrompt?.content}</MarkDownContext>
|
||||
</Modal>
|
||||
</div>
|
||||
@@ -70,8 +76,9 @@ const DetailsCard: React.FC<{
|
||||
const promptTemplate = Form.useWatch('prompt_template', form);
|
||||
const strategy = Form.useWatch('llm_strategy', form);
|
||||
const strategyValue = Form.useWatch('llm_strategy_value', form);
|
||||
const [curPrompt, setCurPrompt] = useState<Record<string, any>>();
|
||||
const [showPrompt, setShowPrompt] = useState<boolean>(false);
|
||||
|
||||
// const [curPrompt, setCurPrompt] = useState<Record<string, any>>();
|
||||
// const [showPrompt, setShowPrompt] = useState<boolean>(false);
|
||||
|
||||
const initVal = useMemo(() => {
|
||||
return initValue?.find((item: any) => item.agent_name === name) || [];
|
||||
@@ -84,7 +91,7 @@ const DetailsCard: React.FC<{
|
||||
async () => {
|
||||
const [, res] = await apiInterceptors(getAppStrategyValues('priority'));
|
||||
return (
|
||||
res?.map((item) => {
|
||||
res?.map(item => {
|
||||
return {
|
||||
label: item,
|
||||
value: item,
|
||||
@@ -121,20 +128,35 @@ const DetailsCard: React.FC<{
|
||||
style={{ width: '100%' }}
|
||||
labelCol={{ span: 4 }}
|
||||
form={form}
|
||||
initialValues={{ llm_strategy: 'default', ...initVal, llm_strategy_value: initVal?.llm_strategy_value?.split(',') }}
|
||||
initialValues={{
|
||||
llm_strategy: 'default',
|
||||
...initVal,
|
||||
llm_strategy_value: initVal?.llm_strategy_value?.split(','),
|
||||
}}
|
||||
>
|
||||
<Form.Item label={t('Prompt')} name="prompt_template">
|
||||
<Form.Item label={t('Prompt')} name='prompt_template'>
|
||||
<PromptSelect promptList={promptList} />
|
||||
</Form.Item>
|
||||
<Form.Item label={t('LLM_strategy')} required name="llm_strategy">
|
||||
<Select className="w-1/5" placeholder={t('please_select_LLM_strategy')} options={modelStrategyOptions} allowClear />
|
||||
<Form.Item label={t('LLM_strategy')} required name='llm_strategy'>
|
||||
<Select
|
||||
className='w-1/5'
|
||||
placeholder={t('please_select_LLM_strategy')}
|
||||
options={modelStrategyOptions}
|
||||
allowClear
|
||||
/>
|
||||
</Form.Item>
|
||||
{strategy === 'priority' && (
|
||||
<Form.Item label={t('LLM_strategy_value')} required name="llm_strategy_value">
|
||||
<Select mode="multiple" className="w-2/5" placeholder={t('please_select_LLM_strategy_value')} options={data} allowClear />
|
||||
<Form.Item label={t('LLM_strategy_value')} required name='llm_strategy_value'>
|
||||
<Select
|
||||
mode='multiple'
|
||||
className='w-2/5'
|
||||
placeholder={t('please_select_LLM_strategy_value')}
|
||||
options={data}
|
||||
allowClear
|
||||
/>
|
||||
</Form.Item>
|
||||
)}
|
||||
<Form.Item label={t('available_resources')} name="resources">
|
||||
<Form.Item label={t('available_resources')} name='resources'>
|
||||
<ResourcesCard
|
||||
resourceTypeOptions={resourceTypeOptions}
|
||||
initValue={initVal?.resources?.map((res: any) => {
|
||||
@@ -143,7 +165,7 @@ const DetailsCard: React.FC<{
|
||||
uid: uuid(),
|
||||
};
|
||||
})}
|
||||
updateData={(data) => {
|
||||
updateData={data => {
|
||||
resourcesRef.current = data?.[1];
|
||||
updateData({
|
||||
agent_name: name,
|
||||
|
@@ -2,7 +2,7 @@ import { apiInterceptors, getResource } from '@/client/api';
|
||||
import { useRequest } from 'ahooks';
|
||||
import { Form, Select, Switch } from 'antd';
|
||||
import cls from 'classnames';
|
||||
import React, { useMemo, useEffect } from 'react';
|
||||
import React, { useEffect, useMemo } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
const ResourceContent: React.FC<{
|
||||
@@ -25,12 +25,12 @@ const ResourceContent: React.FC<{
|
||||
const { t } = useTranslation();
|
||||
// 资源类型选项
|
||||
const options = useMemo(() => {
|
||||
return resourceTypeOptions?.filter((item) => item.value !== 'all') || [];
|
||||
return resourceTypeOptions?.filter(item => item.value !== 'all') || [];
|
||||
}, [resourceTypeOptions]);
|
||||
|
||||
// 获取非动态情况下,知识库、数据库、插件、编排工作流参数列表
|
||||
const { run, data, loading } = useRequest(
|
||||
async (type) => {
|
||||
async type => {
|
||||
const [, res] = await apiInterceptors(getResource({ type }));
|
||||
form.setFieldsValue({
|
||||
value: initValue?.value || res?.[0]?.key,
|
||||
@@ -51,7 +51,7 @@ const ResourceContent: React.FC<{
|
||||
// 动态参数value选项
|
||||
const dynamicOptions = useMemo(() => {
|
||||
return (
|
||||
data?.map((item) => {
|
||||
data?.map(item => {
|
||||
return {
|
||||
...item,
|
||||
label: item.label,
|
||||
@@ -95,8 +95,14 @@ const ResourceContent: React.FC<{
|
||||
// );
|
||||
}
|
||||
return (
|
||||
<Form.Item label={t('resource_value')} name="value" required>
|
||||
<Select placeholder={t('please_select_param')} options={dynamicOptions} loading={loading} className="w-3/5" allowClear />
|
||||
<Form.Item label={t('resource_value')} name='value' required>
|
||||
<Select
|
||||
placeholder={t('please_select_param')}
|
||||
options={dynamicOptions}
|
||||
loading={loading}
|
||||
className='w-3/5'
|
||||
allowClear
|
||||
/>
|
||||
</Form.Item>
|
||||
);
|
||||
};
|
||||
@@ -118,16 +124,16 @@ const ResourceContent: React.FC<{
|
||||
...initValue,
|
||||
}}
|
||||
>
|
||||
<Form.Item label={t('resource_type')} name="type">
|
||||
<Form.Item label={t('resource_type')} name='type'>
|
||||
<Select
|
||||
className="w-2/5"
|
||||
className='w-2/5'
|
||||
options={options}
|
||||
onChange={(val: string) => {
|
||||
setCurIcon({ uid, icon: val });
|
||||
}}
|
||||
/>
|
||||
</Form.Item>
|
||||
<Form.Item label={t('resource_dynamic')} name="is_dynamic">
|
||||
<Form.Item label={t('resource_dynamic')} name='is_dynamic'>
|
||||
<Switch style={{ background: isDynamic ? '#1677ff' : '#ccc' }} />
|
||||
</Form.Item>
|
||||
{/* 如果选择了动态参数这里就不需要参数了 */}
|
||||
|
@@ -1,15 +1,14 @@
|
||||
import MyEmpty from '@/new-components/common/MyEmpty';
|
||||
import { IResource } from '@/types/app';
|
||||
import { DeleteOutlined, PlusOutlined } from '@ant-design/icons';
|
||||
import { Button, Popconfirm, Select, Space, Typography } from 'antd';
|
||||
import { Button, Popconfirm, Select, Typography } from 'antd';
|
||||
import classNames from 'classnames';
|
||||
import { concat } from 'lodash';
|
||||
import React, { useEffect, useMemo, useRef, useState } from 'react';
|
||||
import React, { useEffect, useRef, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { v4 as uuid } from 'uuid';
|
||||
|
||||
import { resourceTypeIcon } from '../../config';
|
||||
import ResourceContent from './ResourceContent';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
interface ResourceTabProps extends IResource {
|
||||
uid?: string;
|
||||
@@ -18,17 +17,20 @@ interface ResourceTabProps extends IResource {
|
||||
name?: string;
|
||||
}
|
||||
|
||||
const ResourcesCard: React.FC<{ name: string; updateData: (data: any) => void; initValue?: any; resourceTypeOptions: Record<string, any>[] }> = ({
|
||||
name,
|
||||
updateData,
|
||||
resourceTypeOptions,
|
||||
initValue,
|
||||
}) => {
|
||||
const ResourcesCard: React.FC<{
|
||||
name: string;
|
||||
updateData: (data: any) => void;
|
||||
initValue?: any;
|
||||
resourceTypeOptions: Record<string, any>[];
|
||||
}> = ({ name, updateData, resourceTypeOptions, initValue }) => {
|
||||
const { t } = useTranslation();
|
||||
const resources = useRef<ResourceTabProps[]>(initValue || []);
|
||||
const [curIcon, setCurIcon] = useState<{ uid: string; icon: string }>({ uid: '', icon: '' });
|
||||
const [curIcon, setCurIcon] = useState<{ uid: string; icon: string }>({
|
||||
uid: '',
|
||||
icon: '',
|
||||
});
|
||||
const [resourcesTabs, setResourcesTabs] = useState<ResourceTabProps[]>(
|
||||
initValue?.map((item: any, index: number) => {
|
||||
initValue?.map((item: any) => {
|
||||
return {
|
||||
...item,
|
||||
icon: item.type,
|
||||
@@ -43,9 +45,9 @@ const ResourcesCard: React.FC<{ name: string; updateData: (data: any) => void; i
|
||||
// 删除资源
|
||||
const remove = (e: any, item: any) => {
|
||||
e?.stopPropagation();
|
||||
const findActiveIndex = resources.current?.findIndex((i) => i.uid === activeKey);
|
||||
const filteredResources = resourcesTabs?.filter((i) => i.uid !== item.uid);
|
||||
resources.current = resources.current.filter((i) => i.uid !== item.uid) || [];
|
||||
const findActiveIndex = resources.current?.findIndex(i => i.uid === activeKey);
|
||||
const filteredResources = resourcesTabs?.filter(i => i.uid !== item.uid);
|
||||
resources.current = resources.current.filter(i => i.uid !== item.uid) || [];
|
||||
updateData([name, resources.current]);
|
||||
setResourcesTabs(filteredResources);
|
||||
if (findActiveIndex === resourcesTabs?.length - 1 && findActiveIndex !== 0) {
|
||||
@@ -64,7 +66,7 @@ const ResourcesCard: React.FC<{ name: string; updateData: (data: any) => void; i
|
||||
[
|
||||
{
|
||||
is_dynamic: false,
|
||||
type: resourceTypeOptions?.filter((item) => item.value !== 'all')?.[0].value,
|
||||
type: resourceTypeOptions?.filter(item => item.value !== 'all')?.[0].value,
|
||||
value: '',
|
||||
uid,
|
||||
name: t('resource') + ` ${resources.current.length + 1}`,
|
||||
@@ -76,11 +78,11 @@ const ResourcesCard: React.FC<{ name: string; updateData: (data: any) => void; i
|
||||
return [
|
||||
...prev,
|
||||
{
|
||||
icon: resourceTypeOptions?.filter((item) => item.value !== 'all')?.[0]?.value || '',
|
||||
icon: resourceTypeOptions?.filter(item => item.value !== 'all')?.[0]?.value || '',
|
||||
uid,
|
||||
initVal: {
|
||||
is_dynamic: false,
|
||||
type: resourceTypeOptions?.filter((item) => item.value !== 'all')?.[0].value,
|
||||
type: resourceTypeOptions?.filter(item => item.value !== 'all')?.[0].value,
|
||||
value: '',
|
||||
uid,
|
||||
name: t('resource') + ` ${prev.length + 1}`,
|
||||
@@ -92,7 +94,7 @@ const ResourcesCard: React.FC<{ name: string; updateData: (data: any) => void; i
|
||||
setActiveKey(uid);
|
||||
setCurIcon({
|
||||
uid,
|
||||
icon: resourceTypeOptions?.filter((item) => item.value !== 'all')?.[0].value,
|
||||
icon: resourceTypeOptions?.filter(item => item.value !== 'all')?.[0].value,
|
||||
});
|
||||
};
|
||||
|
||||
@@ -103,7 +105,7 @@ const ResourcesCard: React.FC<{ name: string; updateData: (data: any) => void; i
|
||||
// 资源切换图标同步切换
|
||||
useEffect(() => {
|
||||
setResourcesTabs(
|
||||
resourcesTabs.map((item) => {
|
||||
resourcesTabs.map(item => {
|
||||
if (curIcon?.uid === item.uid) {
|
||||
return {
|
||||
...item,
|
||||
@@ -117,26 +119,26 @@ const ResourcesCard: React.FC<{ name: string; updateData: (data: any) => void; i
|
||||
}, [curIcon]);
|
||||
|
||||
return (
|
||||
<div className="flex flex-1 h-64 px-3 py-4 border border-[#d6d8da] rounded-md">
|
||||
<div className="flex flex-col w-40 h-full">
|
||||
<div className='flex flex-1 h-64 px-3 py-4 border border-[#d6d8da] rounded-md'>
|
||||
<div className='flex flex-col w-40 h-full'>
|
||||
<Select
|
||||
options={resourceTypeOptions}
|
||||
className="w-full h-8"
|
||||
variant="borderless"
|
||||
defaultValue="all"
|
||||
className='w-full h-8'
|
||||
variant='borderless'
|
||||
defaultValue='all'
|
||||
onChange={(value: any) => {
|
||||
if (value === 'all') {
|
||||
setFilterResourcesTabs(resourcesTabs);
|
||||
setActiveKey(resourcesTabs?.[0]?.uid || '');
|
||||
} else {
|
||||
const newSourcesTabs = resourcesTabs?.filter((item) => item?.icon === value);
|
||||
const newSourcesTabs = resourcesTabs?.filter(item => item?.icon === value);
|
||||
setActiveKey(newSourcesTabs?.[0]?.uid || '');
|
||||
setFilterResourcesTabs(newSourcesTabs as any);
|
||||
}
|
||||
}}
|
||||
/>
|
||||
<div className="flex flex-1 flex-col gap-1 overflow-y-auto">
|
||||
{filterResourcesTabs?.map((item) => (
|
||||
<div className='flex flex-1 flex-col gap-1 overflow-y-auto'>
|
||||
{filterResourcesTabs?.map(item => (
|
||||
<div
|
||||
className={classNames(
|
||||
'flex h-8 items-center px-3 pl-[0.6rem] rounded-md hover:bg-[#f5faff] hover:dark:bg-[#606264] cursor-pointer relative',
|
||||
@@ -164,9 +166,9 @@ const ResourcesCard: React.FC<{ name: string; updateData: (data: any) => void; i
|
||||
autoSize: {
|
||||
maxRows: 1,
|
||||
},
|
||||
onChange: (v) => {
|
||||
onChange: v => {
|
||||
setResourcesTabs(
|
||||
resourcesTabs.map((i) => {
|
||||
resourcesTabs.map(i => {
|
||||
if (i.uid === item.uid) {
|
||||
return {
|
||||
...i,
|
||||
@@ -176,7 +178,7 @@ const ResourcesCard: React.FC<{ name: string; updateData: (data: any) => void; i
|
||||
return i;
|
||||
}),
|
||||
);
|
||||
resources.current = resources.current.map((i) => {
|
||||
resources.current = resources.current.map(i => {
|
||||
if (i.uid === item.uid) {
|
||||
return {
|
||||
...i,
|
||||
@@ -196,28 +198,28 @@ const ResourcesCard: React.FC<{ name: string; updateData: (data: any) => void; i
|
||||
</Typography.Text>
|
||||
<Popconfirm
|
||||
title={t('want_delete')}
|
||||
onConfirm={(e) => {
|
||||
onConfirm={e => {
|
||||
remove(e, item);
|
||||
}}
|
||||
onCancel={(e) => e?.stopPropagation()}
|
||||
onCancel={e => e?.stopPropagation()}
|
||||
>
|
||||
<DeleteOutlined
|
||||
className={`text-sm cursor-pointer absolute right-2 ${hoverKey === item.uid ? 'opacity-100' : 'opacity-0'}`}
|
||||
style={{ top: '50%', transform: 'translateY(-50%)' }}
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
onClick={e => e.stopPropagation()}
|
||||
/>
|
||||
</Popconfirm>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
<Button className="w-full h-8" type="dashed" block icon={<PlusOutlined />} onClick={addSource}>
|
||||
<Button className='w-full h-8' type='dashed' block icon={<PlusOutlined />} onClick={addSource}>
|
||||
{t('add_resource')}
|
||||
</Button>
|
||||
</div>
|
||||
<div className="flex flex-1 ml-6 ">
|
||||
<div className='flex flex-1 ml-6 '>
|
||||
{filterResourcesTabs && filterResourcesTabs?.length > 0 ? (
|
||||
<div className="flex flex-1">
|
||||
{filterResourcesTabs?.map((item) => (
|
||||
<div className='flex flex-1'>
|
||||
{filterResourcesTabs?.map(item => (
|
||||
<ResourceContent
|
||||
key={item.uid}
|
||||
classNames={item.uid === activeKey ? 'block' : 'hidden'}
|
||||
@@ -225,7 +227,7 @@ const ResourcesCard: React.FC<{ name: string; updateData: (data: any) => void; i
|
||||
initValue={item.initVal}
|
||||
setCurIcon={setCurIcon}
|
||||
updateData={(data: any) => {
|
||||
resources.current = resources.current?.map((i) => {
|
||||
resources.current = resources.current?.map(i => {
|
||||
if (i?.uid === data?.uid) {
|
||||
return {
|
||||
...i,
|
||||
@@ -241,7 +243,7 @@ const ResourcesCard: React.FC<{ name: string; updateData: (data: any) => void; i
|
||||
))}
|
||||
</div>
|
||||
) : (
|
||||
<MyEmpty className="w-40 h-40" />
|
||||
<MyEmpty className='w-40 h-40' />
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
@@ -6,9 +6,9 @@ import { Checkbox, Form, Space, Tooltip } from 'antd';
|
||||
import cls from 'classnames';
|
||||
import { concat } from 'lodash';
|
||||
import React, { useEffect, useMemo, useRef, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { agentIcon, resourceTypeIcon } from '../../config';
|
||||
import DetailsCard from './DetailsCard';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
interface AgentSelectProps {
|
||||
agents: IAgent[];
|
||||
@@ -21,13 +21,13 @@ interface AgentSelectProps {
|
||||
const AgentSelect: React.FC<AgentSelectProps> = ({ value, onChange, agents, selectedTab, setSelectedTab }) => {
|
||||
return (
|
||||
<Checkbox.Group
|
||||
className="grid grid-cols-4 gap-4"
|
||||
className='grid grid-cols-4 gap-4'
|
||||
onChange={(value: string[]) => {
|
||||
onChange?.(value);
|
||||
}}
|
||||
value={value}
|
||||
>
|
||||
{agents.map((item) => {
|
||||
{agents.map(item => {
|
||||
return (
|
||||
<div
|
||||
className={`flex grow h-8 items-center px-3 border ${
|
||||
@@ -39,13 +39,15 @@ const AgentSelect: React.FC<AgentSelectProps> = ({ value, onChange, agents, sele
|
||||
}}
|
||||
>
|
||||
<Checkbox value={item.name} />
|
||||
<div className="flex items-center flex-1 justify-between">
|
||||
<div className='flex items-center flex-1 justify-between'>
|
||||
<div>
|
||||
<span className="ml-2 mr-1">{agentIcon[item.name || '']}</span>
|
||||
<span className="text-sm text-[rgba(0,10,26,0.68)] dark:text-[rgba(255,255,255,0.85)]">{item.label}</span>
|
||||
<span className='ml-2 mr-1'>{agentIcon[item.name || '']}</span>
|
||||
<span className='text-sm text-[rgba(0,10,26,0.68)] dark:text-[rgba(255,255,255,0.85)]'>
|
||||
{item.label}
|
||||
</span>
|
||||
</div>
|
||||
<Tooltip title={item.desc}>
|
||||
<QuestionCircleOutlined className="text-sm" />
|
||||
<QuestionCircleOutlined className='text-sm' />
|
||||
</Tooltip>
|
||||
</div>
|
||||
</div>
|
||||
@@ -70,10 +72,14 @@ const AutoPlan: React.FC<{
|
||||
|
||||
// 获取agents, strategy, sourceType;
|
||||
const { data, loading } = useRequest(async () => {
|
||||
const res = await Promise.all([apiInterceptors(getAgents()), apiInterceptors(getAppStrategy()), apiInterceptors(getResourceType())]);
|
||||
const res = await Promise.all([
|
||||
apiInterceptors(getAgents()),
|
||||
apiInterceptors(getAppStrategy()),
|
||||
apiInterceptors(getResourceType()),
|
||||
]);
|
||||
const [, agents] = res?.[0] || [];
|
||||
details.current =
|
||||
agents?.map((item) => {
|
||||
agents?.map(item => {
|
||||
return {
|
||||
agent_name: item.name,
|
||||
llm_strategy: '',
|
||||
@@ -82,7 +88,9 @@ const AutoPlan: React.FC<{
|
||||
resources: [],
|
||||
};
|
||||
}) || [];
|
||||
form.setFieldsValue({ agent_name: initValue?.map((item: any) => item.agent_name) });
|
||||
form.setFieldsValue({
|
||||
agent_name: initValue?.map((item: any) => item.agent_name),
|
||||
});
|
||||
setSelectedTab(initValue?.map((item: any) => item.agent_name)?.[0] || agents?.[0]?.name || '');
|
||||
return res ?? [];
|
||||
});
|
||||
@@ -102,7 +110,7 @@ const AutoPlan: React.FC<{
|
||||
const modelStrategyOptions: any[] = useMemo(() => {
|
||||
const [, strategy] = data?.[1] || [];
|
||||
if (strategy?.length) {
|
||||
return strategy.map((item) => {
|
||||
return strategy.map(item => {
|
||||
return {
|
||||
label: language ? item.name : item.name_cn,
|
||||
value: item.value,
|
||||
@@ -116,7 +124,7 @@ const AutoPlan: React.FC<{
|
||||
const resourceTypeOptions: Record<string, any>[] = useMemo(() => {
|
||||
const [, sourceType] = data?.[2] || [];
|
||||
if (sourceType?.length) {
|
||||
const formatterSourceType = sourceType.map((item) => {
|
||||
const formatterSourceType = sourceType.map(item => {
|
||||
return {
|
||||
label: (
|
||||
<Space>
|
||||
@@ -132,9 +140,9 @@ const AutoPlan: React.FC<{
|
||||
[
|
||||
{
|
||||
label: (
|
||||
<div className="flex items-center text-sm">
|
||||
<div className='flex items-center text-sm'>
|
||||
{resourceTypeIcon['all']}
|
||||
<span className="ml-2 text-[rgba(0,10,26,0.68)] dark:text-[#ffffffD9]">{t('All')}</span>
|
||||
<span className='ml-2 text-[rgba(0,10,26,0.68)] dark:text-[#ffffffD9]'>{t('All')}</span>
|
||||
</div>
|
||||
),
|
||||
value: 'all',
|
||||
@@ -148,22 +156,27 @@ const AutoPlan: React.FC<{
|
||||
|
||||
// 实时返回数据给消费组件
|
||||
useEffect(() => {
|
||||
updateData([loading, details.current.filter((detail) => agentName?.includes(detail.agent_name))]);
|
||||
updateData([loading, details.current.filter(detail => agentName?.includes(detail.agent_name))]);
|
||||
}, [loading, agentName, updateData]);
|
||||
|
||||
return (
|
||||
<div className={cls(classNames)}>
|
||||
<Form form={form} style={{ width: '100%' }} labelCol={{ span: 4 }} wrapperCol={{ span: 20 }}>
|
||||
<Form.Item label={`${t('choose')} agent`} name="agent_name" required rules={[{ required: true, message: t('please_choose') + ' agent' }]}>
|
||||
<Form.Item
|
||||
label={`${t('choose')} agent`}
|
||||
name='agent_name'
|
||||
required
|
||||
rules={[{ required: true, message: t('please_choose') + ' agent' }]}
|
||||
>
|
||||
<AgentSelect agents={data?.[0]?.[1] || []} selectedTab={selectedTab} setSelectedTab={setSelectedTab} />
|
||||
</Form.Item>
|
||||
</Form>
|
||||
{data?.[0]?.[1]?.map((item) => (
|
||||
{data?.[0]?.[1]?.map(item => (
|
||||
<DetailsCard
|
||||
key={item.name}
|
||||
classNames={item.name === selectedTab ? 'block' : 'hidden'}
|
||||
updateData={(data: any) => {
|
||||
details.current = details.current.map((detail) => {
|
||||
details.current = details.current.map(detail => {
|
||||
if (detail.agent_name === data?.agent_name) {
|
||||
return {
|
||||
...detail,
|
||||
@@ -174,7 +187,7 @@ const AutoPlan: React.FC<{
|
||||
...detail,
|
||||
};
|
||||
});
|
||||
updateData([loading, details.current.filter((detail) => agentName?.includes(detail.agent_name))]);
|
||||
updateData([loading, details.current.filter(detail => agentName?.includes(detail.agent_name))]);
|
||||
}}
|
||||
initValue={initValue}
|
||||
name={item.name}
|
||||
|
Reference in New Issue
Block a user