/* Copyright (C) 2025 QuantumNous This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. For commercial licensing, please contact support@quantumnous.com */ import React, { useEffect, useState, useCallback } from 'react'; import { Button, Card, Form, Table, Modal, Typography, Toast, } from '@douyinfe/semi-ui'; import { API, showError, showSuccess } from '../../helpers'; import { useTranslation } from 'react-i18next'; import { Plus, Pencil, Trash2, RefreshCw } from 'lucide-react'; const { Text } = Typography; const EMPTY_MODEL = { name: '', provider: '', intelligence: 0, speed: 0, price: 0, latency: 0, context_window: '', type: 'non-reasoning', openness: 'proprietary', category: 'language', }; export default function BenchmarkDataManager() { const { t } = useTranslation(); const [models, setModels] = useState([]); const [loading, setLoading] = useState(false); const [saving, setSaving] = useState(false); const [editModalVisible, setEditModalVisible] = useState(false); const [editingIndex, setEditingIndex] = useState(null); const [editForm, setEditForm] = useState({ ...EMPTY_MODEL }); const fetchData = useCallback(async () => { setLoading(true); try { const res = await API.get('/api/option/'); if (res.data.success && res.data.data) { const option = res.data.data.find( (o) => o.key === 'benchmark_data.models', ); if (option && option.value) { setModels(JSON.parse(option.value)); } else { // try to fetch via the specific key const fallbackRes = await API.get( '/api/option/?key=benchmark_data.models', ); if (fallbackRes.data?.data) { setModels(JSON.parse(fallbackRes.data.data.value || '[]')); } } } } catch (error) { showError(t('获取评测数据失败')); } finally { setLoading(false); } }, [t]); useEffect(() => { fetchData(); }, [fetchData]); const saveData = async (newModels) => { setSaving(true); try { const res = await API.put('/api/option/', { key: 'benchmark_data.models', value: JSON.stringify(newModels), }); if (res.data.success) { showSuccess(t('保存成功')); setModels(newModels); } else { showError(res.data.message || t('保存失败')); } } catch (error) { showError(t('保存失败,请重试')); } finally { setSaving(false); } }; const openAddModal = () => { setEditingIndex(null); setEditForm({ ...EMPTY_MODEL }); setEditModalVisible(true); }; const openEditModal = (index) => { setEditingIndex(index); setEditForm({ ...models[index] }); setEditModalVisible(true); }; const handleSaveModel = async () => { if (!editForm.name || !editForm.provider) { showError(t('模型名称和供应商不能为空')); return; } const newModels = [...models]; if (editingIndex !== null) { newModels[editingIndex] = { ...editForm }; } else { newModels.push({ ...editForm }); } await saveData(newModels); setEditModalVisible(false); }; const handleDeleteModel = async (index) => { const newModels = models.filter((_, i) => i !== index); await saveData(newModels); }; const handleFieldChange = (field, value) => { setEditForm((prev) => ({ ...prev, [field]: ['intelligence', 'speed', 'price', 'latency'].includes(field) ? parseFloat(value) || 0 : value, })); }; const columns = [ { title: t('模型名称'), dataIndex: 'name', width: 180, render: (text, record) => (