Commit 4c0028c8 by zhaochengxiang

采集调度

parent e2aaf708
...@@ -63,7 +63,14 @@ export default class App extends React.Component { ...@@ -63,7 +63,14 @@ export default class App extends React.Component {
<Route path={'/center-home/view/asset-map'} component={Map} exact /> <Route path={'/center-home/view/asset-map'} component={Map} exact />
<Route path={'/center-home/view/asset-manage'} component={AssetManage} exact /> <Route path={'/center-home/view/asset-manage'} component={AssetManage} exact />
<Route path={'/center-home/view/asset-browse'} component={AssetBrowse} exact /> <Route path={'/center-home/view/asset-browse'} component={AssetBrowse} exact />
<Route path={'/center-home/view/asset-recycle'} component={AssetRecycle} exact /> <Route path={'/center-home/view/asset-recycle'} component={AssetRecycle} exact />
<Route path={'/center-home/menu/datasource-manage'} component={DatasourceManage} exact />
<Route path={'/center-home/menu/data-model'} component={Model} exact />
<Route path={'/center-home/menu/asset-map'} component={Map} exact />
<Route path={'/center-home/menu/asset-manage'} component={AssetManage} exact />
<Route path={'/center-home/menu/asset-browse'} component={AssetBrowse} exact />
<Route path={'/center-home/menu/asset-recycle'} component={AssetRecycle} exact />
</Switch> </Switch>
</Router> </Router>
</React.Fragment> </React.Fragment>
......
...@@ -74,4 +74,28 @@ export function* getTaskStates(payload) { ...@@ -74,4 +74,28 @@ export function* getTaskStates(payload) {
export function* getTaskTracerByStateId(payload) { export function* getTaskTracerByStateId(payload) {
return yield call(service.getTaskTracerByStateId, payload); return yield call(service.getTaskTracerByStateId, payload);
}
export function* deleteSchedule(payload) {
return yield call(service.deleteSchedule, payload);
}
export function* getScheduleForm(payload) {
return yield call(service.getScheduleForm, payload);
}
export function* getScheduleById(payload) {
return yield call(service.getScheduleById, payload);
}
export function* getScheduleListByTaskId(payload) {
return yield call(service.getScheduleListByTaskId, payload);
}
export function* saveAndStartSchedule(payload) {
return yield call(service.saveAndStartSchedule, payload);
}
export function* getAllTaskProgress() {
return yield call(service.getAllTaskProgress);
} }
\ No newline at end of file
...@@ -72,3 +72,27 @@ export function getTaskTracerByStateId(payload) { ...@@ -72,3 +72,27 @@ export function getTaskTracerByStateId(payload) {
return GetJSON("/metadataharvester/task/getTaskTracerByStateId", payload); return GetJSON("/metadataharvester/task/getTaskTracerByStateId", payload);
} }
export function deleteSchedule(payload) {
return Delete("/metadataharvester/schedule/deleteSchedule", payload);
}
export function getScheduleForm(payload) {
return GetJSON("/metadataharvester/schedule/getScheduleForm", payload);
}
export function getScheduleById(payload) {
return GetJSON("/metadataharvester/schedule/getTaskById", payload);
}
export function getScheduleListByTaskId(payload) {
return PostJSON("/metadataharvester/schedule/getTaskListByTargetConfId", payload);
}
export function saveAndStartSchedule(payload) {
return PostJSON("/metadataharvester/schedule/saveAndStartSchedule", payload);
}
export function getAllTaskProgress() {
return GetJSON("/metadataharvester/redis/getAllTaskProgress");
}
...@@ -119,7 +119,7 @@ const FilterElement = (props) => { ...@@ -119,7 +119,7 @@ const FilterElement = (props) => {
return ( return (
<Col className='mb-3' key={_index} md={6}> <Col className='mb-3' key={_index} md={6}>
<div className='d-flex'> <div className='d-flex'>
<Checkbox checked={ selectedKeys.indexOf(element.id||'')!==-1 } value={element.id||''} onChange={onCheckChange} > <Checkbox checked={ selectedKeys.indexOf(element.id||'')!==-1 } value={element.id||''} onChange={onCheckChange} disabled={(element.name||'')==='中文名称'} >
</Checkbox> </Checkbox>
<Typography.Paragraph className='ml-1' title={element.name||''} ellipsis> <Typography.Paragraph className='ml-1' title={element.name||''} ellipsis>
{element.name||''} {element.name||''}
......
import React, { useEffect, useState } from 'react';
import { Modal, Select, Form, Input, Divider, Space, Button, Upload } from 'antd';
import { UploadOutlined } from '@ant-design/icons';
import { dispatch } from '../../../../model';
import { showMessage } from '../../../../util';
const { Option } = Select;
const ScheduleAction = (props) => {
const { action, id, form, tid } = props;
const [ schedule, setSchedule ] = useState({});
useEffect(() => {
reset();
if (action === 'add' && tid) {
getScheduleForm();
} else {
getScheduleById();
}
//eslint-disable-next-line react-hooks/exhaustive-deps
}, [ action, id])
const getScheduleForm = () => {
dispatch({
type: 'datasource.getScheduleForm',
payload: {
targetConfId: tid
},
callback: data => {
setSchedule(data||{});
}
});
}
const getScheduleById = () => {
dispatch({
type: 'datasource.getScheduleById',
payload: {
id
},
callback: data => {
setSchedule(data||{});
}
})
}
const reset =() => {
form.resetFields();
}
const formItemLayout = {
labelCol: {
xs: { span: 24 },
sm: { span: 6 },
},
wrapperCol: {
xs: { span: 24 },
sm: { span: 16 },
},
};
return (
<Form {...formItemLayout} form={form}>
{
schedule && (schedule.targetParameters||[]).map((item, index) => {
return (
<Form.Item
label={item.cnName||''}
name={item.name||''}
key={index}
rules={[{ required: item.required, message: '必填项'}]}
>
{ ( item.show ? <Input placeholder={item.explain||''} /> : <Input.Password placeholder={item.explain||''} visibilityToggle={false} /> ) }
</Form.Item>
)
})
}
</Form>
);
}
export default ScheduleAction;
\ No newline at end of file
import React, { useEffect, useState } from 'react';
import { Table, Space, Button, Tooltip, Modal, Form } from 'antd';
import { EditOutlined, ReconciliationOutlined, DeleteOutlined } from '@ant-design/icons';
import ScheduleAction from './ScheduleAction';
import { dispatch } from '../../../../model';
import { showMessage } from '../../../../util';
const ScheduleCURDModal = (props) => {
const { visible, onCancel, id } = props;
const [ schedules, setSchedules ] = useState([]);
const [ loading, setLoading ] = useState(false);
const [ action, setAction ] = useState('');
const [ currentSchedule, setCurrentSchedule ] = useState('');
const [ step, setStep ] = useState(0);
const [ confirmLoading, setConfirmLoading ] = useState(false);
const [modal, contextHolder] = Modal.useModal();
const [form] = Form.useForm();
useEffect(() => {
if (visible) {
getSchedules();
}
}, [ visible ])
const columns = [
{
title: '序号',
dataIndex: 'key',
render: (_, __, index) => {
return (index+1).toString();
},
width: 60,
},
{
title: '调度名称',
dataIndex: 'taskName',
width: 180,
ellipsis: true,
},
{
title: '是否开启',
dataIndex: 'status',
width: 120,
render: (text, _, __) => {
return (text==='1')?'是':'否';
}
},
{
title: '调度时间',
dataIndex: 'cronDesc',
width: 180,
ellipsis: true,
},
{
title: '描述',
dataIndex: 'remark',
ellipsis: true,
},
{
title: '操作',
key: 'action',
width: 120,
render: (_,record) => {
return (
<Space size='small'>
<Tooltip placement='bottom' title={'修改'}>
<Button icon={<EditOutlined />} size='small' onClick={() => { editItem(record); }} />
</Tooltip>
<Tooltip placement='bottom' title={'详情'}>
<Button icon={<ReconciliationOutlined />} size='small' onClick={() => { detailItem(record); }} />
</Tooltip>
<Tooltip placement='bottom' title={'删除'}>
<Button icon={<DeleteOutlined />} size='small' onClick={() => { deleteItem(record); }} />
</Tooltip>
</Space>
)
}
}
];
const getSchedules = () => {
setLoading(true);
dispatch({
type: 'datasource.getScheduleListByTaskId',
payload: {
params: {
targetConfId: id
}
},
callback: data => {
setSchedules(data?.datas||[]);
setLoading(false);
},
error: () => {
setLoading(false);
}
})
}
const editItem = (record) => {
setStep(1);
setAction('edit');
setCurrentSchedule(record);
}
const detailItem = (record) => {
setStep(1);
setAction('detail');
setCurrentSchedule(record);
}
const deleteItem = (record) => {
modal.confirm({
title: '提示!',
content: '您确定要删除该调度吗?',
onOk: () => {
dispatch({
type: 'datasource.deleteSchedule',
payload: {
params: {
id: record.id
}
},
callback: () => {
showMessage('success', '模版调度成功');
getSchedules();
}
})
}
});
}
const onAddClick = () => {
setStep(1);
setAction('add');
}
const cancel = () => {
reset();
onCancel && onCancel(false);
}
const reset = () => {
setStep(0);
setCurrentSchedule({});
setConfirmLoading(false);
}
const onActionChange = (data) => {
getSchedules();
}
const prev = () => {
setStep(step-1);
}
const save = async () => {
// try {
// const row = await form.validateFields();
// const newTemplateData = {...currentTemplate, ...row};
// setConfirmLoading(true);
// dispatchLatest({
// type: 'datamodel.saveTemplate',
// payload: {
// data: newTemplateData
// },
// callback: () => {
// setConfirmLoading(false);
// reset();
// onCancel && onCancel(true);
// },
// error: () => {
// setConfirmLoading(false);
// }
// })
// } catch (errInfo) {
// console.log('Validate Failed:', errInfo);
// }
}
let title = '';
if (step === 0) {
title = '调度详情';
}
if (step === 1) {
if (action === 'add') {
title = '新增调度';
} else if (action === 'edit') {
title = '调度编辑';
} else if (action === 'detail') {
title = '调度详情';
}
}
let footer = null;
if (step === 0) {
footer = [
<Button
key="0"
onClick={cancel}
>
取消
</Button>,
]
} else if (step === 1) {
if (action === 'detail') {
footer = [
<Button
key="0"
onClick={prev}
>
返回
</Button>,
]
} else {
footer = [
<Button
key="0"
onClick={prev}
>
返回
</Button>,
<Button
key="1"
type="primary"
loading={confirmLoading}
onClick={save}
>
保存
</Button>
]
}
}
return (
<Modal
forceRender
className='schedule-curd-modal'
visible={visible}
title={title}
width={1000}
maskClosable={false}
onCancel={cancel}
footer={footer}
>
{
step === 0 && <>
<div className='d-flex mb-3' style={{ alignItems: 'center' }}>
<Button type="primary" onClick={onAddClick} style={{ marginLeft: 'auto' }} >新增调度</Button>
</div>
<Table
loading={loading}
columns={columns}
rowKey={'id'}
dataSource={schedules||[]}
pagination={false}
sticky
/>
</>
}
{
step === 1 && <ScheduleAction
action={action}
id={currentSchedule.id}
form={form}
tid={id}
/>
}
{ contextHolder }
</Modal>
);
}
export default ScheduleCURDModal;
\ No newline at end of file
import React, { useContext } from 'react'; import React, { useContext } from 'react';
import { Card, Typography, Space, Button, Tooltip } from 'antd'; import { Card, Typography, Space, Button, Tooltip } from 'antd';
import { EditOutlined, DeleteOutlined, DatabaseOutlined, FileOutlined } from '@ant-design/icons'; import { EditOutlined, DeleteOutlined, DatabaseOutlined, FileOutlined, ScheduleOutlined } from '@ant-design/icons';
import { DatasourceContext } from './ContextManager'; import { DatasourceContext } from './ContextManager';
import './TaskItem.less'; import './TaskItem.less';
...@@ -8,7 +8,7 @@ import './TaskItem.less'; ...@@ -8,7 +8,7 @@ import './TaskItem.less';
const TaskItem = (props) => { const TaskItem = (props) => {
const { data } = props; const { data } = props;
const { onStartTask, onLogTask, onEditTask, onDeleteTask } = useContext(DatasourceContext); const { onStartTask, onLogTask, onEditTask, onDeleteTask, onScheduleShow } = useContext(DatasourceContext);
return ( return (
<Card className='task-item'> <Card className='task-item'>
...@@ -25,8 +25,11 @@ const TaskItem = (props) => { ...@@ -25,8 +25,11 @@ const TaskItem = (props) => {
</div> </div>
<div className='d-flex mt-2'> <div className='d-flex mt-2'>
<Space style={{ marginLeft: 'auto' }}> <Space style={{ marginLeft: 'auto' }}>
<Tooltip placement='bottom' title='定时调度'>
<Button icon={<ScheduleOutlined />} size='small' onClick={() => { onScheduleShow && onScheduleShow(data); }} />
</Tooltip>
<Tooltip placement='bottom' title='抽取'> <Tooltip placement='bottom' title='抽取'>
<Button icon={<DatabaseOutlined />} size='small' onClick={() => { onStartTask && onStartTask(data); }} /> <Button icon={<DatabaseOutlined />} size='small' onClick={() => { onStartTask && onStartTask(data); }} />
</Tooltip> </Tooltip>
<Tooltip placement='bottom' title='日志'> <Tooltip placement='bottom' title='日志'>
<Button icon={<FileOutlined />} size='small' onClick={() => { onLogTask && onLogTask(data); }} /> <Button icon={<FileOutlined />} size='small' onClick={() => { onLogTask && onLogTask(data); }} />
......
...@@ -3,6 +3,7 @@ import { Space, Select, Button, Modal, Cascader } from 'antd'; ...@@ -3,6 +3,7 @@ import { Space, Select, Button, Modal, Cascader } from 'antd';
import DatasourceList from './Component/DatasourceList'; import DatasourceList from './Component/DatasourceList';
import UpdateDatasourceModal from './Component/UpdateDatasourceModal'; import UpdateDatasourceModal from './Component/UpdateDatasourceModal';
import ScheduleCURDModal from './Component/ScheduleCURDModal';
import TaskLogsModal from './Component/TaskLogsModal'; import TaskLogsModal from './Component/TaskLogsModal';
import TaskLogModal from './Component/TaskLogModal'; import TaskLogModal from './Component/TaskLogModal';
import UpdateTaskModal from './Component/UpdateTaskModal'; import UpdateTaskModal from './Component/UpdateTaskModal';
...@@ -31,6 +32,7 @@ const DatasourceManage = (props) => { ...@@ -31,6 +32,7 @@ const DatasourceManage = (props) => {
const [ loadingDatasources, setLoadingDatasources ] = useState(false); const [ loadingDatasources, setLoadingDatasources ] = useState(false);
const [ updateDatasourceModalVisible, setUpdateDatasourceModalVisible ] = useState(false); const [ updateDatasourceModalVisible, setUpdateDatasourceModalVisible ] = useState(false);
const [ updateDatasourceModalAction, setUpdateDatasourceModalAction ] = useState(''); const [ updateDatasourceModalAction, setUpdateDatasourceModalAction ] = useState('');
const [ scheduleCURDModalVisible, setScheduleCURDModalVisible ] = useState(false);
const [ updateTaskModalVisible, setUpdateTaskModalVisible ] = useState(false); const [ updateTaskModalVisible, setUpdateTaskModalVisible ] = useState(false);
const [ updateTaskModalAction, setUpdateTaskModalAction ] = useState(''); const [ updateTaskModalAction, setUpdateTaskModalAction ] = useState('');
const [ taskLogsModalVisible, setTaskLogsModalVisible ] = useState(false); const [ taskLogsModalVisible, setTaskLogsModalVisible ] = useState(false);
...@@ -193,6 +195,10 @@ const DatasourceManage = (props) => { ...@@ -193,6 +195,10 @@ const DatasourceManage = (props) => {
}); });
} }
const onScheduleCURDModalCancel = (refresh = false) => {
setScheduleCURDModalVisible(false);
}
const onUpdateDatasourceModalCancel = (refresh = false) => { const onUpdateDatasourceModalCancel = (refresh = false) => {
setUpdateDatasourceModalVisible(false); setUpdateDatasourceModalVisible(false);
refresh && getAllDatasources(); refresh && getAllDatasources();
...@@ -204,6 +210,11 @@ const DatasourceManage = (props) => { ...@@ -204,6 +210,11 @@ const DatasourceManage = (props) => {
setUpdateTaskModalVisible(true); setUpdateTaskModalVisible(true);
} }
const scheduleShow = (task) => {
setCurrentTaskId(task.id);
setScheduleCURDModalVisible(true);
}
const startTask = (task) => { const startTask = (task) => {
modal.confirm({ modal.confirm({
title: '是否执行该任务?', title: '是否执行该任务?',
...@@ -272,6 +283,7 @@ const DatasourceManage = (props) => { ...@@ -272,6 +283,7 @@ const DatasourceManage = (props) => {
return ( return (
<DatasourceContext.Provider value={{ <DatasourceContext.Provider value={{
refreshTasksSuccess: refreshTasksSuccess, refreshTasksSuccess: refreshTasksSuccess,
onScheduleShow: scheduleShow,
onStartTask: startTask, onStartTask: startTask,
onLogTask: logTask, onLogTask: logTask,
onEditTask: editTask, onEditTask: editTask,
...@@ -328,6 +340,12 @@ const DatasourceManage = (props) => { ...@@ -328,6 +340,12 @@ const DatasourceManage = (props) => {
/> />
</div> </div>
<ScheduleCURDModal
visible={scheduleCURDModalVisible}
id={currentTaskId}
onCancel={onScheduleCURDModalCancel}
/>
<TaskLogsModal <TaskLogsModal
visible={taskLogsModalVisible} visible={taskLogsModalVisible}
scope={selectedScope} scope={selectedScope}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment