refactor(agent-editor): use dropdown checkbox model picker
parent
1d79e929f9
commit
6ad8a1517f
|
|
@ -1,5 +1,5 @@
|
|||
import { useEffect, useRef, useState } from 'react';
|
||||
import { Button, Form, Input, InputNumber, Modal, Upload, App as AntApp, List, Popconfirm, Tag, Switch, Select, Collapse, Checkbox } from 'antd';
|
||||
import { Button, Form, Input, InputNumber, Modal, Upload, App as AntApp, List, Popconfirm, Tag, Switch, Select, Collapse, Checkbox, Dropdown } from 'antd';
|
||||
import type { UploadFile } from 'antd/es/upload/interface';
|
||||
import { useNavigate, useParams } from 'react-router-dom';
|
||||
import { Agent, AgentAPI, ImageAPI, KnowledgeStatus, SkillType, Team, TeamAPI, AiModel, ModelAPI } from '../api';
|
||||
|
|
@ -7,7 +7,7 @@ import { DEFAULT_RH_40X40_GRAY } from '../constants';
|
|||
import SkillEditor from '../components/SkillEditor';
|
||||
import McpPanel from '../components/McpPanel';
|
||||
import ChatPreview from '../components/ChatPreview';
|
||||
import { ArrowLeftOutlined, SaveOutlined, FileTextOutlined, RocketOutlined, ToolOutlined, DatabaseOutlined, SettingOutlined, UploadOutlined } from '@ant-design/icons';
|
||||
import { ArrowLeftOutlined, SaveOutlined, FileTextOutlined, RocketOutlined, ToolOutlined, DatabaseOutlined, SettingOutlined, UploadOutlined, DownOutlined } from '@ant-design/icons';
|
||||
|
||||
const STATUS_TAG: Record<KnowledgeStatus, { color: string; text: string }> = {
|
||||
pending: { color: 'default', text: '待处理' },
|
||||
|
|
@ -35,6 +35,67 @@ const parseModelSelections = (value?: string | string[]) =>
|
|||
.map((item) => item.trim())
|
||||
.filter(Boolean);
|
||||
|
||||
function ModelCheckboxDropdown({
|
||||
value = [],
|
||||
onChange,
|
||||
models,
|
||||
}: {
|
||||
value?: string[];
|
||||
onChange?: (value: string[]) => void;
|
||||
models: AiModel[];
|
||||
}) {
|
||||
const [open, setOpen] = useState(false);
|
||||
const summary = value.length ? `${value.length} 个已选` : '选择模型';
|
||||
|
||||
return (
|
||||
<Dropdown
|
||||
trigger={['click']}
|
||||
open={open}
|
||||
onOpenChange={setOpen}
|
||||
popupRender={() => (
|
||||
<div className="agent-model-dropdown-panel" onClick={(e) => e.stopPropagation()}>
|
||||
<Checkbox.Group
|
||||
value={value}
|
||||
onChange={(checked) => onChange?.(checked.map((item) => String(item)))}
|
||||
className="agent-model-checkbox-group"
|
||||
>
|
||||
{models.map((m) => {
|
||||
const inputPrice = 2 * m.model_ratio;
|
||||
const outputPrice = inputPrice * m.completion_ratio;
|
||||
return (
|
||||
<Checkbox key={m.model_name} value={m.model_name} className="agent-model-checkbox-item">
|
||||
<div className="agent-model-checkbox-content">
|
||||
<div className="agent-model-checkbox-meta">
|
||||
<img
|
||||
src={m.icon || DEFAULT_RH_40X40_GRAY}
|
||||
alt={m.model_name}
|
||||
className="agent-model-checkbox-icon"
|
||||
/>
|
||||
<span className="agent-model-checkbox-name">{m.model_name}</span>
|
||||
</div>
|
||||
<div className="agent-model-checkbox-price">
|
||||
<span>输入: ${inputPrice.toFixed(2)}/M</span>
|
||||
<span>输出: ${outputPrice.toFixed(2)}/M</span>
|
||||
</div>
|
||||
</div>
|
||||
</Checkbox>
|
||||
);
|
||||
})}
|
||||
</Checkbox.Group>
|
||||
</div>
|
||||
)}
|
||||
>
|
||||
<button type="button" className="agent-model-dropdown-trigger">
|
||||
<span className="agent-model-dropdown-summary">{summary}</span>
|
||||
<span className="agent-model-dropdown-values">
|
||||
{value.length ? value.join(', ') : '未选择'}
|
||||
</span>
|
||||
<DownOutlined className="agent-model-dropdown-arrow" />
|
||||
</button>
|
||||
</Dropdown>
|
||||
);
|
||||
}
|
||||
|
||||
export default function AgentEditor() {
|
||||
const { id } = useParams();
|
||||
const isNew = !id;
|
||||
|
|
@ -493,30 +554,7 @@ export default function AgentEditor() {
|
|||
Array.isArray(value) ? value.map((item) => String(item).trim()).filter(Boolean).join(', ') : ''
|
||||
}
|
||||
>
|
||||
<Checkbox.Group className="agent-model-checkbox-group">
|
||||
{models.map((m) => {
|
||||
const inputPrice = 2 * m.model_ratio;
|
||||
const outputPrice = inputPrice * m.completion_ratio;
|
||||
return (
|
||||
<Checkbox key={m.model_name} value={m.model_name} className="agent-model-checkbox-item">
|
||||
<div className="agent-model-checkbox-content">
|
||||
<div className="agent-model-checkbox-meta">
|
||||
<img
|
||||
src={m.icon || DEFAULT_RH_40X40_GRAY}
|
||||
alt={m.model_name}
|
||||
className="agent-model-checkbox-icon"
|
||||
/>
|
||||
<span className="agent-model-checkbox-name">{m.model_name}</span>
|
||||
</div>
|
||||
<div className="agent-model-checkbox-price">
|
||||
<span>输入: ${inputPrice.toFixed(2)}/M</span>
|
||||
<span>输出: ${outputPrice.toFixed(2)}/M</span>
|
||||
</div>
|
||||
</div>
|
||||
</Checkbox>
|
||||
);
|
||||
})}
|
||||
</Checkbox.Group>
|
||||
<ModelCheckboxDropdown models={models} />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
name="temperature"
|
||||
|
|
|
|||
|
|
@ -561,6 +561,53 @@ body {
|
|||
box-shadow: var(--shadow-focus);
|
||||
}
|
||||
|
||||
.agent-model-dropdown-trigger {
|
||||
width: 100%;
|
||||
min-height: 42px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
padding: 10px 12px;
|
||||
border: 1px solid var(--color-border);
|
||||
border-radius: 12px;
|
||||
background: var(--color-surface);
|
||||
color: var(--color-text);
|
||||
cursor: pointer;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.agent-model-dropdown-summary {
|
||||
flex-shrink: 0;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.agent-model-dropdown-values {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
color: var(--color-text-secondary);
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.agent-model-dropdown-arrow {
|
||||
flex-shrink: 0;
|
||||
font-size: 12px;
|
||||
color: var(--color-text-tertiary);
|
||||
}
|
||||
|
||||
.agent-model-dropdown-panel {
|
||||
width: min(720px, calc(100vw - 64px));
|
||||
max-height: 360px;
|
||||
overflow-y: auto;
|
||||
padding: 12px;
|
||||
background: var(--color-surface);
|
||||
border: 1px solid var(--color-border);
|
||||
border-radius: 12px;
|
||||
box-shadow: var(--shadow-lg);
|
||||
}
|
||||
|
||||
.agent-model-checkbox-group {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
|
|
|||
Loading…
Reference in New Issue