소스 검색

作业管理和任务日志

Alkuttt 2 년 전
부모
커밋
022c2849f4

+ 3 - 0
.vscode/settings.json

@@ -0,0 +1,3 @@
+{
+  "compile-hero.disable-compile-files-on-did-save-code": true
+}

+ 6 - 3
src/index.js

@@ -4,18 +4,21 @@ import './index.css';
 import 'antd/dist/antd.min.css';
 import reportWebVitals from './reportWebVitals';
 import { BrowserRouter, Routes, Route } from 'react-router-dom';
+// eslint-disable-next-line
 import DatasourceView from './module/datasource/page/DatasourceView.jsx'
 import SyncTaskAdd from './module/datasource/component/SyncTaskAdd.jsx'
 import LogWatcher from './module/datasource/component/LogWatcher.jsx'
-
+import JobManagement from './module/workmgmt/page/JobManagement.jsx'
+import JobCreate from './module/workmgmt/component/JobCreate.jsx'
+import TaskLog from './module/tasklog/page/TaskLog';
 const root = ReactDOM.createRoot(document.getElementById('root'));
-
 root.render(
   <BrowserRouter>
     <Routes>
-      <Route path="/" element={<DatasourceView />} />
+      <Route path="/" element={<TaskLog />} />
       <Route path="sync" element={<SyncTaskAdd />} />
       <Route path="log" element={<LogWatcher />} />
+      <Route path="cre" element={<JobCreate />} />
     </Routes>
   </BrowserRouter>
 );

+ 0 - 1
src/module/datasource/component/StepThree.jsx

