From 369ecf365ab531f1b093a3c56298f914459ab047 Mon Sep 17 00:00:00 2001 From: HynoR <20227709+HynoR@users.noreply.github.com> Date: Fri, 13 Dec 2024 14:10:38 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0=E6=A8=A1=E5=9E=8B?= =?UTF-8?q?=E8=AE=BE=E7=BD=AE=E5=8F=AF=E8=A7=86=E5=8C=96=E7=BC=96=E8=BE=91?= =?UTF-8?q?=E5=99=A8=E7=BB=84=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- web/src/components/OperationSetting.js | 5 + .../Operation/ModelSettingsVisualEditor.js | 251 ++++++++++++++++++ 2 files changed, 256 insertions(+) create mode 100644 web/src/pages/Setting/Operation/ModelSettingsVisualEditor.js diff --git a/web/src/components/OperationSetting.js b/web/src/components/OperationSetting.js index 1c50c971..d7d69f71 100644 --- a/web/src/components/OperationSetting.js +++ b/web/src/components/OperationSetting.js @@ -8,6 +8,7 @@ import SettingsDataDashboard from '../pages/Setting/Operation/SettingsDataDashbo import SettingsMonitoring from '../pages/Setting/Operation/SettingsMonitoring.js'; import SettingsCreditLimit from '../pages/Setting/Operation/SettingsCreditLimit.js'; import SettingsMagnification from '../pages/Setting/Operation/SettingsMagnification.js'; +import ModelSettingsVisualEditor from '../pages/Setting/Operation/ModelSettingsVisualEditor.js'; import { API, showError, showSuccess } from '../helpers'; import SettingsChats from '../pages/Setting/Operation/SettingsChats.js'; @@ -141,6 +142,10 @@ const OperationSetting = () => { + {/*可视化倍率设置*/} + + + ); diff --git a/web/src/pages/Setting/Operation/ModelSettingsVisualEditor.js b/web/src/pages/Setting/Operation/ModelSettingsVisualEditor.js new file mode 100644 index 00000000..b3ebb9e9 --- /dev/null +++ b/web/src/pages/Setting/Operation/ModelSettingsVisualEditor.js @@ -0,0 +1,251 @@ +// ModelSettingsVisualEditor.js +import React, { useEffect, useState } from 'react'; +import { Table, Button, Input, Modal, Form, Space } from '@douyinfe/semi-ui'; +import { IconDelete, IconPlus, IconSearch } from '@douyinfe/semi-icons'; +import { showError, showSuccess } from '../../../helpers'; +import { API } from '../../../helpers'; +export default function ModelSettingsVisualEditor(props) { + const [models, setModels] = useState([]); + const [visible, setVisible] = useState(false); + const [currentModel, setCurrentModel] = useState(null); + const [searchText, setSearchText] = useState(''); + const [currentPage, setCurrentPage] = useState(1); + const pageSize = 10; + + useEffect(() => { + try { + const modelPrice = JSON.parse(props.options.ModelPrice || '{}'); + const modelRatio = JSON.parse(props.options.ModelRatio || '{}'); + const completionRatio = JSON.parse(props.options.CompletionRatio || '{}'); + + // 合并所有模型名称 + const modelNames = new Set([ + ...Object.keys(modelPrice), + ...Object.keys(modelRatio), + ...Object.keys(completionRatio) + ]); + + const modelData = Array.from(modelNames).map(name => ({ + name, + price: modelPrice[name] === undefined ? '' : modelPrice[name], + ratio: modelRatio[name] === undefined ? '' : modelRatio[name], + completionRatio: completionRatio[name] === undefined ? '' : completionRatio[name] + })); + + setModels(modelData); + } catch (error) { + console.error('JSON解析错误:', error); + } + }, [props.options]); + + // 首先声明分页相关的工具函数 + const getPagedData = (data, currentPage, pageSize) => { + const start = (currentPage - 1) * pageSize; + const end = start + pageSize; + return data.slice(start, end); + }; + + // 在 return 语句之前,先处理过滤和分页逻辑 + const filteredModels = models.filter(model => + searchText ? model.name.toLowerCase().includes(searchText.toLowerCase()) : true + ); + + // 然后基于过滤后的数据计算分页数据 + const pagedData = getPagedData(filteredModels, currentPage, pageSize); + + // 转换回JSON格式 + const generateJSONOutput = async () => { + const output = { + ModelPrice: {}, + ModelRatio: {}, + CompletionRatio: {} + }; + let currentConvertModelName = ''; + try { + models.forEach(model => { + currentConvertModelName = model.name; + if (model.price !== '') output.ModelPrice[model.name] = parseFloat(model.price); + if (model.ratio !== '') output.ModelRatio[model.name] = parseFloat(model.ratio); + if (model.completionRatio != '') output.CompletionRatio[model.name] = parseFloat(model.completionRatio); + }); + } catch (error) { + console.error('JSON转换错误:', error); + showError('JSON转换错误, 请检查输入+模型名称: ' + currentConvertModelName); + return; + } + + const finalOutput = { + ModelPrice: JSON.stringify(output.ModelPrice, null, 2), + ModelRatio: JSON.stringify(output.ModelRatio, null, 2), + CompletionRatio: JSON.stringify(output.CompletionRatio, null, 2) + } + + forEach(finalOutput, (value, key) => { + API.put('/api/option/', { + key: key, + value + }).then(res => { + if (res.data.success) { + showSuccess('保存成功'); + } else { + showError(res.data.message); + } + }) + }) + + + showSuccess('转换成功'); + props.refresh(); + }; + + const columns = [ + { + title: '模型名称', + dataIndex: 'name', + key: 'name', + }, + { + title: '固定价格', + dataIndex: 'price', + key: 'price', + render: (text, record) => ( + updateModel(record.name, 'price', value)} + /> + ) + }, + { + title: '模型倍率', + dataIndex: 'ratio', + key: 'ratio', + render: (text, record) => ( + updateModel(record.name, 'ratio', value)} + /> + ) + }, + { + title: '补全倍率', + dataIndex: 'completionRatio', + key: 'completionRatio', + render: (text, record) => ( + updateModel(record.name, 'completionRatio', value)} + /> + ) + }, + { + title: '操作', + key: 'action', + render: (_, record) => ( + + + } + placeholder="搜索模型名称" + value={searchText} + onChange={value => { + setSearchText(value) + // 搜索时重置页码 + setCurrentPage(1); + }} + style={{ width: 200 }} + /> + + setCurrentPage(page), + showTotal: true, + showSizeChanger: false + }} + /> + + + setVisible(false)} + onOk={() => { + currentModel && addModel(currentModel); + }} + > +
+ setCurrentModel(prev => ({ ...prev, name: value }))} + /> + setCurrentModel(prev => ({ ...prev, price: value }))} + /> + setCurrentModel(prev => ({ ...prev, ratio: value }))} + /> + setCurrentModel(prev => ({ ...prev, completionRatio: value }))} + /> + +
+ + ); +}