Alkuttt 2 роки тому
батько
коміт
fde333574d

+ 132 - 0
package-lock.json

@@ -3302,6 +3302,11 @@
       "resolved": "https://registry.npmjs.org/@qixian.cs/path-to-regexp/-/path-to-regexp-6.1.0.tgz",
       "integrity": "sha512-2jIiLiVZB1jnY7IIRQKtoV8Gnr7XIhk4mC88ONGunZE3hYt5IHUG4BE/6+JiTBjjEWQLBeWnZB8hGpppkufiVw=="
     },
+    "@remix-run/router": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.0.0.tgz",
+      "integrity": "sha512-SCR1cxRSMNKjaVYptCzBApPDqGwa3FGdjVHc+rOToocNPHQdIYLZBfv/3f+KvYuXDkUGVIW9IAzmPNZDRL1I4A=="
+    },
     "@rollup/plugin-babel": {
       "version": "5.3.1",
       "resolved": "https://registry.npmjs.org/@rollup/plugin-babel/-/plugin-babel-5.3.1.tgz",
@@ -4498,6 +4503,110 @@
         "color-convert": "^2.0.1"
       }
     },
+    "antd": {
+      "version": "4.23.2",
+      "resolved": "https://registry.npmjs.org/antd/-/antd-4.23.2.tgz",
+      "integrity": "sha512-GGOaIUxPg8wl8lGcCJ2U/1Eg5mt0hNb554a0y4mTJa1ijPRCNM8XjUcio4lTMM7M9/fLm9ttKtyxHg4n+JX26A==",
+      "requires": {
+        "@ant-design/colors": "^6.0.0",
+        "@ant-design/icons": "^4.7.0",
+        "@ant-design/react-slick": "~0.29.1",
+        "@babel/runtime": "^7.18.3",
+        "@ctrl/tinycolor": "^3.4.0",
+        "classnames": "^2.2.6",
+        "copy-to-clipboard": "^3.2.0",
+        "lodash": "^4.17.21",
+        "memoize-one": "^6.0.0",
+        "moment": "^2.29.2",
+        "rc-cascader": "~3.7.0",
+        "rc-checkbox": "~2.3.0",
+        "rc-collapse": "~3.3.0",
+        "rc-dialog": "~8.9.0",
+        "rc-drawer": "~5.1.0",
+        "rc-dropdown": "~4.0.0",
+        "rc-field-form": "~1.27.0",
+        "rc-image": "~5.7.0",
+        "rc-input": "~0.1.2",
+        "rc-input-number": "~7.3.5",
+        "rc-mentions": "~1.9.1",
+        "rc-menu": "~9.6.3",
+        "rc-motion": "^2.6.1",
+        "rc-notification": "~4.6.0",
+        "rc-pagination": "~3.1.17",
+        "rc-picker": "~2.6.10",
+        "rc-progress": "~3.3.2",
+        "rc-rate": "~2.9.0",
+        "rc-resize-observer": "^1.2.0",
+        "rc-segmented": "~2.1.0",
+        "rc-select": "~14.1.13",
+        "rc-slider": "~10.0.0",
+        "rc-steps": "~4.1.0",
+        "rc-switch": "~3.2.0",
+        "rc-table": "~7.26.0",
+        "rc-tabs": "~12.1.0-alpha.1",
+        "rc-textarea": "~0.3.0",
+        "rc-tooltip": "~5.2.0",
+        "rc-tree": "~5.7.0",
+        "rc-tree-select": "~5.5.0",
+        "rc-trigger": "^5.2.10",
+        "rc-upload": "~4.3.0",
+        "rc-util": "^5.22.5",
+        "scroll-into-view-if-needed": "^2.2.25"
+      },
+      "dependencies": {
+        "rc-cascader": {
+          "version": "3.7.0",
+          "resolved": "https://registry.npmjs.org/rc-cascader/-/rc-cascader-3.7.0.tgz",
+          "integrity": "sha512-SFtGpwmYN7RaWEAGTS4Rkc62ZV/qmQGg/tajr/7mfIkleuu8ro9Hlk6J+aA0x1YS4zlaZBtTcSaXM01QMiEV/A==",
+          "requires": {
+            "@babel/runtime": "^7.12.5",
+            "array-tree-filter": "^2.1.0",
+            "classnames": "^2.3.1",
+            "rc-select": "~14.1.0",
+            "rc-tree": "~5.7.0",
+            "rc-util": "^5.6.1"
+          }
+        },
+        "rc-select": {
+          "version": "14.1.13",
+          "resolved": "https://registry.npmjs.org/rc-select/-/rc-select-14.1.13.tgz",
+          "integrity": "sha512-WMEsC3gTwA1dbzWOdVIXDmWyidYNLq68AwvvUlRROw790uGUly0/vmqDozXrIr0QvN/A3CEULx12o+WtLCAefg==",
+          "requires": {
+            "@babel/runtime": "^7.10.1",
+            "classnames": "2.x",
+            "rc-motion": "^2.0.1",
+            "rc-overflow": "^1.0.0",
+            "rc-trigger": "^5.0.4",
+            "rc-util": "^5.16.1",
+            "rc-virtual-list": "^3.2.0"
+          }
+        },
+        "rc-tree": {
+          "version": "5.7.0",
+          "resolved": "https://registry.npmjs.org/rc-tree/-/rc-tree-5.7.0.tgz",
+          "integrity": "sha512-F+Ewkv/UcutshnVBMISP+lPdHDlcsL+YH/MQDVWbk+QdkfID7vXiwrHMEZn31+2Rbbm21z/HPceGS8PXGMmnQg==",
+          "requires": {
+            "@babel/runtime": "^7.10.1",
+            "classnames": "2.x",
+            "rc-motion": "^2.0.1",
+            "rc-util": "^5.16.1",
+            "rc-virtual-list": "^3.4.8"
+          }
+        },
+        "rc-tree-select": {
+          "version": "5.5.0",
+          "resolved": "https://registry.npmjs.org/rc-tree-select/-/rc-tree-select-5.5.0.tgz",
+          "integrity": "sha512-XS0Jvw4OjFz/Xvb2byEkBWv55JFKFz0HVvTBa/cPOHJaQh/3EaYwymEMnCCvGEzS1+5CfDVwMtA8j/v4rt1DHw==",
+          "requires": {
+            "@babel/runtime": "^7.10.1",
+            "classnames": "2.x",
+            "rc-select": "~14.1.0",
+            "rc-tree": "~5.7.0",
+            "rc-util": "^5.16.1"
+          }
+        }
+      }
+    },
     "anymatch": {
       "version": "3.1.2",
       "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz",
@@ -9083,6 +9192,11 @@
         "minimist": "^1.2.6"
       }
     },
+    "moment": {
+      "version": "2.29.4",
+      "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz",
+      "integrity": "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w=="
+    },
     "mousetrap": {
       "version": "1.6.5",
       "resolved": "https://registry.npmjs.org/mousetrap/-/mousetrap-1.6.5.tgz",
@@ -10330,6 +10444,16 @@
         "sisteransi": "^1.0.5"
       }
     },
+    "prop-types": {
+      "version": "15.8.1",
+      "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
+      "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==",
+      "requires": {
+        "loose-envify": "^1.4.0",
+        "object-assign": "^4.1.1",
+        "react-is": "^16.13.1"
+      }
+    },
     "proxy-addr": {
       "version": "2.0.7",
       "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz",
@@ -11066,6 +11190,14 @@
       "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.11.0.tgz",
       "integrity": "sha512-F27qZr8uUqwhWZboondsPx8tnC3Ct3SxZA3V5WyEvujRyyNv0VYPhoBg1gZ8/MV5tubQp76Trw8lTv9hzRBa+A=="
     },
