Browse Source

feat:作业管理

Leo 2 years ago
parent
commit
463cc2fe3d

+ 1 - 1
src/App.jsx

@@ -54,7 +54,7 @@ export default function Sidebar() {
       <Router>
         <Layout hasSider>
           <Sider className="sidebar">
-            <div className="headerLogo">ai中台demo</div>
+            <div className="headerLogo">ai中台</div>
             <Menu theme="dark" mode="inline" items={menus} />
           </Sider>
           <Content className="content">

+ 1 - 1
src/module/taskmgmt/component/TaskChartEditor.jsx

@@ -5,7 +5,7 @@ import AlgoNode from './AlgoNode'
 
 const EditorWrapper = styled.div`
   margin-top: 20px;
-  height: 450px;
+  height: 550px;
   background: #f0f2f5;
   border-radius: 2px;
   border: 1px solid #c8d3e9;

+ 122 - 86
src/module/workmgmt/component/JobCreate.jsx

@@ -10,15 +10,19 @@ import {
   message,
   Divider,
 } from 'antd'
-import { UploadOutlined, PlusOutlined } from '@ant-design/icons'
-import React, { useState, Component, useEffect, useRef, props } from 'react'
+import { PlusOutlined } from '@ant-design/icons'
+import React, { useState, useEffect, useRef } 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'
+import { useNavigate, useLocation } from 'react-router'
+import {
+  getJobTypes,
+  createJob,
+  getDagInfomation,
+  getJobInfo,
+} from '../services'
 
 const JobCre = styled.div`
   padding: 20px;
@@ -106,8 +110,6 @@ const CreContent = styled.div`
         width: 88px;
         height: 32px;
         margin-left: 7px;
-        background-color: #4883fb;
-        color: white;
       }
     }
     .JaPySubmit {
@@ -166,17 +168,13 @@ const layout = {
     span: 16,
   },
 }
-const tailLayout = {
-  wrapperCol: {
-    offset: 8,
-    span: 16,
-  },
-}
-export default function JobCreate(props) {
-  const [form] = Form.useForm()
+
+export default function JobCreate() {
+  const [WorkTypeForm] = Form.useForm()
   const { Step } = Steps
   // 路由导航
   const navigate = useNavigate()
+  const { state } = useLocation()
   // 显示/隐藏配置Ja作业信息模块
   const [JaIsShow, setJaIsShow] = useState('none')
 
@@ -187,7 +185,7 @@ export default function JobCreate(props) {
   const [DagIsShow, setDagIsShow] = useState('none')
 
   // 单选框动态传值
-  const [value, setValue] = useState(1)
+  const [radioValue, setRadioValue] = useState(1)
 
   // 步骤数
   const [currentStep, setCurrentStep] = useState(0)
@@ -222,6 +220,28 @@ export default function JobCreate(props) {
 
   const [dagData, setDagData] = useState()
 
+  const [fileList, setFileList] = useState([])
+
+  useEffect(() => {
+    if (state) {
+      fetchJobInfo(state.id)
+    }
+  }, [state])
+
+  const fetchJobInfo = async id => {
+    const { data } = await getJobInfo(id)
+    console.log('%%%%%', data)
+    if (data.code === 200) {
+      WorkTypeForm.setFieldValue('type', data.data.type)
+      onGenderChange(data.data.type)
+      ConfigDataForm.setFieldValue('name', data.data.name)
+      ConfigDataForm.setFieldValue('tag', data.data.tag)
+      ConfigDataForm.setFieldValue('dag_url', data.data.dag_url)
+    } else {
+      message.error(data.msg)
+    }
+  }
+
   //动态改变作业分类的值
   const onNameChange = event => {
     setTagName(event.target.value)
@@ -230,7 +250,6 @@ export default function JobCreate(props) {
   //添加自定义作业分类
   const addTagItem = e => {
     if (tagName) {
-      console.log(tagName)
       e.preventDefault()
       setJobTags([...jobTags, tagName])
       setTagName('')
@@ -244,50 +263,45 @@ export default function JobCreate(props) {
 
   // 设置单选框value值
   const onChange = e => {
-    console.log('radio checked', e.target.value)
-    setValue(e.target.value)
+    setRadioValue(e.target.value)
   }
 
   //上传文件配置
   const UpProps = {
-    name: 'file',
-    action: '',
-    headers: {
-      authorization: 'authorization-text',
+    onRemove: file => {
+      const index = fileList.indexOf(file)
+      const newFileList = fileList.slice()
+      newFileList.splice(index, 1)
+      setFileList(newFileList)
     },
-
-    // 上传文件提交状态
-    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.`)
-      }
+    beforeUpload: file => {
+      setFileList([...fileList, file])
+      return false
     },
+    maxCount: 1,
+    fileList,
   }
 
   //根据作业类型做出判断
   const onGenderChange = value => {
+    console.log(value)
     if (value === 'java') {
       setJaIsShow('block')
       setDagIsShow('none')
       setPyIsShow('none')
-      setCurrentJobType('Java')
+      setCurrentJobType('java')
       setCurrentForm(JavaDataForm)
     } else if (value === 'python') {
       setJaIsShow('none')
       setDagIsShow('none')
       setPyIsShow('block')
-      setCurrentJobType('Python')
+      setCurrentJobType('python')
       setCurrentForm(PythonDataForm)
     } else if (value === 'DAG') {
       setJaIsShow('none')
       setDagIsShow('block')
       setPyIsShow('none')
-      setCurrentJobType('Dag')
+      setCurrentJobType('DAG')
       setCurrentForm(ConfigDataForm)
     }
   }
