// ============================================================ // 模型管理 // ============================================================ import { useState } from 'react' import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query' import { Button, message, Tag, Modal, Form, Input, InputNumber, Switch, Select, Space, Popconfirm } from 'antd' import { PlusOutlined } from '@ant-design/icons' import type { ProColumns } from '@ant-design/pro-components' import { ProTable } from '@ant-design/pro-components' import { modelService } from '@/services/models' import { providerService } from '@/services/providers' import type { Model } from '@/types' export default function Models() { const queryClient = useQueryClient() const [form] = Form.useForm() const [modalOpen, setModalOpen] = useState(false) const [editingId, setEditingId] = useState(null) const { data, isLoading } = useQuery({ queryKey: ['models'], queryFn: ({ signal }) => modelService.list(signal), }) const { data: providersData } = useQuery({ queryKey: ['providers-for-select'], queryFn: ({ signal }) => providerService.list(signal), }) const createMutation = useMutation({ mutationFn: (data: Partial>) => modelService.create(data), onSuccess: () => { message.success('创建成功') queryClient.invalidateQueries({ queryKey: ['models'] }) setModalOpen(false) form.resetFields() }, onError: (err: Error) => message.error(err.message || '创建失败'), }) const updateMutation = useMutation({ mutationFn: ({ id, data }: { id: string; data: Partial> }) => modelService.update(id, data), onSuccess: () => { message.success('更新成功') queryClient.invalidateQueries({ queryKey: ['models'] }) setModalOpen(false) }, onError: (err: Error) => message.error(err.message || '更新失败'), }) const deleteMutation = useMutation({ mutationFn: (id: string) => modelService.delete(id), onSuccess: () => { message.success('删除成功') queryClient.invalidateQueries({ queryKey: ['models'] }) }, onError: (err: Error) => message.error(err.message || '删除失败'), }) const columns: ProColumns[] = [ { title: '模型 ID', dataIndex: 'model_id', width: 180, render: (_, r) => {r.model_id} }, { title: '别名', dataIndex: 'alias', width: 140 }, { title: '服务商', dataIndex: 'provider_id', width: 140, hideInSearch: true, render: (_, r) => { const provider = providersData?.items?.find((p) => p.id === r.provider_id) return provider?.display_name || r.provider_id.substring(0, 8) }, }, { title: '上下文窗口', dataIndex: 'context_window', width: 110, hideInSearch: true, render: (_, r) => r.context_window?.toLocaleString() }, { title: '最大输出', dataIndex: 'max_output_tokens', width: 100, hideInSearch: true, render: (_, r) => r.max_output_tokens?.toLocaleString() }, { title: '流式', dataIndex: 'supports_streaming', width: 70, hideInSearch: true, render: (_, r) => r.supports_streaming ? : , }, { title: '视觉', dataIndex: 'supports_vision', width: 70, hideInSearch: true, render: (_, r) => r.supports_vision ? : , }, { title: '状态', dataIndex: 'enabled', width: 70, hideInSearch: true, render: (_, r) => r.enabled ? 启用 : 禁用, }, { title: '操作', width: 160, hideInSearch: true, render: (_, record) => ( deleteMutation.mutate(record.id)}> ), }, ] const handleSave = async () => { const values = await form.validateFields() if (editingId) { updateMutation.mutate({ id: editingId, data: values }) } else { createMutation.mutate(values) } } return (
columns={columns} dataSource={data?.items ?? []} loading={isLoading} rowKey="id" search={{}} toolBarRender={() => [ , ]} pagination={{ total: data?.total ?? 0, pageSize: data?.page_size ?? 20, current: data?.page ?? 1, showSizeChanger: false, }} /> { setModalOpen(false); setEditingId(null); form.resetFields() }} confirmLoading={createMutation.isPending || updateMutation.isPending} width={600} >
) }