初始化项目

This commit is contained in:
whyour
2021-03-14 22:06:27 +08:00
commit f1f8ece8a2
41 changed files with 3017 additions and 0 deletions
View File
+93
View File
@@ -0,0 +1,93 @@
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);
}).finally(() => setLoading(false));
};
const updateConfig = () => {
request
.post(`${config.apiPrefix}save`, {
data: { content: value, name: 'diy.sh' },
})
.then((data) => {
notification.success({
message: data.msg,
});
});
};
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="互助码"
loading={loading}
extra={[
<Button key="1" type="primary" onClick={updateConfig}>
</Button>,
]}
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',
theme: 'dracula',
readOnly: 'nocursor',
}}
onBeforeChange={(editor, data, value) => {
setValue(value);
}}
onChange={(editor, data, value) => {}}
/>
</PageContainer>
);
};
export default Crontab;
View File
+148
View File
@@ -0,0 +1,148 @@
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';
import QRCode from 'qrcode.react';
const Config = () => {
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/config`).then((data) => {
setValue(data);
}).finally(() => setLoading(false));
};
const updateConfig = () => {
request
.post(`${config.apiPrefix}save`, {
data: { content: value, name: 'config.sh' },
})
.then((data) => {
notification.success({
message: data.msg,
});
});
};
function sleep(time: number) {
return new Promise((resolve) => setTimeout(resolve, time));
}
const showQrCode = () => {
request.get(`${config.apiPrefix}qrcode`).then(async (data) => {
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);
});
};
const getCookie = async (modal: { destroy: () => void }) => {
for (let i = 0; i < 50; i++) {
const result = await request.get(`${config.apiPrefix}cookie`);
console.log(i, result);
if (result && result.cookie) {
notification.success({
message: 'Cookie获取成功',
});
modal.destroy();
Modal.success({
title: '获取Cookie成功',
content: <div>{result.cookie}</div>,
});
break;
}
await sleep(2000);
}
};
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="config.sh"
loading={loading}
extra={[
<Button key="1" type="primary" onClick={updateConfig}>
</Button>,
<Button key="2" type="primary" onClick={showQrCode}>
Cookie
</Button>,
]}
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',
theme: 'dracula',
}}
onBeforeChange={(editor, data, value) => {
setValue(value);
}}
onChange={(editor, data, value) => {}}
/>
</PageContainer>
);
};
export default Config;
View File
+190
View File
@@ -0,0 +1,190 @@
import React, { PureComponent, Fragment, useState, useEffect } from 'react';
import { Button, notification, Modal, Table, Tag, Space } from 'antd';
import config from '@/utils/config';
import { PageContainer } from '@ant-design/pro-layout';
import { request } from '@/utils/http';
import QRCode from 'qrcode.react';
const columns = [
{
title: '用户名',
dataIndex: 'pin',
key: 'pin',
},
{
title: '昵称',
dataIndex: 'nickname',
key: 'nickname',
},
{
title: '值',
dataIndex: 'cookie',
key: 'cookie',
},
{
title: '状态',
key: 'status',
dataIndex: 'status',
render: (text: string, record: any) => (
<Tag color="success">success</Tag>
),
},
{
title: '操作',
key: 'action',
render: (text: string, record: any) => (
<Space size="middle">
<a>Invite {record.name}</a>
<a>Delete</a>
</Space>
),
},
];
const data = [
{
key: '1',
name: 'John Brown',
age: 32,
address: 'New York No. 1 Lake Park',
tags: ['nice', 'developer'],
},
{
key: '2',
name: 'Jim Green',
age: 42,
address: 'London No. 1 Lake Park',
tags: ['loser'],
},
{
key: '3',
name: 'Joe Black',
age: 32,
address: 'Sidney No. 1 Lake Park',
tags: ['cool', 'teacher'],
},
];
const Config = () => {
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/config`).then((data) => {
setValue(data);
}).finally(() => setLoading(false));
};
const updateConfig = () => {
request
.post(`${config.apiPrefix}save`, {
data: { content: value, name: 'config.sh' },
})
.then((data) => {
notification.success({
message: data.msg,
});
});
};
function sleep(time: number) {
return new Promise((resolve) => setTimeout(resolve, time));
}
const showQrCode = () => {
request.get(`${config.apiPrefix}qrcode`).then(async (data) => {
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);
});
};
const getCookie = async (modal: { destroy: () => void }) => {
for (let i = 0; i < 50; i++) {
const result = await request.get(`${config.apiPrefix}cookie`);
console.log(i, result);
if (result && result.cookie) {
notification.success({
message: 'Cookie获取成功',
});
modal.destroy();
Modal.success({
title: '获取Cookie成功',
content: <div>{result.cookie}</div>,
});
break;
}
await sleep(2000);
}
};
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="Cookie管理"
loading={loading}
extra={[
<Button key="2" type="primary" onClick={showQrCode}>
Cookie
</Button>,
]}
header={{
style: {
padding: '4px 16px 4px 15px',
position: 'sticky',
top: 0,
left: 0,
zIndex: 20,
marginTop,
width,
marginLeft,
},
}}
style={{
height: '100vh',
}}
>
<Table columns={columns} pagination={{hideOnSinglePage: true}} dataSource={data} />
</PageContainer>
);
};
export default Config;
View File
+92
View File
@@ -0,0 +1,92 @@
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/crontab`).then((data) => {
setValue(data);
}).finally(() => setLoading(false));
};
const updateConfig = () => {
request
.post(`${config.apiPrefix}save`, {
data: { content: value, name: 'crontab.list' },
})
.then((data) => {
notification.success({
message: data.msg,
});
});
};
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="crontab.list"
loading={loading}
extra={[
<Button key="1" type="primary" onClick={updateConfig}>
</Button>,
]}
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',
theme: 'dracula',
}}
onBeforeChange={(editor, data, value) => {
setValue(value);
}}
onChange={(editor, data, value) => {}}
/>
</PageContainer>
);
};
export default Crontab;
+12
View File
@@ -0,0 +1,12 @@
.d2h-files-diff {
height: calc(100vh - 130px);
overflow: auto;
}
.d2h-code-side-linenumber {
position: relative;
}
.d2h-code-side-line {
padding: 0 0.5em;
}
+93
View File
@@ -0,0 +1,93 @@
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 { request } from '@/utils/http';
import ReactDiffViewer from 'react-diff-viewer';
import './index.less';
const Crontab = () => {
const [width, setWdith] = useState('100%');
const [marginLeft, setMarginLeft] = useState(0);
const [marginTop, setMarginTop] = useState(-72);
const [value, setValue] = useState('');
const [sample, setSample] = useState('');
const [loading, setLoading] = useState(true);
const getConfig = () => {
request.get(`${config.apiPrefix}config/config`).then((data) => {
setValue(data);
});
};
const getSample = () => {
setLoading(true);
request.get(`${config.apiPrefix}config/sample`).then((data) => {
setSample(data);
}).finally(() => setLoading(false));
};
useEffect(() => {
if (document.body.clientWidth < 768) {
setWdith('auto');
setMarginLeft(0);
setMarginTop(0);
} else {
setWdith('100%');
setMarginLeft(0);
setMarginTop(-72);
}
getConfig();
getSample();
}, []);
return (
<PageContainer
className="code-mirror-wrapper"
title="对比工具"
loading={loading}
header={{
style: {
padding: '4px 16px 4px 15px',
position: 'sticky',
top: 0,
left: 0,
zIndex: 20,
marginTop,
width,
marginLeft,
},
}}
style={{
height: '100vh',
}}
>
<ReactDiffViewer
styles={{ diffRemoved: {
overflowX: 'auto',
maxWidth: 300,
},
diffAdded: {
overflowX: 'auto',
maxWidth: 300,
},line: {
wordBreak: 'break-word',
}, }}
oldValue={value}
newValue={sample}
splitView={true}
leftTitle="config.sh"
rightTitle="config.sh.sample"
disableWordDiff={true}
/>
{/* <CodeDiff
style={{ height: 'calc(100vh - 72px)', overflowY: 'auto' }}
outputFormat="side-by-side"
oldStr={value}
newStr={sample}
/> */}
</PageContainer>
);
};
export default Crontab;
View File
+92
View File
@@ -0,0 +1,92 @@
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/diy`).then((data) => {
setValue(data);
}).finally(() => setLoading(false));
};
const updateConfig = () => {
request
.post(`${config.apiPrefix}save`, {
data: { content: value, name: 'diy.sh' },
})
.then((data) => {
notification.success({
message: data.msg,
});
});
};
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="diy.sh"
loading={loading}
extra={[
<Button key="1" type="primary" onClick={updateConfig}>
</Button>,
]}
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',
theme: 'dracula',
}}
onBeforeChange={(editor, data, value) => {
setValue(value);
}}
onChange={(editor, data, value) => {}}
/>
</PageContainer>
);
};
export default Crontab;
View File
+112
View File
@@ -0,0 +1,112 @@
import React, { PureComponent, Fragment, useState, useEffect } from 'react';
import { Button, notification, Modal, TreeSelect } 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 Log = () => {
const [width, setWdith] = useState('100%');
const [marginLeft, setMarginLeft] = useState(0);
const [marginTop, setMarginTop] = useState(-72);
const [title, setTitle] = useState('log');
const [value, setValue] = useState('请选择日志文件');
const [select, setSelect] = useState();
const [data, setData] = useState();
const [loading, setLoading] = useState(false);
const getConfig = () => {
request.get(`${config.apiPrefix}logs`).then((data) => {
setData(formatData(data.dirs) as any);
});
};
const formatData = (tree: any[]) => {
return tree.map(x => {
x.title = x.dirName;
x.value = x.dirName;
x.disabled = true;
x.children = x.files.map((y: string) => ({ title: y, key: y, value: y, parent: x.dirName }));
return x;
})
}
const getLog = (node: any) => {
setLoading(true);
request.get(`${config.apiPrefix}logs/${node.parent}/${node.value}`).then((data) => {
setValue(data);
}).finally(() => setLoading(false));
};
const onSelect = (value: any, node: any) => {
setSelect(value);
setTitle(node.parent);
getLog(node);
};
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={title}
loading={loading}
extra={[
<TreeSelect
style={{ width: 280 }}
value={select}
dropdownStyle={{ maxHeight: 400, overflow: 'auto' }}
treeData={data}
placeholder="请选择日志文件"
showSearch
key="title"
onSelect={onSelect}
/>
]}
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',
theme: 'dracula',
readOnly: 'nocursor',
}}
onBeforeChange={(editor, data, value) => {
setValue(value);
}}
onChange={(editor, data, value) => {}}
/>
</PageContainer>
);
};
export default Log;
+58
View File
@@ -0,0 +1,58 @@
.form {
position: absolute;
top: 45%;
left: 50%;
margin: -160px 0 0 -160px;
width: 320px;
height: 320px;
padding: 36px;
box-shadow: 0 0 100px rgba(0, 0, 0, 0.08);
button {
width: 100%;
}
p {
color: rgb(204, 204, 204);
text-align: center;
margin-top: 16px;
font-size: 12px;
display: flex;
justify-content: space-between;
}
}
.logo {
text-align: center;
cursor: pointer;
margin-bottom: 24px;
display: flex;
justify-content: center;
align-items: center;
img {
width: 40px;
margin-right: 8px;
}
span {
vertical-align: text-bottom;
font-size: 16px;
text-transform: uppercase;
display: inline-block;
font-weight: 700;
// color: @primary-color;
// .text-gradient();
}
}
.ant-spin-container,
.ant-spin-nested-loading {
height: 100%;
}
.footer {
position: absolute;
width: 100%;
bottom: 0;
}
+73
View File
@@ -0,0 +1,73 @@
import React, { Fragment, useEffect } from 'react';
import { Button, Row, Input, Form, notification } from 'antd';
import config from '@/utils/config';
import { history } from 'umi';
import styles from './index.less';
import { request } from '@/utils/http';
const FormItem = Form.Item;
const Login = () => {
const handleOk = (values: any) => {
request
.post(`${config.apiPrefix}auth`, {
data: {
username: values.username,
password: values.password,
},
})
.then((data) => {
if (data.err == 0) {
localStorage.setItem(config.authKey, 'true');
history.push('/cookie');
} else {
notification.open({
message: data.msg,
});
}
})
.catch(function (error) {
console.log(error);
});
};
useEffect(() => {
const isAuth = localStorage.getItem(config.authKey);
if (isAuth) {
history.push('/cookie');
}
}, [])
return (
<Fragment>
<div className={styles.form}>
<div className={styles.logo}>
<span>{config.siteName}</span>
</div>
<Form onFinish={handleOk}>
<FormItem
name="username"
rules={[{ required: true, message: '请输入用户名' }]}
hasFeedback
>
<Input placeholder="用户名" autoFocus/>
</FormItem>
<FormItem
name="password"
rules={[{ required: true, message: '请输入密码' }]}
hasFeedback
>
<Input type="password" placeholder="密码" />
</FormItem>
<Row>
<Button type="primary" htmlType="submit">
Sign in
</Button>
</Row>
</Form>
</div>
</Fragment>
);
};
export default Login;
View File
+84
View File
@@ -0,0 +1,84 @@
import React, { PureComponent, Fragment, useState, useEffect } from 'react';
import { Button, notification, Input, Form } 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 Password = () => {
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 handleOk = (values: any) => {
request
.post(`${config.apiPrefix}auth?t=${Date.now()}`, {
data: {
username: values.username,
password: values.password,
},
})
.then((data) => {
if (data.err == 0) {
localStorage.setItem(config.authKey, 'true');
} else {
notification.open({
message: data.msg,
});
}
})
.catch(function (error) {
console.log(error);
});
};
useEffect(() => {
if (document.body.clientWidth < 768) {
setWdith('auto');
setMarginLeft(0);
setMarginTop(0);
} else {
setWdith('100%');
setMarginLeft(0);
setMarginTop(-72);
}
}, []);
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',
}}
>
<Form onFinish={handleOk} style={{ padding: 20, background: '#fff', height: 'calc(100vh - 96px)' }}>
<Form.Item name="username" rules={[{ required: true, message: '请输入用户名' }]} hasFeedback style={{width:300}}>
<Input placeholder="用户名" autoFocus/>
</Form.Item>
<Form.Item name="password" rules={[{ required: true, message: '请输入密码' }]} hasFeedback style={{width:300}}>
<Input type="password" placeholder="密码" />
</Form.Item>
<Button type="primary" htmlType="submit">
</Button>
</Form>
</PageContainer>
);
};
export default Password;