+    "react-router": {
+      "version": "6.4.0",
+      "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.4.0.tgz",
+      "integrity": "sha512-B+5bEXFlgR1XUdHYR6P94g299SjrfCBMmEDJNcFbpAyRH1j1748yt9NdDhW3++nw1lk3zQJ6aOO66zUx3KlTZg==",
+      "requires": {
+        "@remix-run/router": "1.0.0"
+      }
+    },
     "react-router-dom": {
       "version": "6.3.0",
       "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.3.0.tgz",

+ 5 - 0
src/bus.js

@@ -0,0 +1,5 @@
+import {EventEmitter} from 'events'
+
+const bus = new EventEmitter()
+
+export default bus

+ 611 - 338
src/module/workmgmt/component/JobCreate.jsx

@@ -1,24 +1,21 @@
-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'
+import { Button, Form, Input, Select, Radio, Space, Upload, Steps, message, Divider } from 'antd';
+import type { RadioChangeEvent} from 'antd';
+import type { UploadProps } from 'antd';
+import { UploadOutlined, PlusOutlined } from '@ant-design/icons';
+import React, { useState , Component, useEffect, useRef, props } from 'react';
+import styled from 'styled-components';
+import JobStepOne from './JobStepOne';
+import JobStepTwo from './JobStepTwo';
+import JobStepThree from './JobStepThree';
+import { useNavigate } from 'react-router'
+import bus from '../../../bus.js'
+import { getJobTypes, createJob } from '../services'
+
 
 const JobCre = styled.div``
 const CreContent = styled.div`
+  background-color: #FFFFFF;
+  height: 960px;
   margin-left: 24px;
   .ant-form {
     display: flex;
@@ -28,13 +25,16 @@ const CreContent = styled.div`
     flex-wrap: wrap;
     align-items: stretch;
   }
+  .script_file {
+    margin-left: -29px !important;
+  }
   .creTitle {
     width: 120px;
     height: 60px;
     margin-left: 15px;
     display: flex;
   }