@@ -58,7 +58,6 @@ const StepThreeDiv = styled.div`
     overflow: hidden;
     white-space: nowrap;
 }
-  }
   .field__sync {
     background: #eef5fe;
   }

+ 239 - 0
src/module/tasklog/component/LogTable.jsx

@@ -0,0 +1,239 @@
+import { Button, Form, Input, Popconfirm, Table } from 'antd';
+import React, { useContext, useEffect, useRef, useState } from 'react';
+import styled from 'styled-components'
+import { Link } from 'react-router-dom';
+const EditableContext = React.createContext(null);
+const FormItem = Form.Item
+
+const LogTable = styled.div`
+background-color: #FFFFFF;
+height: 960px;
+margin-left: 24px;
+.delButton {
+  margin-left: 40px;
+}
+`
+
+const EditableRow = ({ index, ...props }) => {
+  const [form] = Form.useForm();
+  return (
+    <Form form={form} component={false}>
+      <EditableContext.Provider value={form}>
+        <tr {...props} />
+      </EditableContext.Provider>
+    </Form>
+  );
+};
+
+const EditableCell = ({
+  title,
+  editable,
+  children,
+  dataIndex,
+  record,
+  handleSave,
+  ...restProps
+}) => {
+  const [editing, setEditing] = useState(false);
+  const inputRef = useRef(null);
+  const form = useContext(EditableContext);
+  useEffect(() => {
+    if (editing) {
+      inputRef.current.focus();
+    }
+  }, [editing]);
+
+  const toggleEdit = () => {
+    setEditing(!editing);
+    form.setFieldsValue({
+      [dataIndex]: record[dataIndex],
+    });
+  };
+
+  const save = async () => {
+    try {
+      const values = await form.validateFields();
+      toggleEdit();
+      handleSave({ ...record, ...values });
+    } catch (errInfo) {
+      console.log('Save failed:', errInfo);
+    }
+  };
+
+  let childNode = children;
+
+  if (editable) {
+    childNode = editing ? (
+      <FormItem
+        style={{
+          margin: 0,
+        }}
+        name={dataIndex}
+        rules={[
+          {
+            required: true,
+            message: `${title} is required.`,
+          },
+        ]}
+      >
+        <Input ref={inputRef} onPressEnter={save} onBlur={save} />
+      </FormItem>
+    ) : (
+      <div
+        className="editable-cell-value-wrap"
+        style={{
+          paddingRight: 24,
+        }}
+        onClick={toggleEdit}
+      >
+        {children}
+      </div>
+    );
+  }
+
+  return <td {...restProps}>{childNode}</td>;
+};
+
+export default function LogItems() {
+  const itemData = [
+    {
+      key: '0',
+      name: '每日供应商销量预测作业2',
+      type: 'java',
+      sort: '业务预测',
+      creTime: '2022.8.18 12:00:00',
+      updTime: '2022.8.18 12:00:00',
+    },
+    {
+      key: '1',
+      name: '每日供应商销量预测作业21',
+      type: 'java',
+      sort: '业务预测',
+      creTime: '2022.8.18 12:00:00',
+      updTime: '2022.8.18 12:00:00',
+    }
+  ];
+  const [dataSource, setDataSource] = useState(itemData
+  //   [
+  //   {
+  //     key: '0',
+  //     name: '每日供应商销量预测作业2',
+  //     type: 'java',
+  //     sort: '业务预测',
+  //     creTime: '2022.8.18 12:00:00',
+  //     updTime: '2022.8.18 12:00:00',
+  //   },
+  //   {
+  //     key: '1',
+  //     name: '每日供应商销量预测作业21',
+  //     type: 'java',
+  //     sort: '业务预测',
+  //     creTime: '2022.8.18 12:00:00',
+  //     updTime: '2022.8.18 12:00:00',
+  //   },
+  // ]
+  );
+  const [count, setCount] = useState(2);
+
+  const handleDelete = (key) => {
+    const newData = dataSource.filter((item) => item.key !== key);
+    setDataSource(newData);
+  };
+
+  const defaultColumns = [
+    {
+      title: '作业名称',
+      dataIndex: 'name',
+      width: '16.6%',
+    },
+    {
+      title: '作业类型',
+      dataIndex: 'type',
+      width: '16.6%',
+    },
+    {
+      title: '作业分类',
+      dataIndex: 'sort',
+      width: '16.6%',
+
+    },
+    {
+      title: '创建时间',
+      dataIndex: 'creTime',
+      width: '16.6%',
+
+    },
+    {
+      title: '更新时间',
+      dataIndex: 'updTime',
+      width: '16.6%',
+
+    },
+    {
+      title: '操作',
+      dataIndex: 'operation',
+      width: '16.6%',
+
+      render: (_, record) =>
+        dataSource.length >= 1 ? (
+          <>
+            <Popconfirm >
+              <a>编辑</a>
+            </Popconfirm>
+            <Popconfirm 
+            title="Sure to delete?" 
+            onConfirm={() => handleDelete(record.key)}
+            >
+              <a className='delButton'>删除</a>
+            </Popconfirm>
+          </>
+        ) : null,
+          
+    },
+  ];
+
+  const handleSave = (row) => {
+    const newData = [...dataSource];
+    const index = newData.findIndex((item) => row.key === item.key);
+    const item = newData[index];
+    newData.splice(index, 1, { ...item, ...row });
+    setDataSource(newData);
+  };
+
+  const components = {
+    body: {
+      row: EditableRow,
+      cell: EditableCell,
+    },
+  };
+  const columns = defaultColumns.map((col) => {
+    if (!col.editable) {
+      return col;
+    }
+
+    return {
+      ...col,
+      onCell: (record) => ({
+        record,
+        editable: col.editable,
+        dataIndex: col.dataIndex,
+        title: col.title,
+        handleSave,
+      }),
+    };
+  });
+  return (
+    <LogTable>
+      <Table
+        components={components}
+        rowClassName={() => 'editable-row'}
+        bordered
+        dataSource={dataSource}
+        columns={columns}
+        style={{
+          marginTop: '20px',
+        }}
+      />
+    </LogTable>
+  );
+};

+ 28 - 0
src/module/tasklog/page/TaskLog.jsx

@@ -0,0 +1,28 @@
+import React from 'react';
+import styled from 'styled-components'
+import LogTable from '../component/LogTable'
+const TSLog = styled.div``
+
+export default function TaskLog() {  
+      document.body.style.background = '#F0F2F5'
+      return (
+        <TSLog>
+          <div>
+          <header  style={{ 
+          height: '40px', 
+          fontSize: '14px',
+          paddingLeft: '24px',
+          lineHeight: '40px',
+          backgroundColor: 'white',
+          marginBottom: '16px',
+          }}>
+          <span>
+            任务日志
+          </span>
+          </header>
+          </div>
+          <LogTable/>
+        </TSLog>
+    )
+}
+  

+ 536 - 0
src/module/workmgmt/component/JobCreate.jsx

@@ -0,0 +1,536 @@
+import { Button, Form, Input, Select, Radio, Space, Upload, Steps, message } from 'antd';
+import type { RadioChangeEvent } from 'antd';
+import type { UploadProps } from 'antd';
+import { UploadOutlined } from '@ant-design/icons';
+import React, { useState , Component, useEffect } from 'react';
+import styled from 'styled-components';
+import JobStepOne from './JobStepOne';
+import JobStepTwo from './JobStepTwo';
+
+const JobCre = styled.div``
+const CreContent = styled.div`
+  background-color: #FFFFFF;
+  height: 960px;
+  margin-left: 24px;
+  .ant-form {
+    display: flex;
+    flex-direction: column;
+    align-content: flex-start;
+    justify-content: center;
+    flex-wrap: wrap;
+    align-items: stretch;
+    
+  }
+  .creTitle {
+    width: 120px;
+    height: 60px;
+    margin-left: 15px;
+    display: flex;
+  }
+  .bluetTitle { 
+    background-color: rgba(24, 129, 218, 1);
+    width: 3px;
+    height: 16px;
+    margin-top: 25px;
+    line-height: 67px;
+  }
+  .creText {
+    width: 105px;
+    height: 20px;    
+    margin-left: 10px;
+    overflow-wrap: break-word;
+    color: rgba(74, 74, 74, 1);
+    font-size: 14px;
+    letter-spacing: 1px;
+    text-align: center;
+    white-space: nowrap;
+    line-height: 67px;
+    font-weight: 800;
+  }
+  .ant-select-arrow {
+    top: 36%;
+    padding-left: 7px;
+    height: 20px;
+    border-left: 1px solid
+  }
+  .ant-col {
+    flex: unset;
+  }
+   
+  .ant-select {
+    width: 295px;
+    height: 32px;
+  }
+  .ant-form-item-control-input {
+    width:295px;
+  }
+  .ant-row {
+    margin-left: 60px;
+  }
+  .JsPyInfo {
+    width:464px;
+    .ant-form {
+      align-content: end;
+    }
+    .choseJs {
+      .ant-row {
+        margin-left: 43px;
+      },
+      .ant-form-item-control-input {
+      left: 11px;
+    }
+    .upButton {
+      width: 88px;
+      height: 32px;
+      margin-left: 7px;
+      background-color: #4883FB;
+      color: white;
+    }
+    }
+    
+  }
+  .mirrorLeft {
+    margin-left: -25px;
+  }
+  .ant-radio-wrapper {
+    display: inline-block;
+  }
+  .javaSelect {
+    width: 255px;
+    left: 8px;
+  }
+  .DagInfo {
+    .ant-steps-item-icon {
+      width: 42px;
+      height: 42px;
+      line-height: 42px;
+    }
+    .ant-steps-item-tail {
+      font-size: 1px;
+      margin-left: 67px;
+    }
+    .ant-steps-label-vertical .ant-steps-item-content {
+      width:220px
+    }
+  }
+  `
+
+const { Option } = Select;
+const FormItem = Form.Item
+const RadioGroup = Radio.Group;
+
+const layout = {
+  labelCol: {
+    span: 8,
+  },
+  wrapperCol: {
+    span: 16,
+  },
+};
+const tailLayout = {
+  wrapperCol: {
+    offset: 8,
+    span: 16,
+  },
+};
+export default function JobCreate () {
+  // 设置背景颜色
+  document.body.style.background = '#F0F2F5'
+  const [form] = Form.useForm();
+  const { Step } = Steps 
+  
+  // 显示/隐藏配置Js作业信息模块
+  const [JsIsShow,setJsIsShow]=useState('none')
+
+  // 显示/隐藏配置Python作业信息模块
+  const [PyIsShow,setPyIsShow]=useState('none')
+
+  // 显示/隐藏配置Dag作业信息模块
+  const [DagIsShow,setDagIsShow]=useState('none')
+
+  // 单选框动态传值
+  const [value, setValue] = useState(1);
+
+  // 步骤数
+  const [currentStep, setCurrentStep] = useState(0)
+
+  const [drawDataForm] = Form.useForm()
+
+  const [currentForm, setCurrentForm] = useState(drawDataForm)
+
+  // 设置单选框value值
+  const onChange = (e) => {
+    console.log('radio checked', e.target.value);
+    setValue(e.target.value);
+  };
+  
+  //上传文件配置
+  const UpProps: UploadProps = {
+    name: 'file',
+    action: '',
+    headers: {
+      authorization: 'authorization-text',
+    },
+
+    // 上传文件提交状态
+    onChange(info) {
+      if (info.file.status !== 'uploading') {
+        console.log(info.file, info.fileList);
+      }
+      if (info.file.status === 'done') {
+        message.success(`${info.file.name} file uploaded successfully`);
+      } else if (info.file.status === 'error') {
+        message.error(`${info.file.name} file upload failed.`);
+      }
+    },
+  };
+
+  //根据作业类型做出判断
+  const onGenderChange = (value) => {
+    if (value === "Java") {
+      setJsIsShow('block')
+      setDagIsShow('none')
+      setPyIsShow('none') 
+    }
+    else if (value === "Python") {
+      setJsIsShow('none')
+      setDagIsShow('none')
+      setPyIsShow('block') 
+    }
+    else if (value === "Dag") {
+      setJsIsShow('none')
+      setDagIsShow('block')
+      setPyIsShow('none')
+    }
+  }
+
+  //上一步/下一步
+  const changeStep = num => {
+    setCurrentStep(currentStep + num)
+  }
+
+  //下一步
+  const nextStep = () => {
+  changeStep(1)
+  }
+
+  useEffect(() => {
+    switch (currentStep) {
+      case 0:
+        setCurrentForm(drawDataForm)
+        console.log(drawDataForm)
+        break
+      default:
+        break
+   
+
+
+
+    }},[currentStep])
+  return (
+    <JobCre>
+      <div>
+        <header  style={{ 
+        height: '40px', 
+        fontSize: '14px',
+        paddingLeft: '24px',
+        lineHeight: '40px',
+        backgroundColor: 'white',
+        marginBottom: '16px',
+        }}>
+          <span>
+            作业列表
+          </span>
+        </header>
+      </div>
+    <CreContent>
+    <div className="choseJob">
+      <div className='creTitle'>
+        <div className='bluetTitle' />
+        <span className='creText'>配置作业类型</span>
+      </div>
+
+      {/* 作业类型选择       */}
+      <Form {...layout} form={form} name="control-hooks" >
+      <FormItem
+        name="type
+        "
+        label="选择作业类型"
+        rules={[
+          {
+            required: true,
+          },
+        ]}
+      >
+        <Select
+          placeholder="请选择作业类型..."
+          onChange={onGenderChange}
+          allowClear
+          value = {value}
+        >
+          <Option value="Java">Java</Option>
+          <Option value="Python">Python</Option>
+          <Option value="Dag">Dag</Option>
+        </Select>
+      </FormItem>
+    </Form>   
+    </div>
+    <div className="DagInfo" style={{display: DagIsShow}}>
+      <Steps labelPlacement="vertical" size="small" current={currentStep}>
+        <Step title="步骤1: 配置作业信息" />
+        <Step title="步骤2: 定义输入数据源" />
+        <Step title="步骤3: 定义输出数据源" />
+      </Steps>
+      <div className='creTitle'>
+        <div className='bluetTitle' />
+        <span className='creText'>配置作业信息</span>
+      </div>  
+
+      {/* 配置Dag作业信息 */}
+
+      {/* 第一步 */}
+      {currentStep === 0 && (
+        <JobStepOne
+          drawDataForm={drawDataForm}
+        />
+      )}
+
+      {/* 第二步 */}
+      {currentStep === 1 && (
+        <JobStepTwo/>
+      )}
+
+    <Space style={{ margin: '20px' }}>
+      <Button onClick={() => {changeStep(-1)}}>上一步</Button>
+      <Button type="primary" onClick={nextStep}>下一步</Button>
+    </Space>
+    </div>
+    
+
+    {/* 配置Js作业信息 */}
+    <div className="JsPyInfo" style={{display: JsIsShow}}>
+      <div className='creTitle'>
+        <div className='bluetTitle' />
+        <span className='creText'>配置作业信息</span>
+      </div>  
+
+      {/* 输入作业名称 */}
+      <Form {...layout} form={form} name="control-hooks" >
+      <FormItem
+        name="JsJobName
+        "
+        label="作业名称"
+        rules={[
+          {
+            required: true,
+          },
+        ]}
+      >
+        <Input
+          placeholder="请输入作业名称..."
+          allowClear
+        >
+        </Input>
+      </FormItem>
+    </Form>  
+
+    {/* 选择作业分类 */}
+    <Form {...layout} form={form} name="control-hooks">
+      <FormItem
+        name="JsJobSort
+        "
+        label="作业分类"
+        rules={[
+          {
+            required: true,
+          },
+        ]}
+      >
+        <Select
+          placeholder="请选择作业分类..."
+          allowClear
+        >
+          <Option value="Java">Java</Option>
+          <Option value="Python">Python</Option>
+          <Option value="Dag">Dag</Option>
+        </Select>
+      </FormItem>
+    </Form>  
+
+    {/* 选择执行镜像 */}
+    <Form {...layout} form={form} name="control-hooks">
+      <FormItem
+        className='mirrorLeft'
+        name="JsMirror
+        "
+        label="配置执行的镜像"
+        rules={[
+          {
+            required: true,
+          },
+        ]}
+      >
+        <Select
+          placeholder="请选择镜像..."
+          allowClear
+        >
+          <Option value="Java">Java</Option>
+          <Option value="Python">Python</Option>
+          <Option value="Dag">Dag</Option>
+        </Select>
+      </FormItem>
+    </Form>
+
+    {/* 选择执行的Java脚本 */}
+    <Form {...layout} form={form} name="control-hooks" className='choseJs'>
+      <FormItem
+        className='mirrorLeft'
+        label="配置执行的Java脚本"
+        name="JsScripter"
+        rules={[
+          {
+            required: true,
+          },
+        ]}
+      >
+      <RadioGroup onChange={onChange} value={value}>
+      <Space direction="vertical" className='jsSel'>
+        <Radio value={1}>
+        <Select
+          placeholder="在工作目录中选择"
+          allowClear
+          className='javaSelect'
+          disabled={value === 1 ? false : true}
+        >
+          <Option value="Java">Java</Option>
+          <Option value="Python">Python</Option>
+          <Option value="Dag">Dag</Option>
+        </Select>
+        </Radio>
+        
+        <Radio value={4}>
+          <Upload {...UpProps}>
+            <Button  className='upButton'>本地上传</Button>
+          </Upload>
+        </Radio>
+      </Space>
+    </RadioGroup>
+      </FormItem>
+    </Form>
+    </div>
+    
+    {/* 配置Python作业信息 */}
+    <div className="JsPyInfo" style={{display: PyIsShow}}>
+      <div className='creTitle'>
+        <div className='bluetTitle' />
+        <span className='creText'>配置作业信息</span>
+      </div>  
+
+      {/* 输入作业名称 */}
+      <Form {...layout} form={form} name="control-hooks" >
+      <FormItem
+        name="PyJobName
+        "
+        label="作业名称"
+        rules={[
+          {
+            required: true,
+          },
+        ]}
+      >
+        <Input
+          placeholder="请输入作业名称..."
+          allowClear
+        >
+        </Input>
+      </FormItem>
+    </Form>  
+
+    {/* 选择作业分类 */}
+    <Form {...layout} form={form} name="control-hooks">
+      <FormItem
+        name="PyJobSort
+        "
+        label="作业分类"
+        rules={[
+          {
+            required: true,
+          },
+        ]}
+      >
+        <Select
+          placeholder="请选择作业分类..."
+          allowClear
+        >
+          <Option value="Java">Java</Option>
+          <Option value="Python">Python</Option>
+          <Option value="Dag">Dag</Option>
+        </Select>
+      </FormItem>
+    </Form>  
+
+    {/* 选择执行镜像 */}
+    <Form {...layout} form={form} name="control-hooks">
+      <FormItem
+        className='mirrorLeft'
+        name="PyMirror
+        "
+        label="配置执行的镜像"
+        rules={[
+          {
+            required: true,
+          },
+        ]}
+      >
+        <Select
+          placeholder="请选择镜像..."
+          allowClear
+        >
+          <Option value="Java">Java</Option>
+          <Option value="Python">Python</Option>
+          <Option value="Dag">Dag</Option>
+        </Select>
+      </FormItem>
+    </Form>
+
+    {/* 选择执行的Java脚本 */}
+    <Form {...layout} form={form} name="control-hooks" className='choseJs'>
+      <FormItem
+        className='mirrorLeft'
+        label="配置执行的Java脚本"
+        name="PyScripter"
+        rules={[
+          {
+            required: true,
+          },
+        ]}
+      >
+      <RadioGroup onChange={onChange} value={value}>
+      <Space direction="vertical" className='jsSel'>
+        <Radio value={1}>
+        <Select
+          placeholder="在工作目录中选择"
+          allowClear
+          className='javaSelect'
+          disabled={value === 1 ? false : true}
+        >
+          <Option value="Java">Java</Option>
+          <Option value="Python">Python</Option>
+          <Option value="Dag">Dag</Option>
+        </Select>
+        </Radio>
+        
+        <Radio value={2}>
+          <Upload {...UpProps}>
+            <Button  className='upButton'>本地上传</Button>
+          </Upload>
+        </Radio>
+      </Space>
+    </RadioGroup>
+      </FormItem>
+    </Form>
+    </div>     
+    </CreContent>
+  </JobCre>
+  );
+};

+ 266 - 0
src/module/workmgmt/component/JobItems.jsx

@@ -0,0 +1,266 @@
+import { Button, Form, Input, Popconfirm, Table } from 'antd';
+import React, { useContext, useEffect, useRef, useState } from 'react';
+import styled from 'styled-components'
+import { Link } from 'react-router-dom';
+const EditableContext = React.createContext(null);
+const FormItem = Form.Item
+
+const JobItems = styled.div`
+  background-color: #FFFFFF;
+  height: 960px;
+  margin-left: 24px;
+  .delButton {
+  margin-left: 40px;
+  }
+  `
+const EditableRow = ({ index, ...props }) => {
+  const [form] = Form.useForm();
+  return (
+    <Form form={form} component={false}>
+      <EditableContext.Provider value={form}>
+        <tr {...props} />
+      </EditableContext.Provider>
+    </Form>
+  );
+};
+
+const EditableCell = ({
+  title,
+  editable,
+  children,
+  dataIndex,
+  record,
+  handleSave,
+  ...restProps
+}) => {
+  const [editing, setEditing] = useState(false);
+  const inputRef = useRef(null);
+  const form = useContext(EditableContext);
+  useEffect(() => {
+    if (editing) {
+      inputRef.current.focus();
+    }
+  }, [editing]);
+
+  const toggleEdit = () => {
+    setEditing(!editing);
+    form.setFieldsValue({
+      [dataIndex]: record[dataIndex],
+    });
+  };
+
+  const save = async () => {
+    try {
+      const values = await form.validateFields();
+      toggleEdit();
+      handleSave({ ...record, ...values });
+    } catch (errInfo) {
+      console.log('Save failed:', errInfo);
+    }
+  };
+
+  let childNode = children;
+
+  if (editable) {
+    childNode = editing ? (
+      <FormItem
+        style={{
+          margin: 0,
+        }}
+        name={dataIndex}
+        rules={[
+          {
+            required: true,
+            message: `${title} is required.`,
+          },
+        ]}
+      >
+        <Input ref={inputRef} onPressEnter={save} onBlur={save} />
+      </FormItem>
+    ) : (
+      <div
+        className="editable-cell-value-wrap"
+        style={{
+          paddingRight: 24,
+        }}
+        onClick={toggleEdit}
+      >
+        {children}
+      </div>
+    );
+  }
+
+  return <td {...restProps}>{childNode}</td>;
+};
+
+const App = () => {
+  const itemData = [
+    {
+      key: '0',
+      name: '每日供应商销量预测作业2',
+      type: 'java',
+      sort: '业务预测',
+      creTime: '2022.8.18 12:00:00',
+      updTime: '2022.8.18 12:00:00',
+    },
+    {
+      key: '1',
+      name: '每日供应商销量预测作业21',
+      type: 'java',
+      sort: '业务预测',
+      creTime: '2022.8.18 12:00:00',
+      updTime: '2022.8.18 12:00:00',
+    }
+  ];
+  const [dataSource, setDataSource] = useState(itemData
+  //   [
+  //   {
+  //     key: '0',
+  //     name: '每日供应商销量预测作业2',
+  //     type: 'java',
+  //     sort: '业务预测',
+  //     creTime: '2022.8.18 12:00:00',
+  //     updTime: '2022.8.18 12:00:00',
+  //   },
+  //   {
+  //     key: '1',
+  //     name: '每日供应商销量预测作业21',
+  //     type: 'java',
+  //     sort: '业务预测',
+  //     creTime: '2022.8.18 12:00:00',
+  //     updTime: '2022.8.18 12:00:00',
+  //   },
+  // ]
+  );
+  const [count, setCount] = useState(2);
+
+  const handleDelete = (key) => {
+    const newData = dataSource.filter((item) => item.key !== key);
+    setDataSource(newData);
+  };
+
+  const defaultColumns = [
+    {
+      title: '作业名称',
+      dataIndex: 'name',
+      width: '16.6%',
+    },
+    {
+      title: '作业类型',
+      dataIndex: 'type',
+      width: '16.6%',
+    },
+    {
+      title: '作业分类',
+      dataIndex: 'sort',
+      width: '16.6%',
+
+    },
+    {
+      title: '创建时间',
+      dataIndex: 'creTime',
+      width: '16.6%',
+
+    },
+    {
+      title: '更新时间',
+      dataIndex: 'updTime',
+      width: '16.6%',
+
+    },
+    {
+      title: '操作',
+      dataIndex: 'operation',
+      width: '16.6%',
+
+      render: (_, record) =>
+        dataSource.length >= 1 ? (
+          <>
+            <Popconfirm >
+              <a>编辑</a>
+            </Popconfirm>
+            <Popconfirm 
+            title="Sure to delete?" 
+            onConfirm={() => handleDelete(record.key)}
+            >
+              <a className='delButton'>删除</a>
+            </Popconfirm>
+          </>
+        ) : null,
+          
+    },
+  ];
+//创建作业
+  const handleAdd = () => {
+    const newData = {
+      key: count,
+      name: '每日供应商销量预测作业2',
+      type: 'java',
+      sort: '业务预测',
+      creTime: '2022.8.18 12:00:00',
+      updTime: '2022.8.18 12:00:00',
+    };
+    setDataSource([...dataSource, newData]);
+    setCount(count + 1);
+  };
+
+  const handleSave = (row) => {
+    const newData = [...dataSource];
+    const index = newData.findIndex((item) => row.key === item.key);
+    const item = newData[index];
+    newData.splice(index, 1, { ...item, ...row });
+    setDataSource(newData);
+  };
+
+  const components = {
+    body: {
+      row: EditableRow,
+      cell: EditableCell,
+    },
+  };
+  const columns = defaultColumns.map((col) => {
+    if (!col.editable) {
+      return col;
+    }
+
+    return {
+      ...col,
+      onCell: (record) => ({
+        record,
+        editable: col.editable,
+        dataIndex: col.dataIndex,
+        title: col.title,
+        handleSave,
+      }),
+    };
+  });
+  return (
+    <JobItems>
+      <Link to="/cre">
+        <Button
+        onClick={handleAdd}
+        type="primary"
+        style={{
+          float: 'right',
+          marginBottom: 16,
+          marginTop: '18px',
+          marginRight: '16px',
+          fontSize: '12px',
+        }}
+      >
+        创建作业
+      </Button>
+      </Link>
+      
+      <Table
+        components={components}
+        rowClassName={() => 'editable-row'}
+        bordered
+        dataSource={dataSource}
+        columns={columns}
+      />
+    </JobItems>
+  );
+};
+
+export default App;

+ 99 - 0
src/module/workmgmt/component/JobStepOne.jsx

@@ -0,0 +1,99 @@
+import { Button, Form, Input, Select, Radio, Space, Upload, Steps } from 'antd';
+import setFieldValue from 'antd';
+import React, { useState , Component , useEffect } from 'react';
+const { Option } = Select;
+const FormItem = Form.Item
+
+const layout = {
+  labelCol: {
+    span: 8,
+  },
+  wrapperCol: {
+    span: 16,
+  },
+};
+const tailLayout = {
+  wrapperCol: {
+    offset: 8,
+    span: 16,
+  },
+};
+
+
+
+export default function JobStepOne({ drawDataForm }) {
+  const [form] = Form.useForm();
+  
+useEffect(() => {
+  const DJName = drawDataForm.getFieldValue('DagJobName')
+  if (DJName) {
+    drawDataForm.setFieldValue('DagJobName',DJName)
+    console.log(drawDataForm)
+  }
+},[])
+
+  return (
+    <>
+    <Form  {...layout} form={drawDataForm} name="control-hooks" >
+      <FormItem
+        name="DagJobName
+        "
+        label="作业名称"
+        rules={[
+          {
+            required: true,
+          },
+        ]}
+      >
+        <Input
+          placeholder="请输入作业名称..."
+          allowClear
+        >
+        </Input>
+      </FormItem>
+    
+    {/* 作业分类选择 */}
+      <FormItem
+        name="DagJobSort"
+        label="作业分类"
+        rules={[
+          {
+            required: true,
+          },
+        ]}
+      >
+        <Select
+          placeholder="请选择作业分类..."
+          allowClear
+        >
+          <Option value="Java">Java</Option>
+          <Option value="Python">Python</Option>
+          <Option value="Dag">Dag</Option>
+        </Select>
+      </FormItem>
+
+    {/* 选择执行镜像 */}
+      <FormItem
+        className='mirrorLeft'
+        name="DagMirror
+        "
+        label="选择DAG算子"
+        rules={[
+          {
+            required: true,
+          },
+        ]}
+      >
+        <Select
+          placeholder="请选择DAG算子"
+          allowClear
+        >
+          <Option value="Java">Java</Option>
+          <Option value="Python">Python</Option>
+          <Option value="Dag">Dag</Option>
+        </Select>
+      </FormItem>
+    </Form>
+    </>
+  )
+}

+ 0 - 0
src/module/workmgmt/component/JobStepThree.jsx


+ 126 - 0
src/module/workmgmt/component/JobStepTwo.jsx

@@ -0,0 +1,126 @@
+import { Alert,Button, Form, Input, Select, Radio, Space, Upload, Steps } from 'antd';
+import styled from 'styled-components';
+const StepTwo = styled.div`
+  display: flex;
+  .StepTwo-content {
+    width: 867px; 
+    height: 450px; 
+    margin-left: 50px; 
+    margin-top: 20px; 
+    overflow: scroll;
+    border: 1px solid #C8D3E9;
+    .ant-row {    
+      margin-left: 37px;
+    }
+    .content-item {
+      margin-top: 17px;
+      .ant-form {
+        flex-direction: row;
+        justify-content: left;
+        .ant-form-item {
+          margin-bottom: 10px;
+        }
+      }
+      .item-choseList {
+        .ant-select {
+          width: 158px;
+        }
+      }
+      .stateIcon {
+        display: inline-block;
+        width:20px;
+        background-color: #fff;
+        border: none;
+      }
+      .showStructure {
+        margin-left: 14px;
+      }
+      .dataSourceType {
+        display: flex;
+        margin-left: 137px;
+        color: #7D7D7D;
+      }
+    }
+  }
+  .structure-detail {
+    display: flex;
+    width: 416px;
+    height: 450px;
+    border: 1px solid #C8D3E9;
+    margin-top: 20px;
+    margin-left:60px;
+    border-radius: 2px;
+  }
+`
+const FormItem = Form.Item
+const { Option } = Select;
+
+export default function JobStepTwo() {
+  
+  const showStructure = () => {
+
+  }
+  
+  return (
+    <>
+      <StepTwo>
+      <div className='StepTwo-content'>
+        <div className='content-item'>
+          <Form name="control-hooks" >
+            <FormItem
+            name="sort"
+            label="选择数据源1"
+            >
+              <Select
+              allowClear
+              >
+                <Option value="Java">Java</Option>
+                <Option value="Python">Python</Option>
+                <Option value="Dag">Dag</Option>
+              </Select>
+            </FormItem>
+            <FormItem
+            name="sort"
+            label="选择表1"
+            className='item-choseList'>
+            
+              <Select
+              allowClear
+              >
+                <Option value="Java">Java</Option>
+                <Option value="Python">Python</Option>
+                <Option value="Dag">Dag</Option>
+              </Select>
+              <Alert 
+              type='success'
+              showIcon
+              className='stateIcon'
+              >
+              </Alert>
+              <Button 
+              type='primary' 
+              className='showStructure'
+              onClick={showStructure}>
+              结构预览</Button>
+            </FormItem>
+            <div className='dataSourceType'>
+              数据源类型:
+              <div>
+                <span>
+                  hive
+                </span>
+              </div>
+            </div>
+          </Form>
+        </div>
+      </div>
+      <div className='structure-detail'>
+        <div className='detail-item'> 
+          <div className=''></div>
+        </div>
+      </div>
+    </StepTwo>
+    </>
+    
+  )
+}

+ 28 - 0
src/module/workmgmt/page/JobManagement.jsx

@@ -0,0 +1,28 @@
+import React from 'react';
+import JobItems from '../component/JobItems'
+import styled from 'styled-components'
+const JobManage = styled.div``
+
+export default function JobManagement() {  
+      document.body.style.background = '#F0F2F5'
+      return (
+        <JobManage>
+          <div>
+          <header  style={{ 
+          height: '40px', 
+          fontSize: '14px',
+          paddingLeft: '24px',
+          lineHeight: '40px',
+          backgroundColor: 'white',
+          marginBottom: '16px',
+          }}>
+          <span>
+            作业列表
+          </span>
+          </header>
+          </div>
+         <JobItems/>
+        </JobManage>
+    )
+}
+