Skip to content

Commit e368067

Browse files
committed
feat: 新增新建扫描页面
1 parent 8a75d05 commit e368067

File tree

11 files changed

+385
-42
lines changed

11 files changed

+385
-42
lines changed

src/App/routers/routers.tsx

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ import GlobalReverseLink from '@/pages/ReverseLink';
3636
import { ReverseLinkServer } from '@/pages/ReverseLinkServer/ReverseLinkServer';
3737
import ApiOutlinedIcon from '@/assets/menu/ApiOutlinedIcon';
3838
import CodecEntry from '@/pages/Codec';
39+
import SpecialTask from '@/pages/SpecialTask';
3940
import CreateTask from '@/pages/CreateTask';
4041

4142
// 继承路由接口,增加name字段
@@ -64,12 +65,20 @@ const routers: RouteObjectRootMy[] = [
6465
icon: <TaskCenterIcon />,
6566
children: [
6667
{
67-
path: 'create-task',
68-
key: 'create-task',
69-
name: '新建任务',
68+
path: 'new-create-task',
69+
key: 'new-create-task',
70+
name: '新建扫描',
7071
element: <CreateTask />,
7172
hidden: false,
72-
parentpath: '/task/create-task',
73+
parentpath: '/task/new-create-task',
74+
},
75+
{
76+
path: 'special-task',
77+
key: 'special-task',
78+
name: '专项扫描',
79+
element: <SpecialTask />,
80+
hidden: false,
81+
parentpath: '/task/special-task',
7382
},
7483
{
7584
path: 'task-list',

src/apis/task/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ type TGetAnalysisScriptReponse = Partial<{
5858
tags: string[];
5959
script_name: string;
6060
target: string[];
61+
// prompt_args: Record<string, string>;
6162
}>;
6263

6364
type TNodeListRequest = Partial<{

src/pages/CreateTask/CreateTask.tsx

Lines changed: 307 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,50 +1,324 @@
1-
import { useMemo, type FC } from 'react';
1+
import { useRef, type FC } from 'react';
22

3+
import { Button, Form, Input, message, Radio, Spin } from 'antd';
4+
import { ChunkUpload } from '@/compoments';
5+
import { AddSelectSearch } from '../TaskScript/compoment/AddSelectSearch';
36
import { useRequest, useSafeState } from 'ahooks';
4-
import { getAnalysisScript } from '@/apis/task';
5-
import { Spin } from 'antd';
6-
import { generateUniqueId } from '@/utils';
7-
import { TaskScriptCard, type TTaskScriptCard } from './TaskScirptCard';
7+
import {
8+
getAnalysisScript,
9+
getNodeList,
10+
getScriptTaskGroup,
11+
getTaskStream,
12+
postTaskStart,
13+
} from '@/apis/task';
14+
import type { TScriptGrounpList } from '../TaskScript/compoment/CreateTaskItems';
15+
import dayjs from 'dayjs';
16+
import { useNavigate } from 'react-router-dom';
17+
18+
const { Item } = Form;
19+
const scanList = [
20+
{
21+
targetScriptName: '端口漏洞威胁',
22+
label: 'IP扫描',
23+
value: 'ip',
24+
script_type: 'portAndVulScan',
25+
},
26+
{
27+
targetScriptName: '域名漏洞威胁',
28+
label: '域名扫描',
29+
value: 'domain',
30+
script_type: 'subdomain_scan',
31+
},
32+
];
833

934
const CreateTask: FC = () => {
10-
const [taskScriptList, setTaskScriptList] = useSafeState<
11-
TTaskScriptCard['items'][]
12-
>([]);
35+
const [form] = Form.useForm();
36+
const navigate = useNavigate();
37+
38+
const scriptGroupListRef = useRef<TScriptGrounpList>();
39+
const [targetPlaceholder, setTargetPlaceholder] = useSafeState('请输入');
40+
41+
const onSubmit = async () => {
42+
const resultForm = await form.validateFields();
43+
const findTaskScriptItems: any = taskScriptList?.find(
44+
(items) => items.key === resultForm.scanMode,
45+
);
46+
const targetValues = {
47+
params: {
48+
report_name: resultForm.params.report_name,
49+
target: resultForm.params.target,
50+
execution_node: '1',
51+
mode: 'syn+tcp',
52+
'preset-protes': ['all'],
53+
ports: '1-65535',
54+
...findTaskScriptItems?.prompt_args,
55+
},
56+
task_id: `[${resultForm.params.report_name}]-[${dayjs().format('M月DD日')}]`,
57+
task_group: resultForm.task_group,
58+
script_type: findTaskScriptItems?.script_type,
59+
script_name: findTaskScriptItems?.script_name,
60+
scanner: scannerDataList?.length
61+
? [
62+
scannerDataList.reduce((min, cur) =>
63+
(cur?.size ?? Infinity) < (min?.size ?? Infinity)
64+
? cur
65+
: min,
66+
)?.name as string,
67+
]
68+
: [],
69+
sched_type: 1,
70+
concurrent: 20,
71+
task_type: 'batch-invoking-script',
72+
enable_sched: false,
73+
};
74+
75+
await AddTaskRunAsync(targetValues);
76+
};
77+
78+
const { run: TaskStearmRun } = useRequest(getTaskStream, {
79+
manual: true,
80+
onError: () => message.error('加入实时更新失败'),
81+
});
82+
83+
const { runAsync: AddTaskRunAsync, loading: addLoading } = useRequest(
84+
postTaskStart,
85+
{
86+
manual: true,
87+
onSuccess: async ({ data }) => {
88+
message.success('创建成功');
89+
await TaskStearmRun(data.id);
90+
navigate('/task/task-list', { replace: true });
91+
},
92+
onError: (err) => {
93+
message.destroy();
94+
message.error(`错误: ${err.message}`);
95+
},
96+
},
97+
);
1398

1499
// 获取脚本列表
15-
const { loading: scriptLoading, refreshAsync } = useRequest(
16-
async (script_name: string) => {
17-
const result = await getAnalysisScript({ script_name });
100+
const { data: taskScriptList, loading } = useRequest(
101+
async () => {
102+
const result = await getAnalysisScript();
18103
const {
19104
data: { list },
20105
} = result;
21-
const resultList =
22-
list?.map((it) => ({ isCopy: false, ...it })) ?? [];
23-
setTaskScriptList(resultList);
24-
return resultList;
106+
107+
const scanMap = new Map(
108+
scanList.map((item) => [item.targetScriptName, item.value]),
109+
);
110+
111+
const targetScriptNameList = list
112+
.filter(
113+
(item): item is typeof item & { script_name: string } =>
114+
typeof item.script_name === 'string' &&
115+
[...scanMap.keys()].some((key) =>
116+
item.script_name?.includes(key),
117+
),
118+
)
119+
.map((item) => {
120+
const matchedKey = [...scanMap.keys()].find((key) =>
121+
item.script_name.includes(key),
122+
)!;
123+
124+
return {
125+
...item,
126+
key: scanMap.get(matchedKey)!,
127+
};
128+
});
129+
130+
return targetScriptNameList;
131+
},
132+
{
133+
onSuccess: (val) => {
134+
const resultFormTargetPlaceholder =
135+
val?.find((items) => items.key === 'ip')?.description ??
136+
'请输入';
137+
setTargetPlaceholder(resultFormTargetPlaceholder);
138+
},
25139
},
26140
);
27141

28-
const taskScriptRender = useMemo(() => {
29-
return (
30-
<div className="grid grid-cols-3 gap-4">
31-
{taskScriptList?.map((items) => {
32-
return (
33-
<TaskScriptCard
34-
key={generateUniqueId()}
35-
items={items}
36-
refreshAsync={refreshAsync}
37-
/>
38-
);
39-
})}
40-
</div>
41-
);
42-
}, [taskScriptList]);
142+
// 获取 启动脚本任务 任务组参数
143+
const { data: scriptTaskGroupData, loading: scriptTaskGroupLoading } =
144+
useRequest(async () => {
145+
const result = await getScriptTaskGroup();
146+
const {
147+
data: { list },
148+
} = result;
149+
150+
const resultList = list?.map((it) => ({
151+
value: it.name,
152+
label: it.name,
153+
}));
154+
return resultList ?? [];
155+
});
156+
157+
// 获取节点 请求
158+
const { data: scannerDataList } = useRequest(async () => {
159+
const result = await getNodeList();
160+
const {
161+
data: { list },
162+
} = result;
163+
164+
const targetNodeList = list?.map((it) => ({
165+
name: it?.node_id,
166+
size: it?.task_running,
167+
date: it?.updated_at
168+
? dayjs(new Date().getTime()).unix() - it.updated_at
169+
: '-',
170+
}));
171+
return targetNodeList ?? [];
172+
});
43173

44174
return (
45-
<div className="p-4">
46-
<Spin spinning={scriptLoading}>{taskScriptRender}</Spin>
47-
</div>
175+
<Spin spinning={loading}>
176+
<div className="flex justify-center mt-10">
177+
<div className="flex items-center justify-center w-1/2">
178+
<Form
179+
form={form}
180+
layout="vertical"
181+
className="w-full"
182+
initialValues={{ scanMode: 'ip' }}
183+
onValuesChange={(changedValues) => {
184+
if (changedValues.scanMode) {
185+
const resultFormTargetPlaceholder =
186+
taskScriptList?.find(
187+
(items) =>
188+
items.key ===
189+
changedValues.scanMode,
190+
)?.description ?? '请输入';
191+
192+
setTargetPlaceholder(
193+
resultFormTargetPlaceholder,
194+
);
195+
}
196+
}}
197+
>
198+
<Item
199+
label="报告名称"
200+
name={['params', 'report_name']}
201+
rules={[
202+
{
203+
message: '请输入报告名称',
204+
required: true,
205+
},
206+
]}
207+
>
208+
<Input placeholder="请输入..." />
209+
</Item>
210+
211+
<Item
212+
label="所属任务组"
213+
name="task_group"
214+
rules={[
215+
{
216+
message: '请选择所属任务组',
217+
required: true,
218+
},
219+
]}
220+
>
221+
<AddSelectSearch
222+
scriptGroupListRef={scriptGroupListRef}
223+
scriptGroupList={scriptTaskGroupData}
224+
loading={scriptTaskGroupLoading}
225+
/>
226+
</Item>
227+
228+
<Item
229+
name="scanMode"
230+
label="扫描模式"
231+
layout="horizontal"
232+
>
233+
<Radio.Group
234+
optionType="button"
235+
buttonStyle="solid"
236+
options={scanList}
237+
/>
238+
</Item>
239+
240+
<Item noStyle name="param_files" />
241+
242+
<Item noStyle dependencies={[]}>
243+
{({ setFieldValue }) => {
244+
return (
245+
<Item
246+
label="扫描目标"
247+
name={['params', 'target']}
248+
rules={[
249+
{
250+
required: true,
251+
message: '请输入或上传扫描目标',
252+
},
253+
]}
254+
extra={
255+
<div className="flex items-center font-normal text-xs color-[#85899E]">
256+
可将TXT、Excel文件拖入框内或
257+
<ChunkUpload
258+
url="/material/files"
259+
chunkSize={2}
260+
accept=".txt"
261+
maxCount={1}
262+
encryptionKey="param_files"
263+
onChange={(fileName) => {
264+
setFieldValue(
265+
[
266+
'params',
267+
'target',
268+
],
269+
fileName,
270+
);
271+
setFieldValue(
272+
'param_files',
273+
fileName,
274+
);
275+
}}
276+
>
277+
<Button type="link">
278+
点击此处
279+
</Button>
280+
</ChunkUpload>
281+
上传
282+
</div>
283+
}
284+
>
285+
<ChunkUpload
286+
url="/material/files"
287+
chunkSize={2}
288+
accept=".txt"
289+
childrenType="textArea"
290+
encryptionKey="param_files"
291+
setFieldValue={setFieldValue}
292+
maxCount={1}
293+
placeholder={targetPlaceholder}
294+
onChange={(fileName) => {
295+
setFieldValue(
296+
['params', 'target'],
297+
fileName,
298+
);
299+
setFieldValue(
300+
'param_files',
301+
fileName,
302+
);
303+
}}
304+
/>
305+
</Item>
306+
);
307+
}}
308+
</Item>
309+
<div className="flex justify-center">
310+
<Button
311+
onClick={onSubmit}
312+
type="primary"
313+
loading={addLoading}
314+
>
315+
开始执行
316+
</Button>
317+
</div>
318+
</Form>
319+
</div>
320+
</div>
321+
</Spin>
48322
);
49323
};
50324

0 commit comments

Comments
 (0)