-  .bluetTitle {
+  .bluetTitle { 
     background-color: rgba(24, 129, 218, 1);
     width: 3px;
     height: 16px;
@@ -43,7 +43,7 @@ const CreContent = styled.div`
   }
   .creText {
     width: 105px;
-    height: 20px;
+    height: 20px;    
     margin-left: 10px;
     overflow-wrap: break-word;
     color: rgba(74, 74, 74, 1);
@@ -54,45 +54,67 @@ const CreContent = styled.div`
     line-height: 67px;
     font-weight: 800;
   }
+  .JobName {
+    margin-left: 25px;
+  }
+  .MMir {
+    margin-left: -17px !important;
+  }
   .ant-select-arrow {
     top: 36%;
     padding-left: 7px;
     height: 20px;
-    border-left: 1px solid;
+    border-left: 1px solid
   }
   .ant-col {
     flex: unset;
   }
-
+   
   .ant-select {
     width: 295px;
     height: 32px;
   }
   .ant-form-item-control-input {
-    width: 295px;
+    width:295px;
   }
   .ant-row {
     margin-left: 60px;
   }
-  .JsPyInfo {
-    width: 464px;
+  .JaPyInfo {
+    width:464px;
     .ant-form {
       align-content: end;
     }
-    .choseJs {
+    .choseJa {
       .ant-row {
         margin-left: 43px;
-      }
-      ,
+      },
       .ant-form-item-control-input {
-        left: 11px;
+      left: 11px;
+    }
+    .upButton {
+      width: 88px;
+      height: 32px;
+      margin-left: 7px;
+      background-color: #4883FB;
+      color: white;
+      }
+    }
+    .JaPySubmit {
+      display: flex;
+      margin-left: 60px;
+      .Submit {
+        margin-left: 20px;
+        .ant-btn {
+          color: #1881DA;
+          border-color: #1881DA;
+        }
       }
-      .upButton {
-        width: 88px;
-        height: 32px;
-        margin-left: 7px;
-        background-color: #4883fb;
-        color: white;
+      .Cancel {
+        .ant-btn {
+          color: #1881DA;
+          border-color: #1881DA;
+        }
       }
     }
   }
@@ -117,14 +139,14 @@ const CreContent = styled.div`
       margin-left: 67px;
     }
     .ant-steps-label-vertical .ant-steps-item-content {
-      width: 220px;
+      width:220px
     }
   }
-`
+  `
 
-const { Option } = Select
+const { Option } = Select;
 const FormItem = Form.Item
-const RadioGroup = Radio.Group
+const RadioGroup = Radio.Group;
 
 const layout = {
   labelCol: {
@@ -133,42 +155,91 @@ const layout = {
   wrapperCol: {
     span: 16,
   },
-}
+};
 const tailLayout = {
   wrapperCol: {
     offset: 8,
     span: 16,
   },
-}
-export default function JobCreate() {
-  const [form] = Form.useForm()
-  const { Step } = Steps
-
-  // 显示/隐藏配置Js作业信息模块
-  const [JsIsShow, setJsIsShow] = useState('none')
+};
+export default function JobCreate (props) {
+  // 设置背景颜色
+  document.body.style.background = '#F0F2F5'
+  const [form] = Form.useForm();
+  const { Step } = Steps 
+  // 路由导航
+  const navigate = useNavigate()
+  // 显示/隐藏配置Ja作业信息模块
+  const [JaIsShow,setJaIsShow]=useState('none')
 
   // 显示/隐藏配置Python作业信息模块
-  const [PyIsShow, setPyIsShow] = useState('none')
+  const [PyIsShow,setPyIsShow]=useState('none')
 
   // 显示/隐藏配置Dag作业信息模块
-  const [DagIsShow, setDagIsShow] = useState('none')
+  const [DagIsShow,setDagIsShow]=useState('none')
 
   // 单选框动态传值
-  const [value, setValue] = useState(1)
+  const [value, setValue] = useState(1);
 
   // 步骤数
   const [currentStep, setCurrentStep] = useState(0)
-
-  const [drawDataForm] = Form.useForm()
-
-  const [currentForm, setCurrentForm] = useState(drawDataForm)
+  
+  //作业类型
+  const [jobTypeOptions, setJobTypeOptions] = useState()
+
+  //作业分类
+  const [jobTags, setJobTags] = useState([])
+
+  //dag第一步表单数据
+  const [ConfigDataForm] = Form.useForm()
+  //dag第二步表单数据
+  const [InputDataForm] = Form.useForm()
+  //dag第三步表单数据
+  const [OutputDataForm] = Form.useForm()
+ 
+  //当前表单数据
+  const [currentForm, setCurrentForm] = useState(ConfigDataForm)
+  
+  //java表单数据
+  const [JavaDataForm] = Form.useForm()
+  //python表单数据
+  const [PythonDataForm] = Form.useForm()
+  
+  //当前选择的作业类型
+  const [currentJobType, setCurrentJobType] = useState('')
+  
+  const JobTagInputRef = useRef(null);
+
+  const [tagName, setTagName] = useState('');
+  
+  const [dagData, setDagData] = useState()
+
+  //动态改变作业分类的值
+  const onNameChange = (event) => {
+    setTagName(event.target.value);
+  };
+
+  //添加自定义作业分类
+  const addTagItem = (e) => {
+    if (tagName) {
+      console.log(tagName);
+      e.preventDefault();
+      setJobTags([...jobTags,tagName])
+      setTagName('')
+      setTimeout(() => {
+        JobTagInputRef.current?.focus();
+      }, 0);
+    } else {
+      message.error('请输入自定义作业分类名称')
+    }
+  };
 
   // 设置单选框value值
-  const onChange = e => {
-    console.log('radio checked', e.target.value)
-    setValue(e.target.value)
-  }
-
+  const onChange = (e) => {
+    console.log('radio checked', e.target.value);
+    setValue(e.target.value);
+  };
+  
   //上传文件配置
   const UpProps: UploadProps = {
     name: 'file',
@@ -180,30 +251,39 @@ export default function JobCreate() {
     // 上传文件提交状态
     onChange(info) {
       if (info.file.status !== 'uploading') {
-        console.log(info.file, info.fileList)
+        console.log(info.file, info.fileList);
       }
       if (info.file.status === 'done') {
-        message.success(`${info.file.name} file uploaded successfully`)
+        message.success(`${info.file.name} file uploaded successfully`);
       } else if (info.file.status === 'error') {
-        message.error(`${info.file.name} file upload failed.`)
+        message.error(`${info.file.name} file upload failed.`);
       }
     },
-  }
+  };
 
   //根据作业类型做出判断
-  const onGenderChange = value => {
-    if (value === 'Java') {
-      setJsIsShow('block')
+  const onGenderChange = (value) => {
+    if (value === "java") {
+      setJaIsShow('block')
       setDagIsShow('none')
-      setPyIsShow('none')
-    } else if (value === 'Python') {
-      setJsIsShow('none')
+      setPyIsShow('none') 
+      setCurrentJobType('Java')
+      setCurrentForm(JavaDataForm)
+    }
+    else if (value === "python") {
+      setJaIsShow('none')
       setDagIsShow('none')
       setPyIsShow('block')
-    } else if (value === 'Dag') {
-      setJsIsShow('none')
+      setCurrentJobType('Python')
+      setCurrentForm(PythonDataForm)
+
+    }
+    else if (value === "DAG") {
+      setJaIsShow('none')
       setDagIsShow('block')
       setPyIsShow('none')
+      setCurrentJobType('Dag')
+      setCurrentForm(ConfigDataForm)
     }
   }
 
@@ -212,287 +292,480 @@ export default function JobCreate() {
     setCurrentStep(currentStep + num)
   }
 
+  //提交DAG
+  const DagSubmit = async () => {
+    const data =  await createJob({...ConfigDataForm.getFieldValue(),'script_file': '', 'type': currentJobType, 'dag_uuid': 'test', 'user_id': 'test', 'project_id': 'test', 'image_url': 'test', 'relation_list': []})
+  }
+
   //下一步
   const nextStep = () => {
-    changeStep(1)
+    currentForm.validateFields().then(() => {
+        // finishSubmit()
+        changeStep(1)
+        console.log('Successfully');
+
+      })
+      .catch(err => { 
+        console.log(err,currentForm.getFieldValue());
+        message.error('请检查表单数据是否完整')
+      })
+    if (currentStep === 2) {
+      DagSubmit()
+      navigate(-1)
+    } 
   }
 
   useEffect(() => {
     switch (currentStep) {
       case 0:
-        setCurrentForm(drawDataForm)
-        console.log(drawDataForm)
+        setCurrentForm(ConfigDataForm)
+        console.log(ConfigDataForm.getFieldValue());
+        break
+      case 1:
+        setCurrentForm(InputDataForm)
+        break
+      case 2:
+        setCurrentForm(OutputDataForm)
         break
       default:
         break
     }
-  }, [currentStep])
+    getJobType()
+      bus.on('DAGSend', data => {
+      console.log('-----------09090---------------------');
+      console.log(data);
+      setDagData(data)
+    })
+    bus.emit('DAGSend',dagData)
+  },[currentStep])
+  
+  //获取作业类型和分类
+  const getJobType = async () => {
+      const JobTypes = await getJobTypes('作业类型')
+      const JobTags = await getJobTypes('作业分类')
+      if (JobTypes.data.length !== 0) {
+      setJobTypeOptions(JobTypes.data.data.map(item => {
+        return {
+          label: item,
+          value: item
+        }
+      }))
+      setJobTags(JobTags.data.data)
+    }
+    }
+
+    const finishSubmit = async () => {
+      console.log(currentForm.getFieldValue());
+      const params = {...currentForm.getFieldValue(), 'type': currentJobType, 'dag_uuid': 'test', 'user_id': 'test', 'project_id': 'test', 'dag_url': 'test', 'image_url': 'test', 'relation_list': []}
+      console.log(params);
+      await createJob(params)
+      navigate(-1)
+    }
+
+    //java or python提交
+    const JaPySubmit = () => {
+      console.log(currentJobType)
+      const Jay = JavaDataForm.getFieldValue()
+      currentForm.validateFields().then(() => {
+        console.log(currentForm.getFieldValue());
+        finishSubmit()
+        console.log('Successfully');
+
+      })
+      .catch(err => { 
+        message.error('请检查表单数据是否完整')
+        console.log(err);
+      })
+      // bus.emit('sendDataForm',{
+      //   Jay,
+      // })
+    }
+  const cancel = () => {
+    navigate(-1)
+  }
   return (
     <JobCre>
-      <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
+      <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)
-              }}>
-              上一步
+        label="选择作业类型"
+        rules={[
+          {
+            required: true,
+          },
+        ]}
+      >
+        <Select
+          placeholder="请选择作业类型..."
+          onSelect={onGenderChange}
+          value = {value}
+          options={jobTypeOptions}
+        />
+      </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
+          ConfigDataForm={ConfigDataForm}
+        />
+      )}
+
+      {/* 第二步 */}
+      {currentStep === 1 && (
+        <JobStepTwo
+          InputDataForm={InputDataForm}
+        />
+      )}
+
+      {/* 第三步 */}
+      {currentStep === 2 && (
+        <JobStepThree
+          OutputDataForm={OutputDataForm}
+        />
+      )}
+
+    <Space style={{ margin: '20px' }}>
+      <Button onClick={
+        () => {
+          if (currentStep !== 0) {
+            changeStep(-1)
+          } else {
+            navigate(-1)
+          }
+        }}
+        >{currentStep === 0 ? '取消' : '上一步'}</Button>
+      <Button type="primary" onClick={nextStep}>{currentStep === 2 ? '提交' : '下一步'}</Button>
+    </Space>
+    </div>
+    
+
+    {/* 配置Java作业信息 */}
+    <div className="JaPyInfo" style={{display: JaIsShow}}>
+      <div className='creTitle'>
+        <div className='bluetTitle' />
+        <span className='creText'>配置作业信息</span>
+      </div>  
+
+      {/* 输入作业名称 */}
+      <Form {...layout} form={JavaDataForm} name="control-hooks" >
+      <FormItem
+        name="name"
+        label="作业名称"
+        className="JobName"
+        rules={[
+          {
+            required: true,
+            message: '请输入作业名称'
+          },
+        ]}
+      >
+        <Input
+          placeholder="请输入作业名称..."
+          allowClear
+        >
+        </Input>
+      </FormItem>
+
+    {/* 选择作业分类 */}
+      <FormItem
+        shouldUpdate
+        name="tag"
+        label="作业分类"
+        className="JobName"
+        rules={[
+          {
+            required: true,
+            message: '请选择作业分类',
+          },
+        ]}
+      >
+        <Select
+          placeholder="请选择作业分类..."
+          allowClear
+          dropdownRender={(menu) => (
+        <>
+          {menu}
+          <Divider
+            style={{
+              margin: '8px 0',
+            }}
+          />
+          <Space
+            style={{
+              padding: '0 8px 4px',
+            }}
+          >
+            <Input
+              placeholder="添加作业分类"
+              ref={JobTagInputRef}
+              value={tagName}
+              onChange={onNameChange}
+            />
+            <Button type="text" icon={<PlusOutlined />} onClick={addTagItem}>
+              添加分类
+            </Button>
+          </Space>
+        </>
+      )}
+        >
+        {jobTags.map((item) => (
+          <Option key={item}>{item}</Option>
+          ))
+        }
+        </Select>
+      </FormItem>
+
+    {/* 选择执行镜像 */}
+      <FormItem
+        className='mirrorLeft MMir'
+        name="dag_url"
+        label="配置执行的镜像"
+        rules={[
+          {
+            required: true,
+            message: '请选择配置执行的镜像',
+          },
+        ]}
+      >
+        <Select
+          placeholder="请选择镜像..."
+          allowClear
+        >
+          <Option value="/test/images/example">/test/images/example</Option>
+        </Select>
+      </FormItem>
+
+    {/* 选择执行的Java脚本 */}
+      <FormItem
+        className='mirrorLeft choseJa script_file'
+        label="配置执行的Java脚本"
+        name="script_file"
+        rules={[
+          {
+            required: true,
+            message: '请选择配置执行的Java脚本',
+          },
+        ]}
+      >
+      <RadioGroup onChange={onChange} value={value}>
+      <Space direction="vertical" className='jsSel'>
+        <Radio value={'fromList'}>
+        <Select
+          placeholder="在工作目录中选择"
+          allowClear
+          className='javaSelect'
+          disabled={value === 'fromList' ? false : true}
+        >
+          <Option value="/test/scripts/example">/test/scripts/example</Option>
+        </Select>
+        </Radio>
+        
+        <Radio value={'fromLocal'}>
+          <Upload {...UpProps}>
+            <Button 
+            disabled={value === 'fromLocal' ? false : true}
+            className='upButton'>
+            本地上传
             </Button>
-            <Button type="primary" onClick={nextStep}>
-              下一步
+          </Upload>
+        </Radio>
+      </Space>
+    </RadioGroup>
+    </FormItem>
+    <FormItem>
+    <div className="JaPySubmit">
+      <div className="Cancel">
+        <Button onClick={cancel}>取消</Button>
+      </div>
+      <div className="Submit">
+        <Button onClick={JaPySubmit}>提交</Button>
+      </div>
+    </div>
+    </FormItem>
+    </Form>
+    
+    
+    </div>
+    
+    {/* 配置Python作业信息 */}
+    <div className="JaPyInfo" style={{display: PyIsShow}}>
+      <div className='creTitle'>
+        <div className='bluetTitle' />
+        <span className='creText'>配置作业信息</span>
+      </div>  
+
+      {/* 输入作业名称 */}
+      <Form {...layout} form={PythonDataForm} name="control-hooks" >
+      <FormItem
+        name="name"
+        label="作业名称"
+        className="JobName"
+        rules={[
+          {
+            required: true,
+            message: '请输入作业名称'
+          },
+        ]}
+      >
+        <Input
+          placeholder="请输入作业名称..."
+          allowClear
+        >
+        </Input>
+      </FormItem>
+    {/* 选择作业分类 */}
+      <FormItem
+        name="tag"
+        label="作业分类"
+        className='JobName'
+        rules={[
+          {
+            required: true,
+            message: '请选则作业分类'
+          },
+        ]}
+      >
+        <Select
+          placeholder="请选择作业分类..."
+          allowClear
+          dropdownRender={(menu) => (
+        <>
+        {menu}
+          <Divider
+            style={{
+              margin: '8px 0',
+            }}
+          />
+          <Space
+            style={{
+              padding: '0 8px 4px',
+            }}
+          >
+            <Input
+              placeholder="添加作业分类"
+              ref={JobTagInputRef}
+              value={tagName}
+              onChange={onNameChange}
+            />
+            <Button type="text" icon={<PlusOutlined />} onClick={addTagItem}>
+              添加分类
             </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>
-  )
-}
+        </>
+      )}
+        >
+        {jobTags.map((item) => (
+          <Option key={item}>{item}</Option>
+          ))
+        }
+        </Select>
+      </FormItem>
+    {/* 选择执行镜像 */}
+      <FormItem
+        className='mirrorLeft MMir'
+        name="dag_url "
+        label="配置执行的镜像"
+        rules={[
+          {
+            required: true,
+            message: '请配置执行的镜像'
+          },
+        ]}
+      >
+        <Select
+          placeholder="请选择镜像..."
+          allowClear
+        >
+          <Option value="test">test</Option>
+        </Select>
+      </FormItem>
+
+    {/* 选择执行的Java脚本 */}
+      <FormItem
+        className='mirrorLeft choseJa script_file'
+        label="配置执行的Java脚本"
+        name="script_file"
+        rules={[
+          {
+            required: true,
+            message: '请配置执行的Java脚本'
+          },
+        ]}
+      >
+      <RadioGroup onChange={onChange} value={value} className='PyScript_file'>
+      <Space direction="vertical">
+        <Radio value={'fromList'}>
+        <Select
+          placeholder="在工作目录中选择"
+          allowClear
+          className='javaSelect'
+          disabled={value === 'fromList' ? false : true}
+        >
+          <Option value="test">test</Option>
+        </Select>
+        </Radio>
+        <Radio value={'fromLocal'}>
+          <Upload {...UpProps}>
+            <Button  
+            className='upButton'
+            disabled={value === 'fromLocal' ? false : true}>
+            本地上传
+            </Button>
+          </Upload>
+        </Radio>
+      </Space>
+      </RadioGroup>
+      </FormItem>
+      <FormItem>
+    <div className="JaPySubmit">
+      <div className="Cancel">
+        <Button onClick={cancel}>取消</Button>
+      </div>
+      <div className="Submit">
+        <Button onClick={JaPySubmit}>提交</Button>
+      </div>
+    </div>
+    </FormItem>
+    </Form>
+    </div>     
+    </CreContent>
+  </JobCre>
+  );
+};

+ 179 - 124
src/module/workmgmt/component/JobItems.jsx

@@ -1,26 +1,39 @@
-import { Button, Form, Input, Popconfirm, Table } from 'antd'
-import React, { useContext, useEffect, useRef, useState } from 'react'
+/* eslint-disable jsx-a11y/anchor-is-valid */
+import { Button, Form, Input, message, Popconfirm, Table } from 'antd';
+import React, { useContext, useEffect, useRef, useState, props, useRoutes } from 'react';
 import styled from 'styled-components'
-import { Link } from 'react-router-dom'
-const EditableContext = React.createContext(null)
+import { Link } from 'react-router-dom';
+import bus from '../../../bus.js'
+import { getJobDataList, deleteJob, getJobInfo  } from '../services'
+import {routes} from '../../../routes/index.js'
+const EditableContext = React.createContext(null);
 const FormItem = Form.Item
 
 const JobItems = styled.div`
+  background-color: #FFFFFF;
+  height: 45vw;
   margin-left: 24px;
   .delButton {
-    margin-left: 40px;
+  margin-left: 40px;
   }
-`
+  .ant-table-wrapper {
+  margin-right: 12px;
+  .ant-table {
+  margin-left: 16px;
+    }
+  }
+  
+  `
 const EditableRow = ({ index, ...props }) => {
-  const [form] = Form.useForm()
+  const [form] = Form.useForm();
   return (
     <Form form={form} component={false}>
       <EditableContext.Provider value={form}>
         <tr {...props} />
       </EditableContext.Provider>
     </Form>
-  )
-}
+  );
+};
 
 const EditableCell = ({
   title,
@@ -31,33 +44,33 @@ const EditableCell = ({
   handleSave,
   ...restProps
 }) => {
-  const [editing, setEditing] = useState(false)
-  const inputRef = useRef(null)
-  const form = useContext(EditableContext)
+  const [editing, setEditing] = useState(false);
+  const inputRef = useRef(null);
+  const form = useContext(EditableContext);
   useEffect(() => {
     if (editing) {
-      inputRef.current.focus()
+      inputRef.current.focus();
     }
-  }, [editing])
+  }, [editing]);
 
   const toggleEdit = () => {
-    setEditing(!editing)
+    setEditing(!editing);
     form.setFieldsValue({
       [dataIndex]: record[dataIndex],
-    })
-  }
+    });
+  };
 
   const save = async () => {
     try {
-      const values = await form.validateFields()
-      toggleEdit()
-      handleSave({ ...record, ...values })
+      const values = await form.validateFields();
+      toggleEdit();
+      handleSave({ ...record, ...values });
     } catch (errInfo) {
-      console.log('Save failed:', errInfo)
+      console.log('Save failed:', errInfo);
     }
-  }
+  };
 