@@ -299,16 +313,41 @@ export default function JobCreate(props) {
 
   //提交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 res = await getDagInfomation(dagData)
+    if (res.status === 200) {
+      const nodes = res.data.nodes.filter(item => item.op === 'datasource')
+      const relation_list = []
+      nodes.forEach((item, index) => {
+        relation_list.push({
+          type: 'input',
+          datasource_id: InputDataForm.getFieldValue(`datasource${index}`),
+          node_uuid: item.id,
+          table: InputDataForm.getFieldValue(`sourceTable${index}`),
+        })
+        relation_list.push({
+          type: 'output',
+          datasource_id: OutputDataForm.getFieldValue(`datasource${index}`),
+          node_uuid: item.id,
+          table: OutputDataForm.getFieldValue(`sourceTable${index}`),
+        })
+      })
+      const { data } = await createJob({
+        ...ConfigDataForm.getFieldValue(),
+        script_file: '',
+        type: currentJobType,
+        dag_uuid: 'test',
+        user_id: 'test',
+        project_id: 'test',
+        // 镜像
+        image_url: '/test/images/exa',
+        relation_list,
+      })
+      if (data.code === 200) {
+        navigate(-1)
+      } else {
+        message.error(data.msg)
+      }
+    }
   }
 
   //下一步
@@ -316,17 +355,13 @@ export default function JobCreate(props) {
     currentForm
       .validateFields()
       .then(() => {
-        // finishSubmit()
         changeStep(1)
-        console.log('Successfully')
       })
       .catch(err => {
-        console.log(err, currentForm.getFieldValue())
         message.error('请检查表单数据是否完整')
       })
     if (currentStep === 2) {
       DagSubmit()
-      navigate(-1)
     }
   }
 
@@ -334,7 +369,6 @@ export default function JobCreate(props) {
     switch (currentStep) {
       case 0:
         setCurrentForm(ConfigDataForm)
-        console.log(ConfigDataForm.getFieldValue())
         break
       case 1:
         setCurrentForm(InputDataForm)
@@ -346,12 +380,6 @@ export default function JobCreate(props) {
         break
     }
     getJobType()
-    bus.on('DAGSend', data => {
-      console.log('-----------09090---------------------')
-      console.log(data)
-      setDagData(data)
-    })
-    bus.emit('DAGSend', dagData)
   }, [currentStep])
 
   //获取作业类型和分类
@@ -372,7 +400,6 @@ export default function JobCreate(props) {
   }
 
   const finishSubmit = async () => {
-    console.log(currentForm.getFieldValue())
     const params = {
       ...currentForm.getFieldValue(),
       type: currentJobType,
@@ -383,29 +410,30 @@ export default function JobCreate(props) {
       image_url: 'test',
       relation_list: [],
     }
-    console.log(params)
-    await createJob(params)
-    navigate(-1)
+    const { data } = await createJob(params)
+    if (data.code === 200) {
+      navigate(-1)
+    } else {
+      message.error(data.msg)
+    }
   }
 
   //java or python提交
   const JaPySubmit = () => {
-    console.log(currentJobType)
     const Jay = JavaDataForm.getFieldValue()
     currentForm
       .validateFields()
       .then(() => {
-        console.log(currentForm.getFieldValue())
-        finishSubmit()
-        console.log('Successfully')
+        if (radioValue === 'fromList' || fileList.length > 0) {
+          finishSubmit()
+        } else {
+          message.error('请选择本地文件')
+        }
       })
       .catch(err => {
         message.error('请检查表单数据是否完整')
-        console.log(err)
+        console.log('error', err)
       })
-    // bus.emit('sendDataForm',{
-    //   Jay,
-    // })
   }
   const cancel = () => {
     navigate(-1)
@@ -420,10 +448,9 @@ export default function JobCreate(props) {
           </div>
 
           {/* 作业类型选择       */}
-          <Form {...layout} form={form} name="control-hooks">
+          <Form {...layout} form={WorkTypeForm} name="control-hooks">
             <FormItem
-              name="type
-        "
+              name="type"
               label="选择作业类型"
               rules={[
                 {
@@ -433,7 +460,7 @@ export default function JobCreate(props) {
               <Select
                 placeholder="请选择作业类型..."
                 onSelect={onGenderChange}
-                value={value}
+                value={radioValue}
                 options={jobTypeOptions}
               />
             </FormItem>
@@ -453,14 +480,21 @@ export default function JobCreate(props) {
           {/* 配置Dag作业信息 */}
 
           {/* 第一步 */}
-          {currentStep === 0 && <JobStepOne ConfigDataForm={ConfigDataForm} />}
+          {currentStep === 0 && (
+            <JobStepOne
+              ConfigDataForm={ConfigDataForm}
+              SelectDag={val => setDagData(val)}
+            />
+          )}
 
           {/* 第二步 */}
-          {currentStep === 1 && <JobStepTwo InputDataForm={InputDataForm} />}
+          {currentStep === 1 && (
+            <JobStepTwo InputDataForm={InputDataForm} dagData={dagData} />
+          )}
 
           {/* 第三步 */}
           {currentStep === 2 && (
-            <JobStepThree OutputDataForm={OutputDataForm} />
+            <JobStepThree OutputDataForm={OutputDataForm} dagData={dagData} />
           )}
 
           <Space style={{ margin: '20px' }}>
@@ -579,14 +613,14 @@ export default function JobCreate(props) {
                   message: '请选择配置执行的Java脚本',
                 },
               ]}>
-              <RadioGroup onChange={onChange} value={value}>
+              <RadioGroup onChange={onChange} value={radioValue}>
                 <Space direction="vertical" className="jsSel">
                   <Radio value={'fromList'}>
                     <Select
                       placeholder="在工作目录中选择"
                       allowClear
                       className="javaSelect"
-                      disabled={value === 'fromList' ? false : true}>
+                      disabled={radioValue === 'fromList' ? false : true}>
                       <Option value="/test/scripts/example">
                         /test/scripts/example
                       </Option>
@@ -596,7 +630,8 @@ export default function JobCreate(props) {
                   <Radio value={'fromLocal'}>
                     <Upload {...UpProps}>
                       <Button
-                        disabled={value === 'fromLocal' ? false : true}
+                        disabled={radioValue === 'fromLocal' ? false : true}
+                        type="primary"
                         className="upButton">
                         本地上传
                       </Button>
@@ -701,20 +736,20 @@ export default function JobCreate(props) {
               </Select>
             </FormItem>
 
-            {/* 选择执行的Java脚本 */}
+            {/* 选择执行的Python脚本 */}
             <FormItem
               className="mirrorLeft choseJa script_file"
-              label="配置执行的Java脚本"
+              label="配置执行的Python脚本"
               name="script_file"
               rules={[
                 {
                   required: true,
-                  message: '请配置执行的Java脚本',
+                  message: '请配置执行的Python脚本',
                 },
               ]}>
               <RadioGroup
                 onChange={onChange}
-                value={value}
+                value={radioValue}
                 className="PyScript_file">
                 <Space direction="vertical">
                   <Radio value={'fromList'}>
@@ -722,7 +757,7 @@ export default function JobCreate(props) {
                       placeholder="在工作目录中选择"
                       allowClear
                       className="javaSelect"
-                      disabled={value === 'fromList' ? false : true}>
+                      disabled={radioValue === 'fromList' ? false : true}>
                       <Option value="test">test</Option>
                     </Select>
                   </Radio>
@@ -730,7 +765,8 @@ export default function JobCreate(props) {
                     <Upload {...UpProps}>
                       <Button
                         className="upButton"
-                        disabled={value === 'fromLocal' ? false : true}>
+                        type="primary"
+                        disabled={radioValue === 'fromLocal' ? false : true}>
                         本地上传
                       </Button>
                     </Upload>

+ 7 - 40
src/module/workmgmt/component/JobItems.jsx

@@ -1,18 +1,10 @@
 /* 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 React, { useContext, useEffect, useRef, useState } from 'react'
 import styled from 'styled-components'
 import { Link } from 'react-router-dom'
-import bus from '../../../bus.js'
-import { getJobDataList, deleteJob, getJobInfo } from '../services'
-import { routes } from '../../../routes/index.js'
+import { getJobDataList, deleteJob } from '../services'
+import { useNavigate } from 'react-router'
 const EditableContext = React.createContext(null)
 const FormItem = Form.Item
 
@@ -131,27 +123,8 @@ const App = () => {
     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 navigate = useNavigate()
 
   //删除作业
   const handleDelete = async key => {
@@ -165,9 +138,8 @@ const App = () => {
     }
   }
 
-  const editJobitem = async key => {
-    const data = await getJobInfo(key)
-    setJobData(data)
+  const editJobitem = id => {
+    navigate('/work-management/cre', { state: { id } })
   }
 
   // 格式化事件
@@ -223,9 +195,7 @@ const App = () => {
       render: (_, record) =>
         dataSource.length >= 1 ? (
           <>
-            <Link to={'/work-management/cre?data=' + JobData}>
-              <Button onClick={() => editJobitem(record.key)}>编辑</Button>
-            </Link>
+            <Button onClick={() => editJobitem(record.key)}>编辑</Button>
 
             <Popconfirm
               title="确认删除?"
@@ -270,9 +240,6 @@ const App = () => {
       }),
     }
   })
-  useEffect(() => {
-    bus.on('sendDataForm', data => {})
-  }, [])
   return (
     <JobItems>
       <Link to="/work-management/cre">

+ 116 - 124
src/module/workmgmt/component/JobStepOne.jsx

@@ -1,14 +1,23 @@
-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, useRef } from 'react';
+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, useRef } from 'react'
 import bus from '../../../bus.js'
-import ButtonGroup from 'antd/lib/button/button-group.js';
+import ButtonGroup from 'antd/lib/button/button-group.js'
 import { getJobTypes, getDagFile } from '../services'
-const { Option } = Select;
+const { Option } = Select
 const FormItem = Form.Item
 
-
 const layout = {
   labelCol: {
     span: 8,
@@ -16,20 +25,18 @@ const layout = {
   wrapperCol: {
     span: 16,
   },
-};
+}
 const tailLayout = {
   wrapperCol: {
     offset: 8,
     span: 16,
   },
-};
+}
 
-export default function JobStepOne({ ConfigDataForm }) {
-  const [form] = Form.useForm();
-  
-  const JobTagInputRef = useRef(null);
+export default function JobStepOne({ ConfigDataForm, SelectDag }) {
+  const JobTagInputRef = useRef(null)
   //自定义作业分类名称
-  const [tagName, setTagName] = useState('');
+  const [tagName, setTagName] = useState('')
   //作业分类
   const [jobTags, setJobTags] = useState([])
 
@@ -38,22 +45,20 @@ export default function JobStepOne({ ConfigDataForm }) {
   useEffect(() => {
     const DJName = ConfigDataForm.getFieldValue('DagJobName')
     if (DJName) {
-      ConfigDataForm.setFieldValue('DagJobName',DJName)
-      console.log(ConfigDataForm)
+      ConfigDataForm.setFieldValue('DagJobName', DJName)
     }
     getJobType()
     getDags()
-  },[])
-  
+  }, [])
+
   //获取作业分类
   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 = {
@@ -62,119 +67,106 @@ export default function JobStepOne({ ConfigDataForm }) {
     }
     const data = await getDagFile(params)
     setDags(data.data.data)
+  }
 
+  const onNameChange = event => {
+    setTagName(event.target.value)
   }
 
-  const onNameChange = (event) => {
-    setTagName(event.target.value);
-  };
-  
   //添加自定义作业分类
-  const addTagItem = (e) => {
-    e.preventDefault();
-    setJobTags([...jobTags,tagName])
+  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);
+      JobTagInputRef.current?.focus()
+    }, 0)
   }
+
   return (
     <>
-    <Form  {...layout} form={ConfigDataForm} name="control-hooks" >
-      <FormItem
-        name="name"
-        label="作业名称"
-        rules={[
-          {
-            required: true,
-          },
-        ]}
-      >
-        <Input
-          placeholder="请输入作业名称..."
-          allowClear
-          // onChange={}
-        >
-        </Input>
-      </FormItem>
-    
-    {/* 作业分类选择 */}
-      <FormItem
-        name="tag"
-        label="作业分类"
-        rules={[
-          {
-            required: true,
-          },
-        ]}
-      >
-        <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>
+      <Form {...layout} form={ConfigDataForm} name="control-hooks">
+        <FormItem
+          name="name"
+          label="作业名称"
+          rules={[
+            {
+              required: true,
+            },
+          ]}>
+          <Input
+            placeholder="请输入作业名称..."
+            allowClear
+            // onChange={}
+          ></Input>
+        </FormItem>
+
+        {/* 作业分类选择 */}
+        <FormItem
+          name="tag"
+          label="作业分类"
+          rules={[
+            {
+              required: true,
+            },
+          ]}>
+          <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'
-        name="dag_url"
-        label="选择DAG算子"
-        rules={[
-          {
-            required: true,
-            message: '请选择DAG算子',
-          },
-        ]}
-      >
-        <Select
-          placeholder="请选择DAG算子"
-          allowClear
-          onSelect={sendDag}
-          >
-          {dags.map((item) => (
-          <Option key={item}>{item}</Option>
-          ))
-        }
-        </Select>
-      </FormItem>
-    </Form>
+        {/* 选择执行镜像 */}
+        <FormItem
+          className="mirrorLeft"
+          name="dag_url"
+          label="选择DAG算子"
+          rules={[
+            {
+              required: true,
+              message: '请选择DAG算子',
+            },
+          ]}>
+          <Select
+            placeholder="请选择DAG算子"
+            allowClear
+            onSelect={val => SelectDag(val)}>
+            {dags.map(item => (
+              <Option key={item}>{item}</Option>
+            ))}
+          </Select>
+        </FormItem>
+      </Form>
     </>
   )
-}
+}

+ 215 - 186
src/module/workmgmt/component/JobStepThree.jsx

@@ -1,63 +1,49 @@
-import { Alert,Button, Form, Input, Select, Radio, Space, Upload, Steps } from 'antd';
-import styled from 'styled-components';
-import { getDagInfomation, getDataSourceInfo, getTableNameInfo } from '../services'
+import { Alert, Button, Form, Select, Row } from 'antd'
+import styled from 'styled-components'
+import {
+  getDagInfomation,
+  getDataSourceInfo,
+  getTableNameInfo,
+  getTableSchemaInfo,
+} from '../services'
 import { useEffect, useState } from 'react'
-import bus from '../../../bus.js'
-
+import waringUrl from '../style/img/warning.png'
+import syncUrl from '../style/img/sync.png'
 
 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;
+    margin: 20px 30px 0;
+    padding: 20px;
+    height: 450px;
+    overflow-y: auto;
+    border: 1px solid #c8d3e9;
     .dtsource {
       .ant-select {
-        width:80%;
+        width: 80%;
       }
     }
-    .ant-row {    
-      margin-left: 37px;
-      flex-wrap: nowrap;
+    .ant-row {
+      margin-left: 0;
     }
     .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;
+        .ant-form-item-control-input {
+          width: 160px;
+          .ant-select {
+            width: 100%;
+          }
         }
       }
       .stateIcon {
-        display: inline-block;
-        width:20px;
+        display: inline-flex;
+        height: 32px;
         background-color: #fff;
         border: none;
       }
-      .showStructure {
-        margin-left: 14px;
-      }
       .dataSourceType {
-        display: flex;
-        margin-left: 137px;
-        color: #7D7D7D;
-        left: 175px;
-        position: absolute;
-        top: 390px;
+        margin-bottom: 24px;
+        color: #7d7d7d;
       }
       .form {
         flex-wrap: nowrap;
@@ -68,9 +54,9 @@ const StepTwo = styled.div`
     display: flex;
     width: 416px;
     height: 450px;
-    border: 1px solid #C8D3E9;
+    border: 1px solid #c8d3e9;
     margin-top: 20px;
-    margin-left:60px;
+    margin-left: 60px;
     border-radius: 2px;
     flex-wrap: wrap;
     flex-direction: column;
@@ -78,10 +64,10 @@ const StepTwo = styled.div`
       width: 100%;
       height: 44px;
       margin-top: 26px;
-      color: #4A4A4A;
-      border-bottom: 1px solid #C8D3E9;
+      color: #4a4a4a;
+      border-bottom: 1px solid #c8d3e9;
       .datasourceFont {
-        margin-left: 85px;     
+        margin-left: 85px;
       }
       .schemaFont {
         margin-left: 115px;
@@ -94,9 +80,7 @@ const StepTwo = styled.div`
         text-align: center;
         height: 40px;
         width: 50px;
-        margin-top: 10px;
-        margin-left: 7px;
-        color: #C8D3E9;
+        color: #c8d3e9;
         line-height: 50px;
       }
       .dataSource {
@@ -106,179 +90,224 @@ const StepTwo = styled.div`
         height: 33px;
         line-height: 33px;
         text-align: center;
-        background-color: #EEF5FE;
+        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 { Option } = Select
 
-  const [choseDag,setChoseDag] = useState(null)
-
-  const [node,setNode] = useState(null)
-
-  const [dagName,setDagName] = useState(null)
-  //获取数据源
+export default function JobStepThree({ OutputDataForm, dagData }) {
+  //获取数据源节点
+  const [nodes, setNodes] = useState([])
   //数据源名称
-  const [datasourceName,setDatasourceName] = useState()
-  const [datasourceNam,setDatasourceNam] = useState()
+  const [datasources, setDatasources] = useState([])
+  //表
+  const [tableData, setTableData] = useState([])
 
-  //数据源ID
-  const [datasourceID,setDatasourceID] = useState()
-  const [datasourceI,setDatasourceI] = useState()
+  const [detailIsShow, setDetailIsShow] = useState('none')
+  // 预览node
+  const [selectedNode, setSelectedNode] = useState([])
+  // 所有预览map
+  const [nodeSchemas, setNodeSchemas] = useState({})
 
-  const [detailIsSHow,setDetailIsSHow] = useState('none')
+  //所有节点预览状态
+  const [nodeStates, setNodeStates] = useState({})
 
-  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 getDagInfo = async dag_url => {
+    const data = await getDagInfomation(dag_url)
+    if (data.status === 200) {
+      const nodes = data.data.nodes.filter(item => item.op === 'datasource')
+      setNodes(nodes)
     }
   }
 
   const getDataSource = async () => {
     const params = {
       page: 1,
-      size: 100
+      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 { data } = await getDataSourceInfo(params)
+    if (data.code === 200) {
+      setDatasources(data.data.items)
     }
   }
-
-  const getTableName = async () => {
-    const data = await getTableNameInfo(datasourceID)
-     data = await getTableNameInfo(datasourceID)
-
-    console.log(data);
+  const onDatasourcesSelect = async val => {
+    if (val !== undefined) {
+      const { data } = await getTableNameInfo(val)
+      if (data.code === 200) {
+        setTableData(data.data)
+      }
+    }
   }
-  const showStructure = () => {
-    setDetailIsSHow('block')
+  const onTableSelect = async (val, index) => {
+    if (val !== undefined) {
+      const { data } = await getTableSchemaInfo({
+        id: OutputDataForm.getFieldValue(`datasource${index}`),
+        table_name: val,
+      })
+      if (data.code === 200) {
+        const schemas = data.data.map(item => {
+          const strs = item.split(':')
+          return { dataField: strs[1], dataType: strs[2] }
+        })
+        handleSyncData(schemas, nodes[index]?.data.input_source, index)
+      }
+    }
   }
-  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 handleSyncData = (datasourceSchemas, nodeDataSchemas, index) => {
+    const list = []
+    const syncList = []
+    nodeDataSchemas.forEach(item => {
+      const syncItem = datasourceSchemas.find(
+        val => val.dataField === item.dataField
+      )
+      if (syncItem) {
+        const handleType = syncItem.dataType.split('(')[0]
+        const result =
+          item.dataType === handleType ||
+          (item.dataType === 'string' && handleType === 'varchar')
+        syncList.push({ datasource: syncItem, dag: item, result })
+        datasourceSchemas = datasourceSchemas.filter(val => val !== syncItem)
+      } else {
+        list.push(item)
       }
     })
-    getDagInfo()
+    if (list.length > datasourceSchemas.length) {
+      list.forEach((item, index) => {
+        syncList.push({
+          datasource: item,
+          dag: datasourceSchemas[index],
+          result: false,
+        })
+      })
+    } else {
+      datasourceSchemas.forEach((item, index) => {
+        syncList.push({
+          datasource: item,
+          dag: list[index],
+          result: false,
+        })
+      })
+    }
+    if (list.length === 0) {
+      nodeStates[index] = true
+    } else {
+      nodeStates[index] = false
+    }
+    setNodeStates(nodeStates)
+    nodeSchemas[index] = syncList
+    setNodeSchemas(nodeSchemas)
+  }
+
+  const showStructure = index => {
+    setDetailIsShow('block')
+    setSelectedNode(nodeSchemas[index])
+  }
+  useEffect(() => {
     getDataSource()
-  }, []);
+  }, [])
+  useEffect(() => {
+    getDagInfo(dagData)
+  }, [dagData])
   return (
-    <>
-      <StepTwo>
-      <div className='StepTwo-content'>
-        <div className='content-item'>
+    <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>
+            {nodes.map((item, index) => (
+              <div key={index}>
+                <Row>
+                  <FormItem
+                    name={`datasource${index}`}
+                    rules={[{ required: true, message: '请选择数据源!' }]}
+                    label={item.name}
+                    className="dtsource">
+                    <Select allowClear onSelect={onDatasourcesSelect}>
+                      {datasources.map(item => (
+                        <Option key={item.id} value={item.id}>
+                          {item.datasource_name}
+                        </Option>
+                      ))}
+                    </Select>
+                  </FormItem>
+                  <FormItem
+                    name={`sourceTable${index}`}
+                    label="选择表"
+                    rules={[{ required: true, message: '请选择表!' }]}
+                    className="item-choseList">
+                    <Select
+                      allowClear
+                      onSelect={val => onTableSelect(val, index)}>
+                      {tableData.map(item => (
+                        <Option key={item} value={item}>
+                          {item}
+                        </Option>
+                      ))}
+                    </Select>
+                  </FormItem>
+                  <Alert
+                    type={nodeStates[index] ? 'success' : 'warning'}
+                    showIcon
+                    className="stateIcon"></Alert>
+                  <Button type="primary" onClick={() => showStructure(index)}>
+                    结构预览
+                  </Button>
+                </Row>
+                <Row>
+                  <div className="dataSourceType">
+                    数据源类型:
+                    {
+                      datasources.find(
+                        val =>
+                          val.id ===
+                          OutputDataForm.getFieldValue(`datasource${index}`)
+                      )?.datasource
+                    }
+                  </div>
+                </Row>
               </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 className="structure-detail" style={{ display: detailIsShow }}>
+        <div className="detail-title">
+          <span className="datasourceFont">数据源</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>
+        {selectedNode?.map((item, index) => (
+          <div key={index} className="detail-item">
+            <div
+              className="dataSource"
+              style={{
+                display: item?.datasource?.dataField ? 'block' : 'none',
+              }}>
+              <span>{`${item?.datasource?.dataField}.${item?.datasource?.dataType}`}</span>
+            </div>
+            <span className="icon">
+              <img
+                src={item?.result ? syncUrl : waringUrl}
+                alt=""
+                style={{ width: '20px', height: '20px' }}
+              />
+            </span>
+            <div
+              className="dataSource Dagdatasource"
+              style={{
+                display: item?.dag?.dataField ? 'block' : 'none',
+              }}>
+              <span>{`${item?.dag?.dataField}.${item?.dag?.dataType}`}</span>
+            </div>
           </div>
-        </div>
+        ))}
       </div>
     </StepTwo>
-    </>
-    
   )
-}
+}

+ 216 - 194
src/module/workmgmt/component/JobStepTwo.jsx

@@ -1,63 +1,49 @@
-import { Alert,Button, Form, Input, Select, Radio, Space, Upload, Steps } from 'antd';
-import styled from 'styled-components';
-import { getDagInfomation, getDataSourceInfo, getTableNameInfo } from '../services'
+import { Alert, Button, Form, Select, Row } from 'antd'
+import styled from 'styled-components'
+import {
+  getDagInfomation,
+  getDataSourceInfo,
+  getTableNameInfo,
+  getTableSchemaInfo,
+} from '../services'
 import { useEffect, useState } from 'react'
-import bus from '../../../bus.js'
-
+import waringUrl from '../style/img/warning.png'
+import syncUrl from '../style/img/sync.png'
 
 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;
+    margin: 20px 30px 0;
+    padding: 20px;
+    height: 450px;
+    overflow-y: auto;
+    border: 1px solid #c8d3e9;
     .dtsource {
       .ant-select {
-        width:80%;
+        width: 80%;
       }
     }
-    .ant-row {    
-      margin-left: 37px;
-      flex-wrap: nowrap;
+    .ant-row {
+      margin-left: 0;
     }
     .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;
+        .ant-form-item-control-input {
+          width: 160px;
+          .ant-select {
+            width: 100%;
+          }
         }
       }
       .stateIcon {
-        display: inline-block;
-        width:20px;
+        display: inline-flex;
+        height: 32px;
         background-color: #fff;
         border: none;
       }
-      .showStructure {
-        margin-left: 14px;
-      }
       .dataSourceType {
-        display: flex;
-        margin-left: 137px;
-        color: #7D7D7D;
-        left: 175px;
-        position: absolute;
-        top: 390px;
+        margin-bottom: 24px;
+        color: #7d7d7d;
       }
       .form {
         flex-wrap: nowrap;
@@ -68,9 +54,9 @@ const StepTwo = styled.div`
     display: flex;
     width: 416px;
     height: 450px;
-    border: 1px solid #C8D3E9;
+    border: 1px solid #c8d3e9;
     margin-top: 20px;
-    margin-left:60px;
+    margin-left: 60px;
     border-radius: 2px;
     flex-wrap: wrap;
     flex-direction: column;
@@ -78,10 +64,10 @@ const StepTwo = styled.div`
       width: 100%;
       height: 44px;
       margin-top: 26px;
-      color: #4A4A4A;
-      border-bottom: 1px solid #C8D3E9;
+      color: #4a4a4a;
+      border-bottom: 1px solid #c8d3e9;
       .datasourceFont {
-        margin-left: 85px;     
+        margin-left: 85px;
       }
       .schemaFont {
         margin-left: 115px;
@@ -94,9 +80,7 @@ const StepTwo = styled.div`
         text-align: center;
         height: 40px;
         width: 50px;
-        margin-top: 10px;
-        margin-left: 7px;
-        color: #C8D3E9;
+        color: #c8d3e9;
         line-height: 50px;
       }
       .dataSource {
@@ -106,188 +90,226 @@ const StepTwo = styled.div`
         height: 33px;
         line-height: 33px;
         text-align: center;
-        background-color: #EEF5FE;
+        background-color: #eef5fe;
         border-radius: 2px;
       }
       .Dagdatasource {
         margin-left: 10px;
       }
     }
-    
   }
 `
 const FormItem = Form.Item
-const { Option } = Select;
-
-export default function JobStepTwo({ InputDataForm }) {
-  let noden = null;
+const { Option } = Select
 
-  const [form] = Form.useForm();
-
-  const [choseDag,setChoseDag] = useState(null)
-
-  const [node,setNode] = useState(null)
-
-  const [dagName,setDagName] = useState(null)
-  //获取数据源
+export default function JobStepTwo({ InputDataForm, dagData }) {
+  //获取数据源节点
+  const [nodes, setNodes] = useState([])
   //数据源名称
-  const [datasourceName,setDatasourceName] = useState()
-  const [datasourceNam,setDatasourceNam] = useState()
+  const [datasources, setDatasources] = useState([])
+  //表
+  const [tableData, setTableData] = useState([])
 
-  //数据源ID
-  const [datasourceID,setDatasourceID] = useState()
-  const [datasourceI,setDatasourceI] = useState()
+  const [detailIsShow, setDetailIsShow] = useState('none')
+  // 预览node
+  const [selectedNode, setSelectedNode] = useState([])
+  // 所有预览map
+  const [nodeSchemas, setNodeSchemas] = useState({})
 
-  const [detailIsSHow,setDetailIsSHow] = useState('none')
+  //所有节点预览状态
+  const [nodeStates, setNodeStates] = useState({})
 
-  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 getDagInfo = async dag_url => {
+    const data = await getDagInfomation(dag_url)
+    if (data.status === 200) {
+      const nodes = data.data.nodes.filter(item => item.op === 'datasource')
+      setNodes(nodes)
     }
   }
 
   const getDataSource = async () => {
     const params = {
       page: 1,
-      size: 100
+      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 { data } = await getDataSourceInfo(params)
+    if (data.code === 200) {
+      setDatasources(data.data.items)
     }
   }
-
-  const getTableName = async () => {
-    const data = await getTableNameInfo(datasourceID)
-     data = await getTableNameInfo(datasourceID)
-
-    console.log(data);
+  const onDatasourcesSelect = async val => {
+    if (val !== undefined) {
+      const { data } = await getTableNameInfo(val)
+      if (data.code === 200) {
+        setTableData(data.data)
+      }
+    }
   }
-  const showStructure = () => {
-    setDetailIsSHow('block')
-    console.log(InputDataForm.getFieldValue());
+  const onTableSelect = async (val, index) => {
+    if (val !== undefined) {
+      const { data } = await getTableSchemaInfo({
+        id: InputDataForm.getFieldValue(`datasource${index}`),
+        table_name: val,
+      })
+      if (data.code === 200) {
+        const schemas = data.data.map(item => {
+          const strs = item.split(':')
+          return { dataField: strs[1], dataType: strs[2] }
+        })
+        handleSyncData(schemas, nodes[index]?.data.input_source, index)
+      }
+    }
   }
-  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 handleSyncData = (datasourceSchemas, nodeDataSchemas, index) => {
+    const list = []
+    const syncList = []
+    nodeDataSchemas.forEach(item => {
+      const syncItem = datasourceSchemas.find(
+        val => val.dataField === item.dataField
+      )
+      if (syncItem) {
+        const handleType = syncItem.dataType.split('(')[0]
+        const result =
+          item.dataType === handleType ||
+          (item.dataType === 'string' && handleType === 'varchar')
+        syncList.push({ datasource: syncItem, dag: item, result })
+        datasourceSchemas = datasourceSchemas.filter(val => val !== syncItem)
+      } else {
+        list.push(item)
       }
     })
-    const DJName = InputDataForm.getFieldValue('choseTable')
-    if (DJName) {
-      InputDataForm.setFieldValue('choseTable',DJName)
-      console.log()
+    if (list.length > datasourceSchemas.length) {
+      list.forEach((item, index) => {
+        syncList.push({
+          datasource: item,
+          dag: datasourceSchemas[index],
+          result: false,
+        })
+      })
+    } else {
+      datasourceSchemas.forEach((item, index) => {
+        syncList.push({
+          datasource: item,
+          dag: list[index],
+          result: false,
+        })
+      })
+    }
+    if (list.length === 0) {
+      nodeStates[index] = true
+    } else {
+      nodeStates[index] = false
     }
-    getDagInfo()
+    setNodeStates(nodeStates)
+    nodeSchemas[index] = syncList
+    console.log(syncList)
+    setNodeSchemas(nodeSchemas)
+  }
+
+  const showStructure = index => {
+    setDetailIsShow('block')
+    setSelectedNode(nodeSchemas[index])
+  }
+  useEffect(() => {
     getDataSource()
-  }, []);
+  }, [])
+  useEffect(() => {
+    getDagInfo(dagData)
+  }, [dagData])
+
   return (
-    <>
-      <StepTwo>
-      <div className='StepTwo-content'>
-        <div className='content-item'>
+    <StepTwo>
+      <div className="StepTwo-content">
+        <div className="content-item">
           <Form name="control-hooks" form={InputDataForm} className="form">
-            <FormItem
-            name="sort"
-            label={dagName}
-            className="dtsource"
-            >
-              <Select
-              allowClear
-              >
-              {/*  */}
-                <Option value={datasourceName}>{datasourceName}</Option>
-              </Select>
-            </FormItem>
-            <FormItem
-            name='choseTable'
-            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>
+            {nodes.map((item, index) => (
+              <div key={index}>
+                <Row>
+                  <FormItem
+                    name={`datasource${index}`}
+                    rules={[{ required: true, message: '请选择数据源!' }]}
+                    label={item.name}
+                    className="dtsource">
+                    <Select allowClear onSelect={onDatasourcesSelect}>
+                      {datasources.map(item => (
+                        <Option key={item.id} value={item.id}>
+                          {item.datasource_name}
+                        </Option>
+                      ))}
+                    </Select>
+                  </FormItem>
+                  <FormItem
+                    name={`sourceTable${index}`}
+                    label="选择表"
+                    rules={[{ required: true, message: '请选择表!' }]}
+                    className="item-choseList">
+                    <Select
+                      allowClear
+                      onSelect={val => onTableSelect(val, index)}>
+                      {tableData.map(item => (
+                        <Option key={item} value={item}>
+                          {item}
+                        </Option>
+                      ))}
+                    </Select>
+                  </FormItem>
+                  <Alert
+                    type={nodeStates[index] ? 'success' : 'warning'}
+                    showIcon
+                    className="stateIcon"></Alert>
+                  <Button type="primary" onClick={() => showStructure(index)}>
+                    结构预览
+                  </Button>
+                </Row>
+                <Row>
+                  <div className="dataSourceType">
+                    数据源类型:
+                    {
+                      datasources.find(
+                        val =>
+                          val.id ===
+                          InputDataForm.getFieldValue(`datasource${index}`)
+                      )?.datasource
+                    }
+                  </div>
+                </Row>
               </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 className="structure-detail" style={{ display: detailIsShow }}>
+        <div className="detail-title">
+          <span className="datasourceFont">数据源</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>
+        {selectedNode?.map((item, index) => (
+          <div key={index} className="detail-item">
+            <div
+              className="dataSource"
+              style={{
+                display: item?.datasource?.dataField ? 'block' : 'none',
+              }}>
+              <span>{`${item?.datasource?.dataField}.${item?.datasource?.dataType}`}</span>
+            </div>
+            <span className="icon">
+              <img
+                src={item?.result ? syncUrl : waringUrl}
+                alt=""
+                style={{ width: '20px', height: '20px' }}
+              />
+            </span>
+            <div
+              className="dataSource Dagdatasource"
+              style={{
+                display: item?.dag?.dataField ? 'block' : 'none',
+              }}>
+              <span>{`${item?.dag?.dataField}.${item?.dag?.dataType}`}</span>
+            </div>
           </div>
-        </div>
+        ))}
       </div>
     </StepTwo>
-    </>
-    
   )
-}
+}

+ 53 - 37
src/module/workmgmt/services/index.js

@@ -1,56 +1,72 @@
 import request from '../../../utils/request'
 
 // 获取数据源列表
-export const getJobDataList = params => request({
-  url: `/jpt/jm_homework/?project_id=${params}`,
-  method: 'get',
-})
+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 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 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'
-})
+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'
-})
+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'
-})
+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 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 getTableNameInfo = params =>
+  request({
+    url: `/jpt/datasource/table_names?ds_id=${params}`,
+    method: 'post',
+  })
+
+//获取表结构
+export const getTableSchemaInfo = params =>
+  request({
+    url: `/jpt/datasource/table_schema?ds_id=${params.id}&table_name=${params.table_name}`,
+    method: 'post',
+  })
 
 //获取指定作业信息
-export const getJobInfo = params => request({
-  url: `/jpt/jm_homework/info?homework_id=${params}`,
-  methods: 'get'
-})
+export const getJobInfo = params =>
+  request({
+    url: `/jpt/jm_homework/info?homework_id=${params}`,
+    methods: 'get',
+  })

BIN
src/module/workmgmt/style/img/success.png


BIN
src/module/workmgmt/style/img/sync.png


BIN
src/module/workmgmt/style/img/warning.png