diff --git a/web/src/components/OperationSetting.js b/web/src/components/OperationSetting.js index f2713b4..ef82bbc 100644 --- a/web/src/components/OperationSetting.js +++ b/web/src/components/OperationSetting.js @@ -3,7 +3,8 @@ import {Divider, Form, Grid, Header} from 'semantic-ui-react'; import {API, showError, showSuccess, timestamp2string, verifyJSON} from '../helpers'; const OperationSetting = () => { - let now = new Date();let [inputs, setInputs] = useState({ + let now = new Date(); + let [inputs, setInputs] = useState({ QuotaForNewUser: 0, QuotaForInviter: 0, QuotaForInvitee: 0, @@ -20,28 +21,32 @@ const OperationSetting = () => { LogConsumeEnabled: '', DisplayInCurrencyEnabled: '', DisplayTokenStatEnabled: '', + DrawingEnabled: '', + DataExportEnabled: '', + DataExportInterval: 5, RetryTimes: 0 }); const [originInputs, setOriginInputs] = useState({}); - let [loading, setLoading] = useState(false);let [historyTimestamp, setHistoryTimestamp] = useState(timestamp2string(now.getTime() / 1000 - 30 * 24 * 3600)); // a month ago + let [loading, setLoading] = useState(false); + let [historyTimestamp, setHistoryTimestamp] = useState(timestamp2string(now.getTime() / 1000 - 30 * 24 * 3600)); // a month ago - const getOptions = async () => { - const res = await API.get('/api/option/'); - const { success, message, data } = res.data; - if (success) { - let newInputs = {}; - data.forEach((item) => { - if (item.key === 'ModelRatio' || item.key === 'GroupRatio'|| item.key === 'ModelPrice') { - item.value = JSON.stringify(JSON.parse(item.value), null, 2); + const getOptions = async () => { + const res = await API.get('/api/option/'); + const {success, message, data} = res.data; + if (success) { + let newInputs = {}; + data.forEach((item) => { + if (item.key === 'ModelRatio' || item.key === 'GroupRatio' || item.key === 'ModelPrice') { + item.value = JSON.stringify(JSON.parse(item.value), null, 2); + } + newInputs[item.key] = item.value; + }); + setInputs(newInputs); + setOriginInputs(newInputs); + } else { + showError(message); } - newInputs[item.key] = item.value; - }); - setInputs(newInputs); - setOriginInputs(newInputs); - } else { - showError(message); - } - }; + }; useEffect(() => { getOptions().then(); @@ -66,87 +71,88 @@ const OperationSetting = () => { }; const handleInputChange = async (e, {name, value}) => { - if (name.endsWith('Enabled')) { + if (name.endsWith('Enabled') || name === 'DataExportInterval') { 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); + 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['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 '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['QuotaPerUnit'] !== inputs.QuotaPerUnit) { + await updateOption('QuotaPerUnit', inputs.QuotaPerUnit); + } + if (originInputs['RetryTimes'] !== inputs.RetryTimes) { + await updateOption('RetryTimes', inputs.RetryTimes); + } + break; } - 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['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 '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['QuotaPerUnit'] !== inputs.QuotaPerUnit) { - await updateOption('QuotaPerUnit', inputs.QuotaPerUnit); - } - if (originInputs['RetryTimes'] !== inputs.RetryTimes) { - await updateOption('RetryTimes', inputs.RetryTimes); - } - break; - } - }; + }; const deleteHistoryLogs = async () => { - console.log(inputs); - const res = await API.delete(`/api/log/?target_timestamp=${Date.parse(historyTimestamp) / 1000}`); - const { success, message, data } = res.data; - if (success) { - showSuccess(`${data} 条日志已清理!`); - return; - } - showError('日志清理失败:' + message); - };return ( + console.log(inputs); + const res = await API.delete(`/api/log/?target_timestamp=${Date.parse(historyTimestamp) / 1000}`); + const {success, message, data} = res.data; + if (success) { + showSuccess(`${data} 条日志已清理!`); + return; + } + showError('日志清理失败:' + message); + }; + return (
@@ -208,31 +214,58 @@ const OperationSetting = () => { name='DisplayTokenStatEnabled' onChange={handleInputChange} /> + { submitConfig('general').then(); - }}>保存通用设置 -
- 日志设置 -
- - - - - { - setHistoryTimestamp(value); - }} /> - - { - deleteHistoryLogs().then(); - }}>清理历史日志 + }}>保存通用设置 +
+ 日志设置 +
+ + + + + + + + + + + { + setHistoryTimestamp(value); + }}/> + + { + deleteHistoryLogs().then(); + }}>清理历史日志
监控设置 diff --git a/web/src/components/SiderBar.js b/web/src/components/SiderBar.js index 3758e62..3d1e497 100644 --- a/web/src/components/SiderBar.js +++ b/web/src/components/SiderBar.js @@ -6,7 +6,7 @@ import {API, getLogo, getSystemName, isAdmin, isMobile, showSuccess} from '../he import '../index.css'; import { - IconAt, + IconCalendarClock, IconHistogram, IconGift, IconKey, @@ -74,11 +74,19 @@ let headerButtons = [ to: '/log', icon: }, + { + text: '数据看版', + itemKey: 'detail', + to: '/detail', + icon: , + className: localStorage.getItem('enable_data_export') === 'true'?'semi-navigation-item-normal':'tableHiddle', + }, { text: '绘图', itemKey: 'midjourney', to: '/midjourney', - icon: + icon: , + className: localStorage.getItem('enable_drawing') === 'true'?'semi-navigation-item-normal':'tableHiddle', }, { text: '设置', @@ -133,6 +141,7 @@ const SiderBar = () => { setting: "/setting", about: "/about", chat: "/chat", + detail: "/detail", }; return (