ck管理增加排序,禁用,实时状态变成手动获取

This commit is contained in:
whyour
2021-04-10 00:21:51 +08:00
parent ef24fc8354
commit fb98bc44e4
17 changed files with 621 additions and 522 deletions
View File
-77
View File
@@ -1,77 +0,0 @@
import React, { PureComponent, Fragment, useState, useEffect } from 'react';
import { Button, notification, Modal } from 'antd';
import config from '@/utils/config';
import { PageContainer } from '@ant-design/pro-layout';
import { Controlled as CodeMirror } from 'react-codemirror2';
import { request } from '@/utils/http';
const Crontab = () => {
const [width, setWdith] = useState('100%');
const [marginLeft, setMarginLeft] = useState(0);
const [marginTop, setMarginTop] = useState(-72);
const [value, setValue] = useState('');
const [loading, setLoading] = useState(true);
const getConfig = () => {
setLoading(true);
request
.get(`${config.apiPrefix}config/shareCode`)
.then((data) => {
setValue(data.data);
})
.finally(() => setLoading(false));
};
useEffect(() => {
if (document.body.clientWidth < 768) {
setWdith('auto');
setMarginLeft(0);
setMarginTop(0);
} else {
setWdith('100%');
setMarginLeft(0);
setMarginTop(-72);
}
getConfig();
}, []);
return (
<PageContainer
className="code-mirror-wrapper"
title="互助码"
header={{
style: {
padding: '4px 16px 4px 15px',
position: 'sticky',
top: 0,
left: 0,
zIndex: 20,
marginTop,
width,
marginLeft,
},
}}
style={{
height: '100vh',
}}
>
<CodeMirror
value={value}
options={{
lineNumbers: true,
lineWrapping: true,
styleActiveLine: true,
matchBrackets: true,
mode: 'shell',
readOnly: true,
}}
onBeforeChange={(editor, data, value) => {
setValue(value);
}}
onChange={(editor, data, value) => {}}
/>
</PageContainer>
);
};
export default Crontab;
+7
View File
@@ -0,0 +1,7 @@
tr.drop-over-downward td {
border-bottom: 2px dashed #1890ff;
}
tr.drop-over-upward td {
border-top: 2px dashed #1890ff;
}
+246 -109
View File
@@ -1,4 +1,4 @@
import React, { PureComponent, Fragment, useState, useEffect } from 'react';
import React, { useCallback, useRef, useState, useEffect } from 'react';
import {
Button,
notification,
@@ -7,48 +7,121 @@ import {
Tag,
Space,
Typography,
Tooltip,
} from 'antd';
import { EditOutlined, DeleteOutlined } from '@ant-design/icons';
import {
EditOutlined,
DeleteOutlined,
SyncOutlined,
CheckCircleOutlined,
StopOutlined,
} from '@ant-design/icons';
import config from '@/utils/config';
import { PageContainer } from '@ant-design/pro-layout';
import { request } from '@/utils/http';
import QRCode from 'qrcode.react';
import CookieModal from './modal';
import { DndProvider, useDrag, useDrop } from 'react-dnd';
import { HTML5Backend } from 'react-dnd-html5-backend';
import './index.less';
const { Text } = Typography;
enum Status {
'未获取',
'正常',
'失效',
'已禁用',
'已失效',
'状态异常',
}
enum StatusColor {
'default',
'success',
'error',
'warning',
'error',
}
const type = 'DragableBodyRow';
const DragableBodyRow = ({
index,
moveRow,
className,
style,
...restProps
}: any) => {
const ref = useRef();
const [{ isOver, dropClassName }, drop] = useDrop(
() => ({
accept: type,
collect: (monitor) => {
const { index: dragIndex } = monitor.getItem() || ({} as any);
if (dragIndex === index) {
return {};
}
return {
isOver: monitor.isOver(),
dropClassName:
dragIndex < index ? ' drop-over-downward' : ' drop-over-upward',
};
},
drop: (item: any) => {
moveRow(item.index, index);
},
}),
[index],
);
const [, drag, preview] = useDrag(
() => ({
type,
item: { index },
collect: (monitor) => ({
isDragging: monitor.isDragging(),
}),
}),
[index],
);
drop(drag(ref));
return (
<tr
ref={ref}
className={`${className}${isOver ? dropClassName : ''}`}
style={{ cursor: 'move', ...style }}
{...restProps}
>
{restProps.children}
</tr>
);
};
const Config = () => {
const columns = [
{
title: '序号',
align: 'center' as const,
render: (text: string, record: any, index: number) => {
return <span style={{ cursor: 'text' }}>{index + 1} </span>;
},
},
{
title: '用户名',
dataIndex: 'pin',
key: 'pin',
align: 'center' as const,
render: (text: string, record: any) => {
return <span>{decodeURIComponent(text)}</span>;
const match = record.value.match(/pt_pin=([^; ]+)(?=;?)/);
const val = (match && match[1]) || '未匹配用户名';
return (
<span style={{ cursor: 'text' }}>{decodeURIComponent(val)}</span>
);
},
},
{
title: '昵称',
dataIndex: 'nickname',
key: 'nickname',
align: 'center' as const,
},
{
title: '值',
dataIndex: 'cookie',
key: 'cookie',
dataIndex: 'value',
key: 'value',
align: 'center' as const,
width: '50%',
render: (text: string, record: any) => {
@@ -58,6 +131,7 @@ const Config = () => {
textAlign: 'left',
display: 'inline-block',
wordBreak: 'break-all',
cursor: 'text',
}}
>
{text}
@@ -70,12 +144,23 @@ const Config = () => {
key: 'status',
dataIndex: 'status',
align: 'center' as const,
render: (text: string, record: any) => {
width: '15%',
render: (text: string, record: any, index: number) => {
return (
<Space size="middle">
<Tag color={StatusColor[record.status]}>
<Space size="middle" style={{ cursor: 'text' }}>
<Tag
color={StatusColor[record.status] || StatusColor[3]}
style={{ marginRight: 0 }}
>
{Status[record.status]}
</Tag>
{record.status !== Status. && (
<Tooltip title="刷新">
<a onClick={() => refreshStatus(record, index)}>
<SyncOutlined />
</a>
</Tooltip>
)}
</Space>
);
},
@@ -86,8 +171,25 @@ const Config = () => {
align: 'center' as const,
render: (text: string, record: any, index: number) => (
<Space size="middle">
<EditOutlined onClick={() => editCookie(record, index)} />
<DeleteOutlined onClick={() => deleteCookie(record, index)} />
<Tooltip title="编辑">
<a onClick={() => editCookie(record, index)}>
<EditOutlined />
</a>
</Tooltip>
<Tooltip title={record.status === Status. ? '启用' : '禁用'}>
<a onClick={() => enabledOrDisabledCron(record, index)}>
{record.status === Status. ? (
<CheckCircleOutlined />
) : (
<StopOutlined />
)}
</a>
</Tooltip>
<Tooltip title="删除">
<a onClick={() => deleteCookie(record, index)}>
<DeleteOutlined />
</a>
</Tooltip>
</Space>
),
},
@@ -95,7 +197,7 @@ const Config = () => {
const [width, setWdith] = useState('100%');
const [marginLeft, setMarginLeft] = useState(0);
const [marginTop, setMarginTop] = useState(-72);
const [value, setValue] = useState();
const [value, setValue] = useState<any[]>([]);
const [loading, setLoading] = useState(true);
const [isModalVisible, setIsModalVisible] = useState(false);
const [editedCookie, setEditedCookie] = useState();
@@ -110,98 +212,77 @@ const Config = () => {
.finally(() => setLoading(false));
};
function sleep(time: number) {
return new Promise((resolve) => setTimeout(resolve, time));
}
const showQrCode = (oldCookie?: string) => {
request.get(`${config.apiPrefix}qrcode`).then(async (data) => {
if (data.qrcode) {
const modal = Modal.info({
title: '二维码',
content: (
<div
style={{
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
marginLeft: -38,
}}
>
<QRCode
style={{
width: 200,
height: 200,
marginBottom: 10,
marginTop: 20,
}}
value={data.qrcode}
/>
</div>
),
});
getCookie(modal, oldCookie);
} else {
notification.error({ message: '获取二维码失败' });
}
});
};
const getCookie = async (
modal: { destroy: () => void },
oldCookie: string = '',
) => {
for (let i = 0; i < 50; i++) {
const {
data: { cookie, errcode, message },
} = await request.get(`${config.apiPrefix}cookie?cookie=${oldCookie}`);
if (cookie) {
notification.success({
message: 'Cookie获取成功',
});
modal.destroy();
Modal.success({
title: '获取Cookie成功',
content: <div>{cookie}</div>,
});
getCookies();
break;
}
if (errcode !== 176) {
notification.error({ message });
break;
}
await sleep(2000);
}
};
const reacquire = async (record: any) => {
await showQrCode(record.cookie);
};
const refreshStatus = (record: any, index: number) => {
request
.post(`${config.apiPrefix}cookie/refresh`, {
data: { cookie: record.cookie },
})
.get(`${config.apiPrefix}cookies/${record._id}/refresh`)
.then(async (data: any) => {
if (data.data && data.data.cookie) {
if (data.data && data.data.value) {
(value as any).splice(index, 1, data.data);
setValue([...(value as any)] as any);
notification.success({ message: '更新状态成功' });
} else {
notification.error({ message: '更新状态失败' });
}
});
};
const enabledOrDisabledCron = (record: any, index: number) => {
Modal.confirm({
title: `确认${record.status === Status. ? '启用' : '禁用'}`,
content: (
<>
{record.status === Status. ? '启用' : '禁用'}
Cookie{' '}
<Text style={{ wordBreak: 'break-all' }} type="warning">
{record.value}
</Text>{' '}
</>
),
onOk() {
request
.get(
`${config.apiPrefix}cookies/${record._id}/${
record.status === Status. ? 'enable' : 'disable'
}`,
{
data: { _id: record._id },
},
)
.then((data: any) => {
if (data.code === 200) {
notification.success({
message: `${
record.status === Status. ? '启用' : '禁用'
}成功`,
});
const newStatus =
record.status === Status. ? Status.未获取 : Status.已禁用;
const result = [...value];
result.splice(index, 1, {
...record,
status: newStatus,
});
setValue(result);
} else {
notification.error({
message: data,
});
}
});
},
onCancel() {
console.log('Cancel');
},
});
};
const addCookie = () => {
setEditedCookie(null as any);
setIsModalVisible(true);
};
const editCookie = (record: any, index: number) => {
setEditedCookie(record.cookie);
setEditedCookie(record);
setIsModalVisible(true);
};
@@ -210,20 +291,24 @@ const Config = () => {
title: '确认删除',
content: (
<>
Cookie <Text type="warning">{record.cookie}</Text>
Cookie{' '}
<Text style={{ wordBreak: 'break-all' }} type="warning">
{record.value}
</Text>{' '}
</>
),
onOk() {
request
.delete(`${config.apiPrefix}cookie`, {
data: { cookie: record.cookie },
})
.delete(`${config.apiPrefix}cookies/${record._id}`)
.then((data: any) => {
if (data.code === 200) {
notification.success({
message: '删除成功',
});
getCookies();
const result = [...value];
result.splice(index, 1);
setValue(result);
} else {
notification.error({
message: data,
@@ -240,10 +325,53 @@ const Config = () => {
const handleCancel = (needUpdate?: boolean) => {
setIsModalVisible(false);
if (needUpdate) {
getCookies();
getCookieDetail(editedCookie);
}
};
const getCookieDetail = (cookie: any) => {
request
.get(`${config.apiPrefix}cookies/${cookie._id}`)
.then((data: any) => {
const index = value.findIndex((x) => x._id === cookie._id);
const result = [...value];
result.splice(index, 1, {
...cookie,
...data.data,
});
setValue(result);
})
.finally(() => setLoading(false));
};
const components = {
body: {
row: DragableBodyRow,
},
};
const moveRow = useCallback(
(dragIndex, hoverIndex) => {
const dragRow = value[dragIndex];
const newData = [...value];
newData.splice(dragIndex, 1);
newData.splice(hoverIndex, 0, dragRow);
setValue([...newData]);
request
.put(`${config.apiPrefix}cookies/${dragRow._id}/move`, {
data: { fromIndex: dragIndex, toIndex: hoverIndex },
})
.then((data: any) => {
if (data.code !== 200) {
notification.error({
message: data,
});
}
});
},
[value],
);
useEffect(() => {
if (document.body.clientWidth < 768) {
setWdith('auto');
@@ -283,15 +411,24 @@ const Config = () => {
height: '100vh',
}}
>
<Table
columns={columns}
pagination={false}
dataSource={value}
rowKey="pin"
size="middle"
bordered
scroll={{ x: 768 }}
/>
<DndProvider backend={HTML5Backend}>
<Table
columns={columns}
pagination={false}
dataSource={value}
rowKey="value"
size="middle"
bordered
scroll={{ x: 768 }}
components={components}
onRow={(record, index) => {
return {
index,
moveRow,
} as any;
}}
/>
</DndProvider>
<CookieModal
visible={isModalVisible}
handleCancel={handleCancel}
+13 -13
View File
@@ -8,14 +8,14 @@ const CookieModal = ({
handleCancel,
visible,
}: {
cookie?: string;
cookie?: any;
visible: boolean;
handleCancel: (needUpdate?: boolean) => void;
}) => {
const [form] = Form.useForm();
const handleOk = async (values: any) => {
const cookies = values.cookie
const cookies = values.value
.split('\n')
.map((x: any) => x.trim().replace(/\s/g, ''));
let flag = false;
@@ -30,10 +30,8 @@ const CookieModal = ({
return;
}
const method = cookie ? 'put' : 'post';
const payload = cookie
? { cookie: cookies[0], oldCookie: cookie }
: { cookies };
const { code, data } = await request[method](`${config.apiPrefix}cookie`, {
const payload = cookie ? { value: cookies[0], _id: cookie._id } : cookies;
const { code, data } = await request[method](`${config.apiPrefix}cookies`, {
data: payload,
});
if (code === 200) {
@@ -49,11 +47,7 @@ const CookieModal = ({
};
useEffect(() => {
if (cookie) {
form.setFieldsValue({ cookie });
} else {
form.resetFields();
}
form.resetFields();
}, [cookie]);
return (
@@ -74,9 +68,15 @@ const CookieModal = ({
onCancel={() => handleCancel()}
destroyOnClose
>
<Form form={form} layout="vertical" name="form_in_modal" preserve={false}>
<Form
form={form}
layout="vertical"
name="form_in_modal"
preserve={false}
initialValues={cookie}
>
<Form.Item
name="cookie"
name="value"
rules={[
{ required: true, message: '请输入Cookie' },
{
+16 -4
View File
@@ -169,7 +169,11 @@ const Crontab = () => {
title: '确认删除',
content: (
<>
<Text type="warning">{record.name}</Text>
{' '}
<Text style={{ wordBreak: 'break-all' }} type="warning">
{record.name}
</Text>{' '}
</>
),
onOk() {
@@ -201,7 +205,11 @@ const Crontab = () => {
title: '确认运行',
content: (
<>
<Text type="warning">{record.name}</Text>
{' '}
<Text style={{ wordBreak: 'break-all' }} type="warning">
{record.name}
</Text>{' '}
</>
),
onOk() {
@@ -236,7 +244,11 @@ const Crontab = () => {
content: (
<>
{record.status === CrontabStatus.disabled ? '启用' : '禁用'}
<Text type="warning">{record.name}</Text>
{' '}
<Text style={{ wordBreak: 'break-all' }} type="warning">
{record.name}
</Text>{' '}
</>
),
onOk() {
@@ -415,7 +427,7 @@ const Crontab = () => {
defaultPageSize: 20,
}}
dataSource={value}
rowKey="pin"
rowKey="_id"
size="middle"
bordered
scroll={{ x: 768 }}
+8 -2
View File
@@ -3,6 +3,12 @@ import { Modal, notification, Input, Form } from 'antd';
import { request } from '@/utils/http';
import config from '@/utils/config';
enum CrontabStatus {
'running',
'idle',
'disabled',
}
const CronLogModal = ({
cron,
handleCancel,
@@ -12,14 +18,14 @@ const CronLogModal = ({
visible: boolean;
handleCancel: () => void;
}) => {
const [value, setValue] = useState<string>('运行中...');
const [value, setValue] = useState<string>('启动中...');
const [logTimer, setLogTimer] = useState<any>();
const getCronLog = () => {
request
.get(`${config.apiPrefix}crons/${cron._id}/log`)
.then((data: any) => {
setValue(data.data);
setValue(data.data || '暂无日志');
});
};