import React, { useEffect, useState } from 'react'; import { Button, Card, Form, Input, InputNumber, message, Modal, Popconfirm, Select, Space, Switch, Table, Tag, Typography, } from 'antd'; import { RobotOutlined, PlusOutlined, EditOutlined, DeleteOutlined, } from '@ant-design/icons'; import { getModelConfigs, saveModelConfig, deleteModelConfig } from '../api'; import type { ModelConfig } from '../types'; const AdminModels: React.FC = () => { const [models, setModels] = useState([]); const [loading, setLoading] = useState(true); const [modal, setModal] = useState<{ open: boolean; model: ModelConfig | null }>({ open: false, model: null }); const [form] = Form.useForm(); const load = async () => { setLoading(true); try { const data = await getModelConfigs(); setModels(data); } catch { /* auth error handled by client */ } setLoading(false); }; useEffect(() => { load(); }, []); const handleSave = async () => { try { const values = await form.validateFields(); const payload = { name: values.name, provider: values.provider, model_name: values.modelName, api_base: values.apiBase, api_key: values.apiKey, weight: values.weight, max_tokens: values.maxTokens, temperature: values.temperature, is_active: values.isActive ?? true, priority: values.priority ?? 0, }; if (modal.model?.id) { await saveModelConfig({ id: modal.model.id, ...payload }); } else { await saveModelConfig(payload); } message.success(modal.model?.id ? '模型配置已更新' : '模型配置已添加'); setModal({ open: false, model: null }); form.resetFields(); load(); } catch (e: any) { if (e?.errorFields) return; message.error(e?.message || '保存失败'); } }; const handleDelete = async (id: string) => { try { await deleteModelConfig(id); message.success('模型配置已删除'); load(); } catch (e: any) { message.error(e?.message || '删除失败'); } }; const openEdit = (model?: ModelConfig) => { setModal({ open: true, model: model || null }); if (model) { form.setFieldsValue(model); } else { form.resetFields(); form.setFieldsValue({ provider: 'sdk', weight: 1, maxTokens: 4096, temperature: 0.7, isActive: true, priority: 0, }); } }; const columns = [ { title: '模型名称', dataIndex: 'name', width: 150, render: (v: string, r: ModelConfig) => (
{v}
{r.modelName}
), }, { title: '提供商', dataIndex: 'provider', width: 140, render: (v: string) => { const labelMap: Record = { sdk: 'SDK模式', openai_compatible: 'OpenAI兼容', mock: 'Mock模式', }; return {labelMap[v] || v}; }, }, { title: 'API地址', dataIndex: 'apiBase', width: 200, render: (v: string) => ( {v || '-'} ), }, { title: '权重', dataIndex: 'weight', width: 80, sorter: (a: ModelConfig, b: ModelConfig) => a.weight - b.weight, }, { title: 'Max Tokens', dataIndex: 'maxTokens', width: 100, }, { title: 'Temperature', dataIndex: 'temperature', width: 100, render: (v: number) => v.toFixed(1), }, { title: '状态', dataIndex: 'isActive', width: 80, render: (v: boolean) => ( {v ? '启用' : '停用'} ), }, { title: '操作', key: 'action', width: 150, fixed: 'right' as const, render: (_: any, r: ModelConfig) => ( handleDelete(r.id)}> ), }, ]; return (
共 {models.length} 个模型配置,按权重进行加权随机调度
{/* Edit Modal */} {modal.model?.id ? '编辑模型' : '添加模型'}} open={modal.open} onOk={handleSave} onCancel={() => { setModal({ open: false, model: null }); form.resetFields(); }} okText="确认" cancelText="取消" width={560} >
); }; export default AdminModels;