-  let childNode = children
+  let childNode = children;
 
   if (editable) {
     childNode = editing ? (
@@ -71,7 +84,8 @@ const EditableCell = ({
             required: true,
             message: `${title} is required.`,
           },
-        ]}>
+        ]}
+      >
         <Input ref={inputRef} onPressEnter={save} onBlur={save} />
       </FormItem>
     ) : (
@@ -80,60 +94,98 @@ const EditableCell = ({
         style={{
           paddingRight: 24,
         }}
-        onClick={toggleEdit}>
+        onClick={toggleEdit}
+      >
         {children}
       </div>
-    )
+    );
   }
 
-  return <td {...restProps}>{childNode}</td>
-}
+  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 getJobTables = async () => {
+    const project_id = 'test'
+    const { data } = await getJobDataList(project_id)
+    if (data.code === 200) {
+      const list = data.data.map(item => {
+        return {
+          key: item.id,
+          name: item.name,
+          type: item.type,
+          tag: item.tag,
+          create_time: item.create_time,
+          update_time: item.update_time,
+        }
+      })
+      setDataSource(list)
+    }
+  }
+  
+
+
+  // componentDidMount
+  useEffect(() => {
+    getJobTables()
+  },[])
+  const [dataSource, setDataSource] = useState();
+  //   [
+  //   {
+  //     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 [JobData, setJobData] =useState()
 
