| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
|
| import React, { useEffect, useState, useRef } from 'react'; |
| import { |
| Button, |
| Col, |
| Form, |
| Row, |
| Spin, |
| DatePicker, |
| Typography, |
| Modal, |
| } from '@douyinfe/semi-ui'; |
| import dayjs from 'dayjs'; |
| import { useTranslation } from 'react-i18next'; |
| import { |
| compareObjects, |
| API, |
| showError, |
| showSuccess, |
| showWarning, |
| } from '../../../helpers'; |
|
|
| const { Text } = Typography; |
|
|
| export default function SettingsLog(props) { |
| const { t } = useTranslation(); |
| const [loading, setLoading] = useState(false); |
| const [loadingCleanHistoryLog, setLoadingCleanHistoryLog] = useState(false); |
| const [inputs, setInputs] = useState({ |
| LogConsumeEnabled: false, |
| historyTimestamp: dayjs().subtract(1, 'month').toDate(), |
| }); |
| const refForm = useRef(); |
| const [inputsRow, setInputsRow] = useState(inputs); |
|
|
| function onSubmit() { |
| const updateArray = compareObjects(inputs, inputsRow).filter( |
| (item) => item.key !== 'historyTimestamp', |
| ); |
|
|
| if (!updateArray.length) return showWarning(t('你似乎并没有修改什么')); |
| 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(t('部分保存失败,请重试')); |
| } |
| showSuccess(t('保存成功')); |
| props.refresh(); |
| }) |
| .catch(() => { |
| showError(t('保存失败,请重试')); |
| }) |
| .finally(() => { |
| setLoading(false); |
| }); |
| } |
| async function onCleanHistoryLog() { |
| if (!inputs.historyTimestamp) { |
| showError(t('请选择日志记录时间')); |
| return; |
| } |
|
|
| const now = dayjs(); |
| const targetDate = dayjs(inputs.historyTimestamp); |
| const targetTime = targetDate.format('YYYY-MM-DD HH:mm:ss'); |
| const currentTime = now.format('YYYY-MM-DD HH:mm:ss'); |
| const daysDiff = now.diff(targetDate, 'day'); |
|
|
| Modal.confirm({ |
| title: t('确认清除历史日志'), |
| content: ( |
| <div style={{ lineHeight: '1.8' }}> |
| <p> |
| <Text>{t('当前时间')}:</Text> |
| <Text strong style={{ color: '#52c41a' }}> |
| {currentTime} |
| </Text> |
| </p> |
| <p> |
| <Text>{t('选择时间')}:</Text> |
| <Text strong type='danger'> |
| {targetTime} |
| </Text> |
| {daysDiff > 0 && ( |
| <Text type='tertiary'> |
| {' '} |
| ({t('约')} {daysDiff} {t('天前')}) |
| </Text> |
| )} |
| </p> |
| <div |
| style={{ |
| background: '#fff7e6', |
| border: '1px solid #ffd591', |
| padding: '12px', |
| borderRadius: '4px', |
| marginTop: '12px', |
| color: '#333', |
| }} |
| > |
| <Text strong style={{ color: '#d46b08' }}> |
| ⚠️ {t('注意')}: |
| </Text> |
| <Text style={{ color: '#333' }}>{t('将删除')} </Text> |
| <Text strong style={{ color: '#cf1322' }}> |
| {targetTime} |
| </Text> |
| {daysDiff > 0 && ( |
| <Text style={{ color: '#8c8c8c' }}> |
| {' '} |
| ({t('约')} {daysDiff} {t('天前')}) |
| </Text> |
| )} |
| <Text style={{ color: '#333' }}> {t('之前的所有日志')}</Text> |
| </div> |
| <p style={{ marginTop: '12px' }}> |
| <Text type='danger'> |
| {t('此操作不可恢复,请仔细确认时间后再操作!')} |
| </Text> |
| </p> |
| </div> |
| ), |
| okText: t('确认删除'), |
| cancelText: t('取消'), |
| okType: 'danger', |
| onOk: async () => { |
| try { |
| setLoadingCleanHistoryLog(true); |
| const res = await API.delete( |
| `/api/log/?target_timestamp=${Date.parse(inputs.historyTimestamp) / 1000}`, |
| ); |
| const { success, message, data } = res.data; |
| if (success) { |
| showSuccess(`${data} ${t('条日志已清理!')}`); |
| return; |
| } else { |
| throw new Error(t('日志清理失败:') + message); |
| } |
| } catch (error) { |
| showError(error.message); |
| } finally { |
| setLoadingCleanHistoryLog(false); |
| } |
| }, |
| }); |
| } |
|
|
| useEffect(() => { |
| const currentInputs = {}; |
| for (let key in props.options) { |
| if (Object.keys(inputs).includes(key)) { |
| currentInputs[key] = props.options[key]; |
| } |
| } |
| currentInputs['historyTimestamp'] = inputs.historyTimestamp; |
| setInputs(Object.assign(inputs, currentInputs)); |
| setInputsRow(structuredClone(currentInputs)); |
| refForm.current.setValues(currentInputs); |
| }, [props.options]); |
| return ( |
| <> |
| <Spin spinning={loading}> |
| <Form |
| values={inputs} |
| getFormApi={(formAPI) => (refForm.current = formAPI)} |
| style={{ marginBottom: 15 }} |
| > |
| <Form.Section text={t('日志设置')}> |
| <Row gutter={16}> |
| <Col xs={24} sm={12} md={8} lg={8} xl={8}> |
| <Form.Switch |
| field={'LogConsumeEnabled'} |
| label={t('启用额度消费日志记录')} |
| size='default' |
| checkedText='|' |
| uncheckedText='〇' |
| onChange={(value) => { |
| setInputs({ |
| ...inputs, |
| LogConsumeEnabled: value, |
| }); |
| }} |
| /> |
| </Col> |
| <Col xs={24} sm={12} md={8} lg={8} xl={8}> |
| <Spin spinning={loadingCleanHistoryLog}> |
| <Form.DatePicker |
| label={t('清除历史日志')} |
| field={'historyTimestamp'} |
| type='dateTime' |
| inputReadOnly={true} |
| onChange={(value) => { |
| setInputs({ |
| ...inputs, |
| historyTimestamp: value, |
| }); |
| }} |
| /> |
| <Text |
| type='tertiary' |
| size='small' |
| style={{ display: 'block', marginTop: 4, marginBottom: 8 }} |
| > |
| {t('将清除选定时间之前的所有日志')} |
| </Text> |
| <Button |
| size='default' |
| type='danger' |
| onClick={onCleanHistoryLog} |
| > |
| {t('清除历史日志')} |
| </Button> |
| </Spin> |
| </Col> |
| </Row> |
| |
| <Row> |
| <Button size='default' onClick={onSubmit}> |
| {t('保存日志设置')} |
| </Button> |
| </Row> |
| </Form.Section> |
| </Form> |
| </Spin> |
| </> |
| ); |
| } |
|
|