修复antd兼容性,日志详情自动滚动

This commit is contained in:
whyour
2023-01-11 22:03:44 +08:00
parent 443c581955
commit 2e3c3274c7
12 changed files with 459 additions and 336 deletions
+18
View File
@@ -0,0 +1,18 @@
import React from 'react';
import { Button, Result, Typography } from 'antd';
const { Link } = Typography;
const NotFound: React.FC = () => (
<Result
status="404"
title="404"
extra={
<Button type="primary">
<Link href="/"></Link>
</Button>
}
/>
);
export default NotFound;
+42 -45
View File
@@ -14,6 +14,7 @@ import {
Popover,
Tabs,
TablePaginationConfig,
MenuProps,
} from 'antd';
import {
ClockCircleOutlined,
@@ -684,15 +685,13 @@ const Crontab = () => {
arrow={{ pointAtCenter: true }}
placement="bottomRight"
trigger={['click']}
overlay={
<Menu
items={getMenuItems(record)}
onClick={({ key, domEvent }) => {
domEvent.stopPropagation();
action(key, record, index);
}}
/>
}
menu={{
items: getMenuItems(record),
onClick: ({ key, domEvent }) => {
domEvent.stopPropagation();
action(key, record, index);
},
}}
>
<a onClick={(e) => e.stopPropagation()}>
<EllipsisOutlined />
@@ -889,41 +888,39 @@ const Crontab = () => {
}
};
const menu = (
<Menu
onClick={({ key, domEvent }) => {
domEvent.stopPropagation();
viewAction(key);
}}
items={[
...[...enabledCronViews].slice(4).map((x) => ({
label: (
<Space style={{ display: 'flex', justifyContent: 'space-between' }}>
<span>{x.name}</span>
{viewConf?.id === x.id && (
<CheckOutlined style={{ color: '#1890ff' }} />
)}
</Space>
),
key: x.id,
icon: <UnorderedListOutlined />,
})),
{
type: 'divider',
},
{
label: '新建视图',
key: 'new',
icon: <PlusOutlined />,
},
{
label: '视图管理',
key: 'manage',
icon: <SettingOutlined />,
},
]}
/>
);
const menu: MenuProps = {
onClick: ({ key, domEvent }) => {
domEvent.stopPropagation();
viewAction(key);
},
items: [
...[...enabledCronViews].slice(4).map((x) => ({
label: (
<Space style={{ display: 'flex', justifyContent: 'space-between' }}>
<span>{x.name}</span>
{viewConf?.id === x.id && (
<CheckOutlined style={{ color: '#1890ff' }} />
)}
</Space>
),
key: x.id,
icon: <UnorderedListOutlined />,
})),
{
type: 'divider' as 'group',
},
{
label: '新建视图',
key: 'new',
icon: <PlusOutlined />,
},
{
label: '视图管理',
key: 'manage',
icon: <SettingOutlined />,
},
],
};
const getCronViews = () => {
setLoading(true);
@@ -975,7 +972,7 @@ const Crontab = () => {
className={`crontab-view ${moreMenuActive ? 'more-active' : ''}`}
tabBarExtraContent={
<Dropdown
overlay={menu}
menu={menu}
trigger={['click']}
overlayStyle={{ minWidth: 200 }}
>
+10 -6
View File
@@ -1,4 +1,4 @@
import React, { useEffect, useState } from 'react';
import React, { useEffect, useRef, useState } from 'react';
import { Modal, message, Input, Form, Statistic, Button } from 'antd';
import { request } from '@/utils/http';
import config from '@/utils/config';
@@ -34,7 +34,6 @@ const CronLogModal = ({
const [loading, setLoading] = useState<any>(true);
const [executing, setExecuting] = useState<any>(true);
const [isPhone, setIsPhone] = useState(false);
const [theme, setTheme] = useState<string>('');
const getCronLog = (isFirst?: boolean) => {
if (isFirst) {
@@ -49,10 +48,14 @@ const CronLogModal = ({
) {
const log = data as string;
setValue(log || '暂无日志');
setExecuting(
log && !logEnded(log) && !log.includes('重启面板'),
);
if (log && !logEnded(log) && !log.includes('重启面板')) {
const hasNext = log && !logEnded(log) && !log.includes('重启面板');
setExecuting(hasNext);
setTimeout(() => {
document
.querySelector('#log-flag')!
.scrollIntoView({ behavior: 'smooth' });
});
if (hasNext) {
setTimeout(() => {
getCronLog();
}, 2000);
@@ -155,6 +158,7 @@ const CronLogModal = ({
{value}
</pre>
)}
<div id="log-flag"></div>
</Modal>
);
};
+42 -42
View File
@@ -11,6 +11,7 @@ import {
Dropdown,
Menu,
Empty,
MenuProps,
} from 'antd';
import config from '@/utils/config';
import { PageContainer } from '@ant-design/pro-layout';
@@ -66,7 +67,8 @@ const Script = () => {
const [isEditing, setIsEditing] = useState(false);
const editorRef = useRef<any>(null);
const [isAddFileModalVisible, setIsAddFileModalVisible] = useState(false);
const [isRenameFileModalVisible, setIsRenameFileModalVisible] = useState(false);
const [isRenameFileModalVisible, setIsRenameFileModalVisible] =
useState(false);
const [currentNode, setCurrentNode] = useState<any>();
const [expandedKeys, setExpandedKeys] = useState<string[]>([]);
@@ -293,12 +295,12 @@ const Script = () => {
const renameFile = () => {
setIsRenameFileModalVisible(true);
}
};
const handleRenameFileCancel = () => {
setIsRenameFileModalVisible(false);
getScripts(false);
}
};
const addFile = () => {
setIsAddFileModalVisible(true);
@@ -402,46 +404,44 @@ const Script = () => {
}
};
const menu = isEditing ? (
<Menu
items={[
{ label: '保存', key: 'save', icon: <PlusOutlined /> },
{ label: '退出编辑', key: 'exit', icon: <EditOutlined /> },
]}
onClick={({ key, domEvent }) => {
domEvent.stopPropagation();
action(key);
}}
/>
) : (
<Menu
items={[
{ label: '新建', key: 'add', icon: <PlusOutlined /> },
{
label: '编辑',
key: 'edit',
icon: <EditOutlined />,
disabled: !select,
const menu: MenuProps = isEditing
? {
items: [
{ label: '保存', key: 'save', icon: <PlusOutlined /> },
{ label: '退出编辑', key: 'exit', icon: <EditOutlined /> },
],
onClick: ({ key, domEvent }) => {
domEvent.stopPropagation();
action(key);
},
{
label: '重命名',
key: 'rename',
icon: <IconFont type="ql-icon-rename" />,
disabled: !select,
}
: {
items: [
{ label: '新建', key: 'add', icon: <PlusOutlined /> },
{
label: '编辑',
key: 'edit',
icon: <EditOutlined />,
disabled: !select,
},
{
label: '重命名',
key: 'rename',
icon: <IconFont type="ql-icon-rename" />,
disabled: !select,
},
{
label: '删除',
key: 'delete',
icon: <DeleteOutlined />,
disabled: !select,
},
],
onClick: ({ key, domEvent }) => {
domEvent.stopPropagation();
menuAction(key);
},
{
label: '删除',
key: 'delete',
icon: <DeleteOutlined />,
disabled: !select,
},
]}
onClick={({ key, domEvent }) => {
domEvent.stopPropagation();
menuAction(key);
}}
/>
);
};
return (
<PageContainer
@@ -464,7 +464,7 @@ const Script = () => {
allowClear
onSelect={onSelect}
/>,
<Dropdown overlay={menu} trigger={['click']}>
<Dropdown menu={menu} trigger={['click']}>
<Button type="primary" icon={<EllipsisOutlined />} />
</Dropdown>,
]
+6 -105
View File
@@ -17,7 +17,6 @@ import {
import config from '@/utils/config';
import { PageContainer } from '@ant-design/pro-layout';
import { request } from '@/utils/http';
import * as DarkReader from '@umijs/ssr-darkreader';
import AppModal from './appModal';
import {
EditOutlined,
@@ -27,18 +26,13 @@ import {
import SecuritySettings from './security';
import LoginLog from './loginLog';
import NotificationSetting from './notification';
import CheckUpdate from './checkUpdate';
import Other from './other';
import About from './about';
import { useOutletContext } from '@umijs/max';
import { SharedContext } from '@/layouts';
import './index.less';
const { Text } = Typography;
const optionsWithDisabled = [
{ label: '亮色', value: 'light' },
{ label: '暗色', value: 'dark' },
{ label: '跟随系统', value: 'auto' },
];
const Setting = () => {
const {
@@ -121,37 +115,12 @@ const Setting = () => {
];
const [loading, setLoading] = useState(true);
const defaultTheme = localStorage.getItem('qinglong_dark_theme') || 'auto';
const [dataSource, setDataSource] = useState<any[]>([]);
const [isModalVisible, setIsModalVisible] = useState(false);
const [editedApp, setEditedApp] = useState<any>();
const [tabActiveKey, setTabActiveKey] = useState('security');
const [loginLogData, setLoginLogData] = useState<any[]>([]);
const [notificationInfo, setNotificationInfo] = useState<any>();
const [logRemoveFrequency, setLogRemoveFrequency] = useState<number>();
const [form] = Form.useForm();
const {
enable: enableDarkMode,
disable: disableDarkMode,
exportGeneratedCSS: collectCSS,
setFetchMethod,
auto: followSystemColorScheme,
} = DarkReader || {};
const themeChange = (e: any) => {
const _theme = e.target.value;
localStorage.setItem('qinglong_dark_theme', e.target.value);
setFetchMethod(fetch);
if (_theme === 'dark') {
enableDarkMode({});
} else if (_theme === 'light') {
disableDarkMode();
} else {
followSystemColorScheme({});
}
reloadTheme();
};
const getApps = () => {
setLoading(true);
@@ -276,8 +245,6 @@ const Setting = () => {
getLoginLog();
} else if (activeKey === 'notification') {
getNotification();
} else if (activeKey === 'other') {
getLogRemoveFrequency();
}
};
@@ -294,37 +261,6 @@ const Setting = () => {
});
};
const getLogRemoveFrequency = () => {
request
.get(`${config.apiPrefix}system/log/remove`)
.then(({ code, data }) => {
if (code === 200 && data.info) {
const { frequency } = data.info;
setLogRemoveFrequency(frequency);
}
})
.catch((error: any) => {
console.log(error);
});
};
const updateRemoveLogFrequency = () => {
setTimeout(() => {
request
.put(`${config.apiPrefix}system/log/remove`, {
data: { frequency: logRemoveFrequency },
})
.then(({ code, data }) => {
if (code === 200) {
message.success('更新成功');
}
})
.catch((error: any) => {
console.log(error);
});
});
};
return (
<PageContainer
className="ql-container-wrapper ql-container-wrapper-has-tab ql-setting-container"
@@ -382,46 +318,11 @@ const Setting = () => {
key: 'other',
label: '其他设置',
children: (
<Form layout="vertical" form={form}>
<Form.Item
label="主题设置"
name="theme"
initialValue={defaultTheme}
>
<Radio.Group
options={optionsWithDisabled}
onChange={themeChange}
value={defaultTheme}
optionType="button"
buttonStyle="solid"
/>
</Form.Item>
<Form.Item
label="日志删除频率"
name="frequency"
tooltip="每x天自动删除x天以前的日志"
>
<Input.Group compact>
<InputNumber
addonBefore="每"
addonAfter="天"
style={{ width: 150 }}
min={0}
value={logRemoveFrequency}
onChange={(value) => setLogRemoveFrequency(value)}
/>
<Button type="primary" onClick={updateRemoveLogFrequency}>
</Button>
</Input.Group>
</Form.Item>
<Form.Item label="检查更新" name="update">
<CheckUpdate
systemInfo={systemInfo}
socketMessage={socketMessage}
/>
</Form.Item>
</Form>
<Other
reloadTheme={reloadTheme}
socketMessage={socketMessage}
systemInfo={systemInfo}
/>
),
},
{
+120
View File
@@ -0,0 +1,120 @@
import React, { useState, useEffect } from 'react';
import { Button, InputNumber, Form, Radio, message, Input } from 'antd';
import * as DarkReader from '@umijs/ssr-darkreader';
import config from '@/utils/config';
import { request } from '@/utils/http';
import CheckUpdate from './checkUpdate';
import { SharedContext } from '@/layouts';
import './index.less';
const optionsWithDisabled = [
{ label: '亮色', value: 'light' },
{ label: '暗色', value: 'dark' },
{ label: '跟随系统', value: 'auto' },
];
const Other = ({
systemInfo,
socketMessage,
reloadTheme,
}: Pick<SharedContext, 'socketMessage' | 'reloadTheme' | 'systemInfo'>) => {
const defaultTheme = localStorage.getItem('qinglong_dark_theme') || 'auto';
const [logRemoveFrequency, setLogRemoveFrequency] = useState<number | null>();
const [form] = Form.useForm();
const {
enable: enableDarkMode,
disable: disableDarkMode,
exportGeneratedCSS: collectCSS,
setFetchMethod,
auto: followSystemColorScheme,
} = DarkReader || {};
const themeChange = (e: any) => {
const _theme = e.target.value;
localStorage.setItem('qinglong_dark_theme', e.target.value);
setFetchMethod(fetch);
if (_theme === 'dark') {
enableDarkMode({});
} else if (_theme === 'light') {
disableDarkMode();
} else {
followSystemColorScheme({});
}
reloadTheme();
};
const getLogRemoveFrequency = () => {
request
.get(`${config.apiPrefix}system/log/remove`)
.then(({ code, data }) => {
if (code === 200 && data.info) {
const { frequency } = data.info;
setLogRemoveFrequency(frequency);
}
})
.catch((error: any) => {
console.log(error);
});
};
const updateRemoveLogFrequency = () => {
setTimeout(() => {
request
.put(`${config.apiPrefix}system/log/remove`, {
data: { frequency: logRemoveFrequency },
})
.then(({ code, data }) => {
if (code === 200) {
message.success('更新成功');
}
})
.catch((error: any) => {
console.log(error);
});
});
};
useEffect(() => {
getLogRemoveFrequency();
}, []);
return (
<Form layout="vertical" form={form}>
<Form.Item label="主题设置" name="theme" initialValue={defaultTheme}>
<Radio.Group
options={optionsWithDisabled}
onChange={themeChange}
value={defaultTheme}
optionType="button"
buttonStyle="solid"
/>
</Form.Item>
<Form.Item
label="日志删除频率"
name="frequency"
tooltip="每x天自动删除x天以前的日志"
>
<Input.Group compact>
<InputNumber
addonBefore="每"
addonAfter="天"
style={{ width: 150 }}
min={0}
value={logRemoveFrequency}
onChange={(value) => setLogRemoveFrequency(value)}
/>
<Button type="primary" onClick={updateRemoveLogFrequency}>
</Button>
</Input.Group>
</Form.Item>
<Form.Item label="检查更新" name="update">
<CheckUpdate systemInfo={systemInfo} socketMessage={socketMessage} />
</Form.Item>
</Form>
);
};
export default Other;
+20 -22
View File
@@ -427,28 +427,26 @@ const Subscription = () => {
arrow={{ pointAtCenter: true }}
placement="bottomRight"
trigger={['click']}
overlay={
<Menu
items={[
{ label: '编辑', key: 'edit', icon: <EditOutlined /> },
{
label: record.is_disabled === 1 ? '启用' : '禁用',
key: 'enableOrDisable',
icon:
record.is_disabled === 1 ? (
<CheckCircleOutlined />
) : (
<StopOutlined />
),
},
{ label: '删除', key: 'delete', icon: <DeleteOutlined /> },
]}
onClick={({ key, domEvent }) => {
domEvent.stopPropagation();
action(key, record, index);
}}
/>
}
menu={{
items: [
{ label: '编辑', key: 'edit', icon: <EditOutlined /> },
{
label: record.is_disabled === 1 ? '启用' : '禁用',
key: 'enableOrDisable',
icon:
record.is_disabled === 1 ? (
<CheckCircleOutlined />
) : (
<StopOutlined />
),
},
{ label: '删除', key: 'delete', icon: <DeleteOutlined /> },
],
onClick: ({ key, domEvent }) => {
domEvent.stopPropagation();
action(key, record, index);
},
}}
>
<a onClick={(e) => e.stopPropagation()}>
<EllipsisOutlined />