diff --git a/web/src/components/OperationSetting.js b/web/src/components/OperationSetting.js index 31345a5..2529ca2 100644 --- a/web/src/components/OperationSetting.js +++ b/web/src/components/OperationSetting.js @@ -1,6 +1,6 @@ import React, { useEffect, useState } from 'react'; import { Divider, Form, Grid, Header } from 'semantic-ui-react'; -import { Card } from '@douyinfe/semi-ui'; +import { Card, Spin } from '@douyinfe/semi-ui'; import SettingsGeneral from '../pages/Setting/Operation/SettingsGeneral.js'; import SettingsDrawing from '../pages/Setting/Operation/SettingsDrawing.js'; import SettingsSensitiveWords from '../pages/Setting/Operation/SettingsSensitiveWords.js'; @@ -8,6 +8,7 @@ import SettingsLog from '../pages/Setting/Operation/SettingsLog.js'; import SettingsDataDashboard from '../pages/Setting/Operation/SettingsDataDashboard.js'; 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 { API, @@ -17,10 +18,7 @@ import { verifyJSON, } from '../helpers'; -import { useTheme } from '../context/Theme'; - const OperationSetting = () => { - let now = new Date(); let [inputs, setInputs] = useState({ QuotaForNewUser: 0, QuotaForInviter: 0, @@ -58,7 +56,7 @@ const OperationSetting = () => { DefaultCollapseSidebar: false, // 默认折叠侧边栏 RetryTimes: 0, }); - const [originInputs, setOriginInputs] = useState({}); + let [loading, setLoading] = useState(false); const getOptions = async () => { @@ -86,271 +84,62 @@ const OperationSetting = () => { }); setInputs(newInputs); - setOriginInputs(newInputs); } else { showError(message); } }; - - const theme = useTheme(); - const isDark = theme === 'dark'; + async function onRefresh() { + try { + setLoading(true); + await getOptions(); + showSuccess('刷新成功'); + } catch (error) { + showError('刷新失败'); + } finally { + setLoading(false); + } + } useEffect(() => { - getOptions().then(); + getOptions(); }, []); - const updateOption = async (key, value) => { - setLoading(true); - if (key.endsWith('Enabled')) { - value = inputs[key] === 'true' ? 'false' : 'true'; - } - if (key === 'DefaultCollapseSidebar') { - value = inputs[key] === 'true' ? 'false' : 'true'; - } - console.log(key, value); - const res = await API.put('/api/option/', { - key, - value, - }); - const { success, message } = res.data; - if (success) { - setInputs((inputs) => ({ ...inputs, [key]: value })); - } else { - showError(message); - } - setLoading(false); - }; - - const handleInputChange = async (e, { name, value }) => { - if ( - name.endsWith('Enabled') || - name === 'DataExportInterval' || - name === 'DataExportDefaultTime' || - name === 'DefaultCollapseSidebar' - ) { - if (name === 'DataExportDefaultTime') { - localStorage.setItem('data_export_default_time', value); - } else if (name === 'MjNotifyEnabled') { - localStorage.setItem('mj_notify_enabled', value); - } - await updateOption(name, value); - } else { - setInputs((inputs) => ({ ...inputs, [name]: value })); - } - }; - - const submitConfig = async (group) => { - switch (group) { - case 'monitor': - if ( - originInputs['ChannelDisableThreshold'] !== - inputs.ChannelDisableThreshold - ) { - await updateOption( - 'ChannelDisableThreshold', - inputs.ChannelDisableThreshold, - ); - } - if ( - originInputs['QuotaRemindThreshold'] !== inputs.QuotaRemindThreshold - ) { - await updateOption( - 'QuotaRemindThreshold', - inputs.QuotaRemindThreshold, - ); - } - break; - case 'ratio': - if (originInputs['ModelRatio'] !== inputs.ModelRatio) { - if (!verifyJSON(inputs.ModelRatio)) { - showError('模型倍率不是合法的 JSON 字符串'); - return; - } - await updateOption('ModelRatio', inputs.ModelRatio); - } - if (originInputs['CompletionRatio'] !== inputs.CompletionRatio) { - if (!verifyJSON(inputs.CompletionRatio)) { - showError('模型补全倍率不是合法的 JSON 字符串'); - return; - } - await updateOption('CompletionRatio', inputs.CompletionRatio); - } - if (originInputs['GroupRatio'] !== inputs.GroupRatio) { - if (!verifyJSON(inputs.GroupRatio)) { - showError('分组倍率不是合法的 JSON 字符串'); - return; - } - await updateOption('GroupRatio', inputs.GroupRatio); - } - if (originInputs['ModelPrice'] !== inputs.ModelPrice) { - if (!verifyJSON(inputs.ModelPrice)) { - showError('模型固定价格不是合法的 JSON 字符串'); - return; - } - await updateOption('ModelPrice', inputs.ModelPrice); - } - break; - case 'words': - if (originInputs['SensitiveWords'] !== inputs.SensitiveWords) { - await updateOption('SensitiveWords', inputs.SensitiveWords); - } - break; - case 'quota': - if (originInputs['QuotaForNewUser'] !== inputs.QuotaForNewUser) { - await updateOption('QuotaForNewUser', inputs.QuotaForNewUser); - } - if (originInputs['QuotaForInvitee'] !== inputs.QuotaForInvitee) { - await updateOption('QuotaForInvitee', inputs.QuotaForInvitee); - } - if (originInputs['QuotaForInviter'] !== inputs.QuotaForInviter) { - await updateOption('QuotaForInviter', inputs.QuotaForInviter); - } - if (originInputs['PreConsumedQuota'] !== inputs.PreConsumedQuota) { - await updateOption('PreConsumedQuota', inputs.PreConsumedQuota); - } - break; - case 'general': - if (originInputs['TopUpLink'] !== inputs.TopUpLink) { - await updateOption('TopUpLink', inputs.TopUpLink); - } - if (originInputs['ChatLink'] !== inputs.ChatLink) { - await updateOption('ChatLink', inputs.ChatLink); - } - if (originInputs['ChatLink2'] !== inputs.ChatLink2) { - await updateOption('ChatLink2', inputs.ChatLink2); - } - if (originInputs['QuotaPerUnit'] !== inputs.QuotaPerUnit) { - await updateOption('QuotaPerUnit', inputs.QuotaPerUnit); - } - if (originInputs['RetryTimes'] !== inputs.RetryTimes) { - await updateOption('RetryTimes', inputs.RetryTimes); - } - break; - } - }; return ( <> - {/* 通用设置 */} - - - - {/* 绘图设置 */} - - - - {/* 屏蔽词过滤设置 */} - - - - {/* 日志设置 */} - - - - {/* 数据看板 */} - - - - {/* 监控设置 */} - - - - {/* 额度设置 */} - - - - - -
- {/**/} - {/* */} - {/**/} - {/**/} - {/* */} - {/**/} - - -
- 倍率设置 -
- - - - - - - - - - - - - { - submitConfig('ratio').then(); - }} - > - 保存倍率设置 - - -
-
+ + {/* 通用设置 */} + + + + {/* 绘图设置 */} + + + + {/* 屏蔽词过滤设置 */} + + + + {/* 日志设置 */} + + + + {/* 数据看板 */} + + + + {/* 监控设置 */} + + + + {/* 额度设置 */} + + + + {/* 倍率设置 */} + + + + ); }; diff --git a/web/src/pages/Setting/Operation/SettingsMagnification.js b/web/src/pages/Setting/Operation/SettingsMagnification.js new file mode 100644 index 0000000..3f38b37 --- /dev/null +++ b/web/src/pages/Setting/Operation/SettingsMagnification.js @@ -0,0 +1,193 @@ +import React, { useEffect, useState, useRef } from 'react'; +import { Button, Col, Form, Row, Spin } from '@douyinfe/semi-ui'; +import { + compareObjects, + API, + showError, + showSuccess, + showWarning, + verifyJSON, +} from '../../../helpers'; + +export default function SettingsMagnification(props) { + const [loading, setLoading] = useState(false); + const [inputs, setInputs] = useState({ + ModelPrice: '', + ModelRatio: '', + CompletionRatio: '', + GroupRatio: '', + }); + const refForm = useRef(); + const [inputsRow, setInputsRow] = useState(inputs); + + async function onSubmit() { + try { + await refForm.current.validate(); + const updateArray = compareObjects(inputs, inputsRow); + if (!updateArray.length) return showWarning('你似乎并没有修改什么'); + const requestQueue = updateArray.map((item) => { + let value = ''; + if (typeof inputs[item.key] === 'boolean') { + value = String(inputs[item.key]); + } else { + value = inputs[item.key]; + } + return API.put('/api/option/', { + key: item.key, + value, + }); + }); + setLoading(true); + Promise.all(requestQueue) + .then((res) => { + if (requestQueue.length === 1) { + if (res.includes(undefined)) return; + } else if (requestQueue.length > 1) { + if (res.includes(undefined)) return showError('部分更新失败'); + } + showSuccess('更新成功'); + }) + .catch(() => { + showError('更新失败'); + }) + .finally(() => { + setLoading(false); + setInputsRow(structuredClone(inputs)); + }); + } catch (error) { + showError('请检查输入'); + console.error(error); + } finally { + } + } + + useEffect(() => { + const currentInputs = {}; + for (let key in props.options) { + if (Object.keys(inputs).includes(key)) { + currentInputs[key] = props.options[key]; + } + } + setInputs(currentInputs); + setInputsRow(structuredClone(currentInputs)); + refForm.current.setValues(currentInputs); + }, [props.options]); + return ( + <> + +
(refForm.current = formAPI)} + style={{ marginBottom: 15 }} + > + + + + verifyJSON(value), + message: '不是合法的 JSON 字符串', + }, + ]} + onChange={(value) => + setInputs({ + ...inputs, + ModelPrice: value, + }) + } + /> + + + + + verifyJSON(value), + message: '不是合法的 JSON 字符串', + }, + ]} + onChange={(value) => + setInputs({ + ...inputs, + ModelRatio: value, + }) + } + /> + + + + + verifyJSON(value), + message: '不是合法的 JSON 字符串', + }, + ]} + onChange={(value) => + setInputs({ + ...inputs, + CompletionRatio: value, + }) + } + /> + + + + + verifyJSON(value), + message: '不是合法的 JSON 字符串', + }, + ]} + onChange={(value) => + setInputs({ + ...inputs, + GroupRatio: value, + }) + } + /> + + + + + + + +
+
+ + ); +}