-  const handleDelete = key => {
-    const newData = dataSource.filter(item => item.key !== key)
-    setDataSource(newData)
+  //删除作业
+  const handleDelete = async (key) => {
+    const { data } = await deleteJob(key)
+    if (data.code === 200) {
+      const newData = dataSource.filter((item) => item.key !== key);
+      setDataSource(newData);
+      message.success('删除成功');
+    } else {
+      message.error('删除失败')
+    }
+    
+  };
+  
+  const editJobitem = async(key) => {
+    const data = await getJobInfo(key)
+    setJobData(data)
+  }
+
+  // 格式化事件
+  const formatTime = time => {
+    const date = new Date(Number(time) * 1000)
+    const YY = date.getFullYear()
+    const MM =
+      date.getMonth() + 1 < 10
+        ? '0' + (date.getMonth() + 1)
+        : date.getMonth() + 1
+    const DD = date.getDate() < 10 ? '0' + date.getDate() : date.getDate()
+    const hh = date.getHours() < 10 ? '0' + date.getHours() : date.getHours()
+    const mm =
+      date.getMinutes() < 10 ? '0' + date.getMinutes() : date.getMinutes()
+    const ss =
+      date.getSeconds() < 10 ? '0' + date.getSeconds() : date.getSeconds()
+    return YY + '-' + MM + '-' + DD + ' ' + hh + ':' + mm + ':' + ss
   }
 
   const defaultColumns = [
@@ -149,18 +201,21 @@ const App = () => {
     },
     {
       title: '作业分类',
-      dataIndex: 'sort',
+      dataIndex: 'tag',
       width: '16.6%',
+
     },
     {
       title: '创建时间',
-      dataIndex: 'creTime',
+      dataIndex: 'create_time',
       width: '16.6%',
+      render: time => formatTime(time),
     },
     {
       title: '更新时间',
-      dataIndex: 'updTime',
+      dataIndex: 'update_time',
       width: '16.6%',
+      render: time => formatTime(time),
     },
     {
       title: '操作',
@@ -170,79 +225,79 @@ const App = () => {
       render: (_, record) =>
         dataSource.length >= 1 ? (
           <>
-            <Popconfirm>
-              <a>编辑</a>
-            </Popconfirm>
-            <Popconfirm
-              title="Sure to delete?"
-              onConfirm={() => handleDelete(record.key)}>
-              <a className="delButton">删除</a>
+            <Link to={'/work-management/cre?data=' + JobData}>
+              <Button onClick={() => editJobitem(record.key)}>
+                编辑
+              </Button>
+            </Link>
+            
+            <Popconfirm 
+            title="确认删除?" 
+            okText="确认"
+            cancelText="取消"
+            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 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 => {
+  };
+  const columns = defaultColumns.map((col) => {
     if (!col.editable) {
-      return col
+      return col;
     }
 
     return {
       ...col,
-      onCell: record => ({
+      onCell: (record) => ({
         record,
         editable: col.editable,
         dataIndex: col.dataIndex,
         title: col.title,
         handleSave,
       }),
-    }
-  })
+    };
+  });
+  useEffect (() => {
+    bus.on('sendDataForm',data => {
+      
+    })
+  },[])
   return (
     <JobItems>
-      <Link to="/cre">
+      <Link to="/work-management/cre">
         <Button
-          onClick={handleAdd}
-          type="primary"
-          style={{
-            float: 'right',
-            marginBottom: 16,
-            marginTop: '18px',
-            marginRight: '16px',
-            fontSize: '12px',
-          }}>
-          创建作业
-        </Button>
+        type="primary"
+        style={{
+          float: 'right',
+          marginBottom: 16,
+          marginTop: '18px',
+          marginRight: '16px',
+          fontSize: '12px',
+        }}
+      >
+        创建作业
+      </Button>
       </Link>
-
+      
       <Table
         components={components}
         rowClassName={() => 'editable-row'}
@@ -251,7 +306,7 @@ const App = () => {
         columns={columns}
       />
     </JobItems>
-  )
-}
+  );
+};
 
-export default App
+export default App;

+ 104 - 23
src/module/workmgmt/component/JobStepOne.jsx

@@ -1,9 +1,14 @@
-import { Button, Form, Input, Select, Radio, Space, Upload, Steps } from 'antd';
+import { Button, Form, Input, Select, Radio, Space, Upload, Steps, Divider } from 'antd';
+import { UploadOutlined, PlusOutlined } from '@ant-design/icons';
 import setFieldValue from 'antd';
-import React, { useState , Component , useEffect } from 'react';
+import React, { useState , Component , useEffect, useRef } from 'react';
+import bus from '../../../bus.js'
+import ButtonGroup from 'antd/lib/button/button-group.js';
+import { getJobTypes, getDagFile } from '../services'
 const { Option } = Select;
 const FormItem = Form.Item
 
+
 const layout = {
   labelCol: {
     span: 8,
@@ -19,25 +24,72 @@ const tailLayout = {
   },
 };
 
+export default function JobStepOne({ ConfigDataForm }) {
+  const [form] = Form.useForm();
+  
+  const JobTagInputRef = useRef(null);
+  //自定义作业分类名称
+  const [tagName, setTagName] = useState('');
+  //作业分类
+  const [jobTags, setJobTags] = useState([])
 
+  const [dags, setDags] = useState([])
 
-export default function JobStepOne({ drawDataForm }) {
-  const [form] = Form.useForm();
+  useEffect(() => {
+    const DJName = ConfigDataForm.getFieldValue('DagJobName')
+    if (DJName) {
+      ConfigDataForm.setFieldValue('DagJobName',DJName)
+      console.log(ConfigDataForm)
+    }
+    getJobType()
+    getDags()
+  },[])
   
-useEffect(() => {
-  const DJName = drawDataForm.getFieldValue('DagJobName')
-  if (DJName) {
-    drawDataForm.setFieldValue('DagJobName',DJName)
-    console.log(drawDataForm)
+  //获取作业分类
+  const getJobType = async () => {
+    const JobTags = await getJobTypes('作业分类')
+    console.log(JobTags);
+    if (JobTags.data.code === 200) {
+      setJobTags(JobTags.data.data)
+    }
   }
-},[])
+  
+  //获取DAG
+  const getDags = async () => {
+    const params = {
+      project_id: 'test',
+      user_id: 'test',
+    }
+    const data = await getDagFile(params)
+    setDags(data.data.data)
 
+  }
+
+  const onNameChange = (event) => {
+    setTagName(event.target.value);
+  };
+  
+  //添加自定义作业分类
+  const addTagItem = (e) => {
+    e.preventDefault();
+    setJobTags([...jobTags,tagName])
+    setTagName('')
+    setTimeout(() => {
+      JobTagInputRef.current?.focus();
+    }, 0);
+  };
+
+  //向第二步传递选择的DAG算子
+  const sendDag = () => {
+    const choseDag = ConfigDataForm.getFieldValue().DagMirror
+    bus.emit('DAGSend',choseDag)
+    console.log(ConfigDataForm.getFieldValue().DagMirror);
+  }
   return (
     <>
-    <Form  {...layout} form={drawDataForm} name="control-hooks" >
+    <Form  {...layout} form={ConfigDataForm} name="control-hooks" >
       <FormItem
-        name="DagJobName
-        "
+        name="name"
         label="作业名称"
         rules={[
           {
@@ -48,13 +100,14 @@ useEffect(() => {
         <Input
           placeholder="请输入作业名称..."
           allowClear
+          // onChange={}
         >
         </Input>
       </FormItem>
     
     {/* 作业分类选择 */}
       <FormItem
-        name="DagJobSort"
+        name="tag"
         label="作业分类"
         rules={[
           {
@@ -65,32 +118,60 @@ useEffect(() => {
         <Select
           placeholder="请选择作业分类..."
           allowClear
+          dropdownRender={(menu) => (
+        <>
+          {menu}
+          <Divider
+            style={{
+              margin: '8px 0',
+            }}
+          />
+          <Space
+            style={{
+              padding: '0 8px 4px',
+            }}
+          >
+            <Input
+              placeholder="添加作业分类"
+              ref={JobTagInputRef}
+              value={tagName}
+              onChange={onNameChange}
+            />
+            <Button type="text" icon={<PlusOutlined />} onClick={addTagItem}>
+              添加分类
+            </Button>
+          </Space>
+        </>
+      )}
         >
-          <Option value="Java">Java</Option>
-          <Option value="Python">Python</Option>
-          <Option value="Dag">Dag</Option>
+        {jobTags.map((item) => (
+          <Option key={item}>{item}</Option>
+          ))
+        }
         </Select>
       </FormItem>
 
     {/* 选择执行镜像 */}
       <FormItem
         className='mirrorLeft'
-        name="DagMirror
-        "
+        name="dag_url"
         label="选择DAG算子"
         rules={[
           {
             required: true,
+            message: '请选择DAG算子',
           },
         ]}
       >
         <Select
           placeholder="请选择DAG算子"
           allowClear
-        >
-          <Option value="Java">Java</Option>
-          <Option value="Python">Python</Option>
-          <Option value="Dag">Dag</Option>
+          onSelect={sendDag}
+          >
+          {dags.map((item) => (
+          <Option key={item}>{item}</Option>
+          ))
+        }
         </Select>
       </FormItem>
     </Form>

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

@@ -0,0 +1,284 @@
+import { Alert,Button, Form, Input, Select, Radio, Space, Upload, Steps } from 'antd';
+import styled from 'styled-components';
+import { getDagInfomation, getDataSourceInfo, getTableNameInfo } from '../services'
+import { useEffect, useState } from 'react'
+import bus from '../../../bus.js'
+
+
+const StepTwo = styled.div`
+  display: flex;
+  .StepTwo-content {
+
+    width: 847px; 
+    height: 450px; 
+    margin-left: 50px; 
+    margin-top: 20px; 
+    overflow-y: scroll;
+    overflow-y: hidden;
+    border: 1px solid #C8D3E9;
+    .dtsource {
+      .ant-select {
+        width:80%;
+      }
+    }
+    .ant-row {    
+      margin-left: 37px;
+      flex-wrap: nowrap;
+    }
+    .content-item {
+      margin-top: 17px;
+      margin-left: -14px;
+      .ant-form {
+        flex-direction: row;
+        justify-content: left;
+        .ant-form-item {
+          margin-bottom: 10px;
+        }
+      }
+      .item-choseList {
+        margin-top: -3px;
+        margin-left: -75px;
+        .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;
+        left: 175px;
+        position: absolute;
+        top: 390px;
+      }
+      .form {
+        flex-wrap: nowrap;
+      }
+    }
+  }
+  .structure-detail {
+    display: flex;
+    width: 416px;
+    height: 450px;
+    border: 1px solid #C8D3E9;
+    margin-top: 20px;
+    margin-left:60px;
+    border-radius: 2px;
+    flex-wrap: wrap;
+    flex-direction: column;
+    .detail-title {
+      width: 100%;
+      height: 44px;
+      margin-top: 26px;
+      color: #4A4A4A;
+      border-bottom: 1px solid #C8D3E9;
+      .datasourceFont {
+        margin-left: 85px;     
+      }
+      .schemaFont {
+        margin-left: 115px;
+      }
+    }
+    .detail-item {
+      display: flex;
+      .icon {
+        display: inline-block;
+        text-align: center;
+        height: 40px;
+        width: 50px;
+        margin-top: 10px;
+        margin-left: 7px;
+        color: #C8D3E9;
+        line-height: 50px;
+      }
+      .dataSource {
+        margin-left: 41px;
+        margin-top: 13px;
+        width: 130px;
+        height: 33px;
+        line-height: 33px;
+        text-align: center;
+        background-color: #EEF5FE;
+        border-radius: 2px;
+      }
+      .Dagdatasource {
+        margin-left: 10px;
+      }
+    }
+    
+  }
+`
+const FormItem = Form.Item
+const { Option } = Select;
+
+export default function JobStepThree({ OutputDataForm }) {
+  let noden = null;
+
+  const [choseDag,setChoseDag] = useState(null)
+
+  const [node,setNode] = useState(null)
+
+  const [dagName,setDagName] = useState(null)
+  //获取数据源
+  //数据源名称
+  const [datasourceName,setDatasourceName] = useState()
+  const [datasourceNam,setDatasourceNam] = useState()
+
+  //数据源ID
+  const [datasourceID,setDatasourceID] = useState()
+  const [datasourceI,setDatasourceI] = useState()
+
+  const [detailIsSHow,setDetailIsSHow] = useState('none')
+
+  const getDagInfo = async () => {
+    // console.log('----===');
+    // console.log(choseDag);    
+    // console.log('---===');
+    const data = await getDagInfomation('/test.dag')
+    // console.log(data);
+    if(data.status === 200) {
+      noden = data.data.nodes.find(item => item.op === 'datasource')
+      // const node = data.data.nodes.find(item => item.op === 'datasource')
+      // console.log(noden);
+      setNode(noden)
+      setDagName(noden.name)
+    }
+  }
+
+  const getDataSource = async () => {
+    const params = {
+      page: 1,
+      size: 100
+    }
+    //////
+    const data = await getDataSourceInfo(params)
+    console.log('------------------------------------------------');
+    console.log(data);
+    console.log('------------------------------------------------');
+    console.log(data.data.data.items[0].id);
+    setDatasourceNam(data)
+    setDatasourceName(data.data.data.items[0].datasource_name)
+    setDatasourceI(data)
+    setDatasourceID(data.data.data.items[0].id)
+    if(data.data.code === 200){
+      getTableName()
+    }
+  }
+
+  const getTableName = async () => {
+    const data = await getTableNameInfo(datasourceID)
+     data = await getTableNameInfo(datasourceID)
+
+    console.log(data);
+  }
+  const showStructure = () => {
+    setDetailIsSHow('block')
+  }
+  const tableData =[
+    "datax_plugin",
+    "grades",
+    "grades1",
+    "grades2",
+    "job_group",
+    "job_group_copy1",
+    "job_group_copy2",
+    "job_info",
+    "job_info_copy1",
+    "job_jdbc_datasource",
+    "job_lock",
+    "job_log",
+    "job_log_report",
+    "job_logglue",
+    "job_permission",
+    "job_registry",
+    "job_template",
+    "job_user"
+  ]
+  useEffect(() => {
+    bus.on('DAGSend', data => {
+      if (data !== ''){
+      }
+    })
+    getDagInfo()
+    getDataSource()
+  }, []);
+  return (
+    <>
+      <StepTwo>
+      <div className='StepTwo-content'>
+        <div className='content-item'>
+          <Form name="control-hooks" form={OutputDataForm} className="form">
+            <FormItem
+            name="sort"
+            label={dagName}
+            className="dtsource"
+            >
+              <Select
+              allowClear
+              >
+              {/*  */}
+                <Option value={datasourceName}>{datasourceName}</Option>
+              </Select>
+            </FormItem>
+            <FormItem
+            label="选择表1"
+            className='item-choseList'>
+              <Select
+              allowClear
+              >
+                {tableData.map((item) => (
+                  <Option key={item}>{item}</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' style={{display: detailIsSHow}}>
+        <div className='detail-title'>
+          <span className='datasourceFont'>数据源1</span>
+          <span className='schemaFont'>Dag输入源结构</span>
+        </div>
+        <div className='detail-item'> 
+          <div className='dataSource'>
+            <span>表1字段1.string</span>
+          </div>
+          <span className='icon'><svg t="1663331186772"  viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2086" width="20" height="20"><path d="M398.222222 398.222222h170.666667v56.888889H398.222222V398.222222z m-341.333333 170.666667h227.555555v56.888889H56.888889v-56.888889z m910.222222-113.777778h-227.555555V398.222222h227.555555v56.888889zM398.222222 853.333333H341.333333V398.222222h56.888889v455.111111z m540.444445 0H398.222222v-56.888889h512V455.111111h56.888889v398.222222h-28.444444zM85.333333 170.666667H625.777778v56.888889H113.777778v341.333333H56.888889V170.666667h28.444444z m568.888889 455.111111H455.111111v-56.888889h170.666667V170.666667h56.888889v455.111111h-28.444445z" fill="#333333" p-id="2087"></path></svg></span>
+          <div className='dataSource Dagdatasource'>
+            <span>表1字段1.string</span>
+          </div>
+        </div>
+      </div>
+    </StepTwo>
+    </>
+    
+  )
+}

+ 185 - 18
src/module/workmgmt/component/JobStepTwo.jsx

@@ -1,19 +1,33 @@
 import { Alert,Button, Form, Input, Select, Radio, Space, Upload, Steps } from 'antd';
 import styled from 'styled-components';
+import { getDagInfomation, getDataSourceInfo, getTableNameInfo } from '../services'
+import { useEffect, useState } from 'react'
+import bus from '../../../bus.js'
+
+
 const StepTwo = styled.div`
   display: flex;
   .StepTwo-content {
-    width: 867px; 
+
+    width: 847px; 
     height: 450px; 
     margin-left: 50px; 
     margin-top: 20px; 
-    overflow: scroll;
+    overflow-y: scroll;
+    overflow-y: hidden;
     border: 1px solid #C8D3E9;
+    .dtsource {
+      .ant-select {
+        width:80%;
+      }
+    }
     .ant-row {    
       margin-left: 37px;
+      flex-wrap: nowrap;
     }
     .content-item {
       margin-top: 17px;
+      margin-left: -14px;
       .ant-form {
         flex-direction: row;
         justify-content: left;
@@ -22,6 +36,8 @@ const StepTwo = styled.div`
         }
       }
       .item-choseList {
+        margin-top: -3px;
+        margin-left: -75px;
         .ant-select {
           width: 158px;
         }
@@ -39,6 +55,12 @@ const StepTwo = styled.div`
         display: flex;
         margin-left: 137px;
         color: #7D7D7D;
+        left: 175px;
+        position: absolute;
+        top: 390px;
+      }
+      .form {
+        flex-wrap: nowrap;
       }
     }
   }
@@ -50,46 +72,181 @@ const StepTwo = styled.div`
     margin-top: 20px;
     margin-left:60px;
     border-radius: 2px;
+    flex-wrap: wrap;
+    flex-direction: column;
+    .detail-title {
+      width: 100%;
+      height: 44px;
+      margin-top: 26px;
+      color: #4A4A4A;
+      border-bottom: 1px solid #C8D3E9;
+      .datasourceFont {
+        margin-left: 85px;     
+      }
+      .schemaFont {
+        margin-left: 115px;
+      }
+    }
+    .detail-item {
+      display: flex;
+      .icon {
+        display: inline-block;
+        text-align: center;
+        height: 40px;
+        width: 50px;
+        margin-top: 10px;
+        margin-left: 7px;
+        color: #C8D3E9;
+        line-height: 50px;
+      }
+      .dataSource {
+        margin-left: 41px;
+        margin-top: 13px;
+        width: 130px;
+        height: 33px;
+        line-height: 33px;
+        text-align: center;
+        background-color: #EEF5FE;
+        border-radius: 2px;
+      }
+      .Dagdatasource {
+        margin-left: 10px;
+      }
+    }
+    
   }
 `
 const FormItem = Form.Item
 const { Option } = Select;
 
-export default function JobStepTwo() {
-  
-  const showStructure = () => {
+export default function JobStepTwo({ InputDataForm }) {
+  let noden = null;
+
+  const [form] = Form.useForm();
+
+  const [choseDag,setChoseDag] = useState(null)
 
+  const [node,setNode] = useState(null)
+
+  const [dagName,setDagName] = useState(null)
+  //获取数据源
+  //数据源名称
+  const [datasourceName,setDatasourceName] = useState()
+  const [datasourceNam,setDatasourceNam] = useState()
+
+  //数据源ID
+  const [datasourceID,setDatasourceID] = useState()
+  const [datasourceI,setDatasourceI] = useState()
+
+  const [detailIsSHow,setDetailIsSHow] = useState('none')
+
+  const getDagInfo = async () => {
+    // console.log('----===');
+    // console.log(choseDag);    
+    // console.log('---===');
+    const data = await getDagInfomation('/test.dag')
+    // console.log(data);
+    if(data.status === 200) {
+      noden = data.data.nodes.find(item => item.op === 'datasource')
+      // const node = data.data.nodes.find(item => item.op === 'datasource')
+      // console.log(noden);
+      setNode(noden)
+      setDagName(noden.name)
+    }
+  }
+
+  const getDataSource = async () => {
+    const params = {
+      page: 1,
+      size: 100
+    }
+    //////
+    const data = await getDataSourceInfo(params)
+    console.log('------------------------------------------------');
+    console.log(data);
+    console.log('------------------------------------------------');
+    console.log(data.data.data.items[0].id);
+    setDatasourceNam(data)
+    setDatasourceName(data.data.data.items[0].datasource_name)
+    setDatasourceI(data)
+    setDatasourceID(data.data.data.items[0].id)
+    if(data.data.code === 200){
+      getTableName()
+    }
   }
-  
+
+  const getTableName = async () => {
+    const data = await getTableNameInfo(datasourceID)
+     data = await getTableNameInfo(datasourceID)
+
+    console.log(data);
+  }
+  const showStructure = () => {
+    setDetailIsSHow('block')
+    console.log(InputDataForm.getFieldValue());
+  }
+  const tableData =[
+    "datax_plugin",
+    "grades",
+    "grades1",
+    "grades2",
+    "job_group",
+    "job_group_copy1",
+    "job_group_copy2",
+    "job_info",
+    "job_info_copy1",
+    "job_jdbc_datasource",
+    "job_lock",
+    "job_log",
+    "job_log_report",
+    "job_logglue",
+    "job_permission",
+    "job_registry",
+    "job_template",
+    "job_user"
+  ]
+  useEffect(() => {
+    bus.on('DAGSend', data => {
+      if (data !== ''){
+      }
+    })
+    const DJName = InputDataForm.getFieldValue('choseTable')
+    if (DJName) {
+      InputDataForm.setFieldValue('choseTable',DJName)
+      console.log()
+    }
+    getDagInfo()
+    getDataSource()
+  }, []);
   return (
     <>
       <StepTwo>
       <div className='StepTwo-content'>
         <div className='content-item'>
-          <Form name="control-hooks" >
+          <Form name="control-hooks" form={InputDataForm} className="form">
             <FormItem
             name="sort"
-            label="选择数据源1"
+            label={dagName}
+            className="dtsource"
             >
               <Select
               allowClear
               >
-                <Option value="Java">Java</Option>
-                <Option value="Python">Python</Option>
-                <Option value="Dag">Dag</Option>
+              {/*  */}
+                <Option value={datasourceName}>{datasourceName}</Option>
               </Select>
             </FormItem>
             <FormItem
-            name="sort"
+            name='choseTable'
             label="选择表1"
             className='item-choseList'>
-            
               <Select
               allowClear
               >
-                <Option value="Java">Java</Option>
-                <Option value="Python">Python</Option>
-                <Option value="Dag">Dag</Option>
+                {tableData.map((item) => (
+                  <Option key={item}>{item}</Option>
+                  ))
+                }
               </Select>
               <Alert 
               type='success'
@@ -114,9 +271,19 @@ export default function JobStepTwo() {
           </Form>
         </div>
       </div>
-      <div className='structure-detail'>
+      <div className='structure-detail' style={{display: detailIsSHow}}>
+        <div className='detail-title'>
+          <span className='datasourceFont'>数据源1</span>
+          <span className='schemaFont'>Dag输入源结构</span>
+        </div>
         <div className='detail-item'> 
-          <div className=''></div>
+          <div className='dataSource'>
+            <span>表1字段1.string</span>
+          </div>
+          <span className='icon'><svg t="1663331186772"  viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2086" width="20" height="20"><path d="M398.222222 398.222222h170.666667v56.888889H398.222222V398.222222z m-341.333333 170.666667h227.555555v56.888889H56.888889v-56.888889z m910.222222-113.777778h-227.555555V398.222222h227.555555v56.888889zM398.222222 853.333333H341.333333V398.222222h56.888889v455.111111z m540.444445 0H398.222222v-56.888889h512V455.111111h56.888889v398.222222h-28.444444zM85.333333 170.666667H625.777778v56.888889H113.777778v341.333333H56.888889V170.666667h28.444444z m568.888889 455.111111H455.111111v-56.888889h170.666667V170.666667h56.888889v455.111111h-28.444445z" fill="#333333" p-id="2087"></path></svg></span>
+          <div className='dataSource Dagdatasource'>
+            <span>表1字段1.string</span>
+          </div>
         </div>
       </div>
     </StepTwo>

+ 23 - 7
src/module/workmgmt/page/JobManagement.jsx

@@ -1,12 +1,28 @@
-import React from 'react'
+import React from 'react';
 import JobItems from '../component/JobItems'
 import styled from 'styled-components'
 const JobManage = styled.div``
 
-export default function JobManagement() {
-  return (
-    <JobManage>
-      <JobItems />
-    </JobManage>
-  )
+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>
+    )
 }
+  

+ 56 - 0
src/module/workmgmt/services/index.js

@@ -0,0 +1,56 @@
+import request from '../../../utils/request'
+
+// 获取数据源列表
+export const getJobDataList = params => request({
+  url: `/jpt/jm_homework/?project_id=${params}`,
+  method: 'get',
+})
+
+//获取作业类型与分类
+export const getJobTypes = params => request({
+  url: `/jpt/constants/?type=${params}`,
+  method: 'get',
+})
+
+//创建作业
+export const createJob = params => request({
+  url: `/jpt/jm_homework/`,
+  method: 'post',
+  data: {...params}
+})
+
+//删除作业
+export const deleteJob = params => request({
+  url: `/jpt/jm_homework/?jm_id=${params}`,
+  method: 'delete'
+})
+
+//获取DAG算子
+export const getDagFile = params => request({
+  url: `/jpt/dag/?project_id=${params.project_id}&user_id=${params.user_id}`,
+  method: 'get'
+})
+
+//获取DAG详细信息
+export const getDagInfomation = params => request({
+  url: `/jpt/dag/info?uri=${params}`,
+  method: 'get'
+})
+
+//获取datasource
+export const getDataSourceInfo = params => request({
+  url: `/jpt/datasource/?page=${params.page}&size=${params.size}`,
+  method: 'get'
+})
+
+//获取表名称
+export const getTableNameInfo = params => request({
+  url: `/jpt/datasource/table_names?ds_id=${params}`,
+  method: 'post',
+})
+
+//获取指定作业信息
+export const getJobInfo = params => request({
+  url: `/jpt/jm_homework/info?homework_id=${params}`,
+  methods: 'get'
+})

+ 11 - 1
src/routes/index.js

@@ -5,7 +5,8 @@ import TaskLog from '../module/tasklog/page/TaskLog.jsx'
 import TaskMgmtView from '../module/taskmgmt/page/TaskMgmtView.jsx'
 import TaskCreaterView from '../module/taskmgmt/component/TaskCreaterView.jsx'
 import TaskLogWatcher from '../module/tasklog/component/TaskLogWatcher.jsx'
-
+import JobCreate from '../module/workmgmt/component/JobCreate.jsx'
+import JobManagement from '../module/workmgmt/page/JobManagement.jsx'
 export const routes = [
   {
     path: '/datasource',
@@ -45,4 +46,13 @@ export const routes = [
       },
     ],
   },
+  {
+    path: '/work-management',
+    title: '作业管理',
+    component: JobManagement,
+    children: [{
+      path: '/work-management/cre',
+      component: JobCreate
+    }]
+  }
 ]