Browse Source

feat: 数据处理

Leo 2 years ago
parent
commit
c618ef44e2

+ 1 - 0
package.json

@@ -14,6 +14,7 @@
     "add": "^2.0.6",
     "add": "^2.0.6",
     "antd": "^4.22.4",
     "antd": "^4.22.4",
     "axios": "^0.27.2",
     "axios": "^0.27.2",
+    "copy-to-clipboard": "^3.3.2",
     "moment": "^2.29.4",
     "moment": "^2.29.4",
     "prop-types": "^15.8.1",
     "prop-types": "^15.8.1",
     "react": "^17.0.2",
     "react": "^17.0.2",

+ 26 - 33
src/module/taskmgmt/component/TaskChartEditor.jsx

@@ -47,9 +47,9 @@ const beginNodes = [
   {
   {
     shape: 'task-node',
     shape: 'task-node',
     height: 50,
     height: 50,
-    width: 180,
+    width: 160,
     data: {
     data: {
-      id: '0',
+      homework_id: 0,
       label: '开始',
       label: '开始',
       type: 'begin',
       type: 'begin',
     },
     },
@@ -60,43 +60,14 @@ const beginNodes = [
 ]
 ]
 
 
 // 作业节点
 // 作业节点
-const workNodes = [
-  {
-    shape: 'task-node',
-    data: {
-      id: '1',
-      label: '每日供应商销量预测作业',
-      type: 'work',
-    },
-    ports: {
-      items: [
-        { id: 'topPort', group: 'top' },
-        { id: 'bottomPort', group: 'bottom' },
-      ],
-    },
-  },
-  {
-    shape: 'task-node',
-    data: {
-      id: '2',
-      label: 'HR材料周更新作业',
-      type: 'work',
-    },
-    ports: {
-      items: [
-        { id: 'topPort', group: 'top' },
-        { id: 'bottomPort', group: 'bottom' },
-      ],
-    },
-  },
-]
+let workNodes = []
 
 
 // 注册节点
 // 注册节点
 Graph.registerNode(
 Graph.registerNode(
   'task-node',
   'task-node',
   {
   {
     inherit: 'react-shape',
     inherit: 'react-shape',
-    width: 180,
+    width: 160,
     height: 50,
     height: 50,
     component: <AlgoNode />,
     component: <AlgoNode />,
     ports: {
     ports: {
@@ -173,6 +144,7 @@ Graph.registerConnector(
 const { Stencil } = Addon
 const { Stencil } = Addon
 // 存储边
 // 存储边
 const taskEdges = []
 const taskEdges = []
+
 export default class TaskChartEditor extends React.Component {
 export default class TaskChartEditor extends React.Component {
   // 容器DIV
   // 容器DIV
   container
   container
@@ -190,6 +162,7 @@ export default class TaskChartEditor extends React.Component {
   //挂载
   //挂载
   componentDidMount() {
   componentDidMount() {
     this.props.onRef(this)
     this.props.onRef(this)
+    this.handleWorkNodes(this.props.jmWorkList)
     //创建图
     //创建图
     const graph = new Graph({
     const graph = new Graph({
       //容器
       //容器
@@ -374,6 +347,26 @@ export default class TaskChartEditor extends React.Component {
     this.stencilContainer = container
     this.stencilContainer = container
   }
   }
 
 
+  // 处理任务节点
+  handleWorkNodes = workList => {
+    workNodes = workList.map(item => {
+      return {
+        shape: 'task-node',
+        data: {
+          homework_id: item.id,
+          label: item.name,
+          type: 'work',
+        },
+        ports: {
+          items: [
+            { id: 'topPort', group: 'top' },
+            { id: 'bottomPort', group: 'bottom' },
+          ],
+        },
+      }
+    })
+  }
+
   render() {
   render() {
     return (
     return (
       <EditorWrapper>
       <EditorWrapper>

+ 101 - 16
src/module/taskmgmt/component/TaskCreaterView.jsx

@@ -1,9 +1,10 @@
-import React, { useState } from 'react'
+import React, { useState, useEffect } from 'react'
 import { Form, Select, Button, Space, message } from 'antd'
 import { Form, Select, Button, Space, message } from 'antd'
 import TaskForm from './TaskForm'
 import TaskForm from './TaskForm'
 import TaskChartEditor from './TaskChartEditor'
 import TaskChartEditor from './TaskChartEditor'
 import styled from 'styled-components'
 import styled from 'styled-components'
 import { useNavigate } from 'react-router'
 import { useNavigate } from 'react-router'
+import { getJmHomeworkList, createJmJob } from '../services'
 
 
 const TaskCreater = styled.div`
 const TaskCreater = styled.div`
   margin: 20px;
   margin: 20px;
@@ -45,38 +46,114 @@ const TaskCreaterView = () => {
   const navigate = useNavigate()
   const navigate = useNavigate()
   const [taskType, setTaskType] = useState(null)
   const [taskType, setTaskType] = useState(null)
   const [graphRef, setGraphRef] = useState(null)
   const [graphRef, setGraphRef] = useState(null)
+  const [cronNum, setCronNum] = useState(null)
+  const [cronUnit, setCronUnit] = useState(null)
+  const [jmWorkList, setJmWorkList] = useState([])
+
   const [taskTypeForm] = Form.useForm()
   const [taskTypeForm] = Form.useForm()
   const [taskForm] = Form.useForm()
   const [taskForm] = Form.useForm()
   const onTaskTypeChange = value => {
   const onTaskTypeChange = value => {
     setTaskType(value)
     setTaskType(value)
   }
   }
   const onSubmit = () => {
   const onSubmit = () => {
-    const cells = graphRef?.state.taskGraph.getCells()
     const taskFormData = taskForm.getFieldsValue()
     const taskFormData = taskForm.getFieldsValue()
-    taskForm
+    taskTypeForm
       .validateFields()
       .validateFields()
       .then(() => {
       .then(() => {
-        const params = {
-          name: taskFormData.taskName,
-          type: taskType === 'singleTask' ? '单作业离线任务' : '多作业离线任务',
-          tag: taskFormData.taskTag,
-          cron_type: taskFormData.executionCycle,
-          user_id: 'test',
-          user_name: 'test',
-          project_id: 'test',
-        }
-        console.log('###', cells, taskFormData, params)
+        taskForm
+          .validateFields()
+          .then(() => {
+            let nodes = []
+            let edges = []
+            let type = ''
+            if (taskType === 'singleTask') {
+              type = '单作业离线任务'
+              nodes = [
+                {
+                  id: 1,
+                  homework_id: taskFormData.job,
+                  homework_name: jmWorkList.find(
+                    item => item.id === taskFormData.job
+                  ).name,
+                  start_point: 1,
+                },
+              ]
+            } else {
+              type = '多作业离线任务'
+              const cells = handleNodes()
+              nodes = cells.nodes
+              edges = cells.edges
+            }
+            const params = {
+              name: taskFormData.taskName,
+              type,
+              tag: taskFormData.taskTag,
+              cron_type: taskFormData.executionCycle,
+              user_id: 'test',
+              user_name: 'test',
+              project_id: 'test',
+              nodes,
+              edges,
+            }
+            if (taskType === 'multitasking') {
+              params['json_str'] = JSON.stringify(
+                graphRef?.state.taskGraph.toJSON()
+              )
+            }
+            if (taskFormData.executionCycle === '2') {
+              params['cron_num'] = cronNum
+              params['cron_unit'] = cronUnit
+            }
+            createJmJob(params).then(() => {
+              navigate(-1)
+            })
+          })
+          .catch(err => {
+            message.error('请检查表单数据是否完整')
+          })
       })
       })
       .catch(err => {
       .catch(err => {
         message.error('请检查表单数据是否完整')
         message.error('请检查表单数据是否完整')
       })
       })
-    // navigate(-1)
+  }
+
+  const handleNodes = () => {
+    const cells = graphRef?.state.taskGraph.getCells()
+    const nodes = []
+    const edges = []
+    cells.forEach(cell => {
+      console.log(cell)
+      if (cell.shape === 'task-node') {
+        nodes.push({
+          id: cell.id,
+          homework_id: cell.data.homework_id,
+          homework_name: cell.data.label,
+          start_point: cell.data.type === 'work' ? 1 : 0,
+        })
+      } else {
+        edges.push({ source: cell.source.cell, target: cell.target.cell })
+      }
+    })
+    return { nodes, edges }
   }
   }
 
 
   const onGraphRef = ref => {
   const onGraphRef = ref => {
     setGraphRef(ref)
     setGraphRef(ref)
   }
   }
 
 
+  const fetchJmWorkList = async () => {
+    const { data } = await getJmHomeworkList('test')
+    if (data.code === 200) {
+      setJmWorkList(data.data)
+    } else {
+      message.error(data.msg)
+    }
+  }
+  //初始化作业列表
+  useEffect(() => {
+    fetchJmWorkList()
+  }, [])
+
   return (
   return (
     <TaskCreater>
     <TaskCreater>
       <div className="tasktype_label">配置任务类型:</div>
       <div className="tasktype_label">配置任务类型:</div>
@@ -95,11 +172,19 @@ const TaskCreaterView = () => {
         </FormItem>
         </FormItem>
       </Form>
       </Form>
       <div className="tasktype_label">配置任务信息:</div>
       <div className="tasktype_label">配置任务信息:</div>
-      <TaskForm taskForm={taskForm} taskType={taskType} />
+      <TaskForm
+        taskForm={taskForm}
+        taskType={taskType}
+        jmWorkList={jmWorkList}
+        setCronNum={cron_num => setCronNum(cron_num)}
+        setCronUnit={cron_unit => setCronUnit(cron_unit)}
+      />
       {taskType === 'multitasking' && (
       {taskType === 'multitasking' && (
         <div className="tasktype_label">作业编排:</div>
         <div className="tasktype_label">作业编排:</div>
       )}
       )}
-      {taskType === 'multitasking' && <TaskChartEditor onRef={onGraphRef} />}
+      {taskType === 'multitasking' && (
+        <TaskChartEditor onRef={onGraphRef} jmWorkList={jmWorkList} />
+      )}
       <Space className="tasktype_btns">
       <Space className="tasktype_btns">
         <Button onClick={() => navigate(-1)}>取消</Button>
         <Button onClick={() => navigate(-1)}>取消</Button>
         <Button onClick={onSubmit}>提交</Button>
         <Button onClick={onSubmit}>提交</Button>

+ 56 - 15
src/module/taskmgmt/component/TaskForm.jsx

@@ -1,6 +1,7 @@
-import React, { useState } from 'react'
+import React, { useState, useEffect } from 'react'
 import styled from 'styled-components'
 import styled from 'styled-components'
-import { Form, Select, Input, Radio, Space } from 'antd'
+import { Form, Select, Input, Radio, Space, message } from 'antd'
+import { getTagList } from '../services'
 
 
 const FormWrapper = styled.div`
 const FormWrapper = styled.div`
   .singletask_form {
   .singletask_form {
@@ -26,18 +27,48 @@ const layout = {
   },
   },
 }
 }
 
 
-const TaskForm = ({ taskForm, taskType }) => {
+const TaskForm = ({
+  taskForm,
+  taskType,
+  jmWorkList,
+  setCronNum,
+  setCronUnit,
+}) => {
   const [radioValue, setRadioValue] = useState(null)
   const [radioValue, setRadioValue] = useState(null)
+  const [tagOptions, setTagOptions] = useState([])
+  const [jmWorkOptions, setJmWorkOptions] = useState([])
 
 
   const onRadioChange = e => {
   const onRadioChange = e => {
     setRadioValue(e.target.value)
     setRadioValue(e.target.value)
   }
   }
 
 
-  const onExecutionCycleNumChange = e => {
-    console.log(e.target.value, e)
-    taskForm.setFieldsValue({ ExecutionCycleNum: e.target.value })
+  const onCronNumChange = e => {
+    setCronNum(e.target.value)
   }
   }
 
 
+  const onCronUnitChange = params => {
+    setCronUnit(params?.label)
+  }
+
+  const fetchTagList = async () => {
+    const { data } = await getTagList('任务分类')
+    if (data.code === 200) {
+      setTagOptions(data.data)
+    } else {
+      message.error(data.msg)
+    }
+  }
+
+  //初始化tag列表
+  useEffect(() => {
+    fetchTagList()
+  }, [])
+
+  //初始化作业列表
+  useEffect(() => {
+    setJmWorkOptions(jmWorkList)
+  }, [jmWorkList])
+
   return (
   return (
     <FormWrapper>
     <FormWrapper>
       <Form {...layout} form={taskForm} className="singletask_form">
       <Form {...layout} form={taskForm} className="singletask_form">
@@ -52,8 +83,11 @@ const TaskForm = ({ taskForm, taskType }) => {
           label="任务分类"
           label="任务分类"
           rules={[{ required: true, message: '请选择任务分类!' }]}>
           rules={[{ required: true, message: '请选择任务分类!' }]}>
           <Select placeholder="选择任务分类" allowClear>
           <Select placeholder="选择任务分类" allowClear>
-            <Option value="业务预测">业务预测</Option>
-            <Option value="监测">监测</Option>
+            {tagOptions.map((item, index) => (
+              <Option key={index} value={item}>
+                {item}
+              </Option>
+            ))}
           </Select>
           </Select>
         </FormItem>
         </FormItem>
         {taskType !== 'multitasking' && (
         {taskType !== 'multitasking' && (
@@ -62,8 +96,11 @@ const TaskForm = ({ taskForm, taskType }) => {
             label="选择作业"
             label="选择作业"
             rules={[{ required: true, message: '请选择作业!' }]}>
             rules={[{ required: true, message: '请选择作业!' }]}>
             <Select placeholder="选择作业" allowClear>
             <Select placeholder="选择作业" allowClear>
-              <Option value="1">作业1</Option>
-              <Option value="2">作业2</Option>
+              {jmWorkOptions.map(item => (
+                <Option key={item.id} value={item.id}>
+                  {item.name}
+                </Option>
+              ))}
             </Select>
             </Select>
           </FormItem>
           </FormItem>
         )}
         )}
@@ -73,17 +110,21 @@ const TaskForm = ({ taskForm, taskType }) => {
           rules={[{ required: true, message: '请设置执行周期!' }]}>
           rules={[{ required: true, message: '请设置执行周期!' }]}>
           <RadioGroup onChange={onRadioChange}>
           <RadioGroup onChange={onRadioChange}>
             <Space direction="vertical">
             <Space direction="vertical">
-              <Radio value={1}>只执行一次,下次手动执行</Radio>
-              <Radio value={2}>
+              <Radio value='1'>只执行一次,下次手动执行</Radio>
+              <Radio value='2'>
                 执行周期
                 执行周期
-                {radioValue === 2 ? (
+                {radioValue === '2' ? (
                   <Space className="form_executionCycle">
                   <Space className="form_executionCycle">
                     <span>每</span>
                     <span>每</span>
                     <input
                     <input
                       style={{ width: '50px' }}
                       style={{ width: '50px' }}
-                      onChange={onExecutionCycleNumChange}
+                      onChange={onCronNumChange}
                     />
                     />
-                    <Select placeholder="选择数" allowClear>
+                    <Select
+                      placeholder="选择数"
+                      allowClear
+                      labelInValue
+                      onChange={onCronUnitChange}>
                       <Option value="min">分</Option>
                       <Option value="min">分</Option>
                       <Option value="hour">时</Option>
                       <Option value="hour">时</Option>
                       <Option value="day">日</Option>
                       <Option value="day">日</Option>

+ 79 - 46
src/module/taskmgmt/page/TaskMgmtView.jsx

@@ -1,9 +1,16 @@
-import React, { useState } from 'react'
-import { Table, Switch, Space, Button } from 'antd'
+import React, { useState, useEffect } from 'react'
+import { Table, Switch, Space, Button, message } from 'antd'
 import { Link } from 'react-router-dom'
 import { Link } from 'react-router-dom'
 import styled from 'styled-components'
 import styled from 'styled-components'
 import errImgUrl from '../style/img/err.png'
 import errImgUrl from '../style/img/err.png'
 import successImgUrl from '../style/img/success.png'
 import successImgUrl from '../style/img/success.png'
+import {
+  getJmJobList,
+  deleteJmJob,
+  executeJmJob,
+  updateJmJobStatus,
+} from '../services'
+import copy from 'copy-to-clipboard'
 
 
 const TaskMgmtWrapper = styled.div`
 const TaskMgmtWrapper = styled.div`
   padding: 20px;
   padding: 20px;
@@ -16,30 +23,72 @@ const TaskMgmtWrapper = styled.div`
     margin-bottom: 20px;
     margin-bottom: 20px;
   }
   }
 `
 `
-const data = [
-  {
-    key: 1,
-    taskName: '每日供应商销量预测任务',
-    taskType: '单作业离线任务',
-    taskTag: '业务预测',
-    executionCycle: '循环触发,1小时',
-    historicalRuntime: [1, 0, 1, 1, 1, 1, 1, 0, 0, 1],
-    taskState: false,
-  },
-  {
-    key: 2,
-    taskName: 'AI平台算法服务定时监测',
-    taskType: '多作业离线任务',
-    taskTag: '任务监测',
-    executionCycle: '循环触发6小时',
-    historicalRuntime: [1, 1, 1, 0, 0, 1],
-    taskState: true,
-  },
-]
 
 
 const TaskMgmtView = () => {
 const TaskMgmtView = () => {
   // 表格Loading状态
   // 表格Loading状态
   const [dataLoading, setDataLoading] = useState(false)
   const [dataLoading, setDataLoading] = useState(false)
+  // 初始化列表
+  const [jobList, setJogList] = useState([])
+
+  // 切换状态
+  const changeTaskState = (checked, id) => {
+    updateJmJobStatus({ id, status: checked ? 1 : 0 })
+  }
+  //执行
+  const runTimeOnce = async id => {
+    const { data } = await executeJmJob(id)
+    if (data.code === 200) {
+      message.success('开始执行')
+    } else {
+      message.error(data.msg)
+    }
+  }
+  //删除
+  const deleteTask = async id => {
+    const { data } = await deleteJmJob(id)
+    if (data.code === 200) {
+      fetchJmJobList()
+    } else {
+      message.error(data.msg)
+    }
+  }
+  //Api调用
+  const getApiUri = id => {
+    const url = `${process.env.REACT_APP_BASE_URL}/jpt/jm_job_info/execute/${id}`
+    copy(url)
+    message.success('复制成功')
+  }
+  //编辑
+  const editTask = id => {
+    console.log('edit', id)
+  }
+
+  //获取列表
+  const fetchJmJobList = async () => {
+    setDataLoading(true)
+    const { data } = await getJmJobList()
+    if (data.code === 200) {
+      const list = data.data.map(item => {
+        return {
+          key: item.id,
+          taskName: item.name,
+          taskType: item.type,
+          taskTag: item.tag,
+          executionCycle:
+            item.cron_type === 1
+              ? '执行一次'
+              : `循环触发,${item.cron_num}${item.cron_unit}`,
+          historicalRuntime: item.history,
+          taskState: item.status === 1,
+        }
+      })
+      setJogList(list)
+    }
+    setDataLoading(false)
+  }
+  useEffect(() => {
+    fetchJmJobList()
+  }, [])
 
 
   const columns = [
   const columns = [
     {
     {
@@ -72,7 +121,11 @@ const TaskMgmtView = () => {
             return (
             return (
               <img
               <img
                 key={index}
                 key={index}
-                src={item === 0 ? errImgUrl : successImgUrl}
+                src={
+                  item.executor_result === 0 || item.executor_result === 0
+                    ? errImgUrl
+                    : successImgUrl
+                }
                 alt=""
                 alt=""
                 className="icon_wrapper"
                 className="icon_wrapper"
               />
               />
@@ -85,12 +138,12 @@ const TaskMgmtView = () => {
       title: '状态',
       title: '状态',
       dataIndex: 'taskState',
       dataIndex: 'taskState',
       key: 'taskState',
       key: 'taskState',
-      render: val => (
+      render: (val, record) => (
         <Switch
         <Switch
           checkedChildren="开启"
           checkedChildren="开启"
           unCheckedChildren="关闭"
           unCheckedChildren="关闭"
           defaultChecked={val}
           defaultChecked={val}
-          onChange={changeTaskState}
+          onChange={checked => changeTaskState(checked, record.key)}
         />
         />
       ),
       ),
     },
     },
@@ -131,26 +184,6 @@ const TaskMgmtView = () => {
       ),
       ),
     },
     },
   ]
   ]
-  // 切换状态
-  const changeTaskState = checked => {
-    console.log(checked)
-  }
-  //执行
-  const runTimeOnce = id => {
-    console.log('runtime', id)
-  }
-  //删除
-  const deleteTask = id => {
-    console.log('delete', id)
-  }
-  //Api调用
-  const getApiUri = id => {
-    console.log('api', id)
-  }
-  //编辑
-  const editTask = id => {
-    console.log('edit', id)
-  }
 
 
   return (
   return (
     <TaskMgmtWrapper>
     <TaskMgmtWrapper>
@@ -161,7 +194,7 @@ const TaskMgmtView = () => {
       </div>
       </div>
       <Table
       <Table
         columns={columns}
         columns={columns}
-        dataSource={data}
+        dataSource={jobList}
         bordered
         bordered
         loading={dataLoading}
         loading={dataLoading}
       />
       />

+ 67 - 0
src/module/taskmgmt/services/index.js

@@ -0,0 +1,67 @@
+import request from '../../../utils/request'
+
+// 分类常量
+export const getTagList = params =>
+  request({
+    url: `/jpt/constants/?type=${params}`,
+    method: 'get',
+  })
+
+// 定时任务列表
+export const getJmJobList = () =>
+  request({
+    url: `/jpt/jm_job_info/`,
+    method: 'get',
+  })
+
+// 更新任务
+export const updateJmJobInfo = params =>
+  request({
+    url: '/jpt/jm_job_info/',
+    method: 'put',
+    data: { ...params },
+  })
+
+// 创建任务
+export const createJmJob = params =>
+  request({
+    url: `/jpt/jm_job_info/`,
+    method: 'post',
+    data: { ...params },
+  })
+
+// 删除任务
+export const deleteJmJob = id =>
+  request({
+    url: `/jpt/jm_job_info/?jm_job_id=${id}`,
+    method: 'delete',
+  })
+
+//获取单个任务信息
+export const getJmJobInfo = id =>
+  request({
+    url: `/jpt/jm_job_info/?jm_job_id=${id}`,
+    method: 'get',
+  })
+
+//修改任务状态
+export const updateJmJobStatus = params =>
+  request({
+    url: '/jpt/jm_job_info/status',
+    method: 'put',
+    data: { ...params },
+  })
+
+//执行一次
+export const executeJmJob = id =>
+  request({
+    url: `/jpt/jm_job_info/execute/${id}`,
+    method: 'post',
+  })
+
+// 作业列表
+export const getJmHomeworkList = id =>
+  request({
+    url: `/jpt/jm_homework/?project_id=${id}`,
+    method: 'get',
+  })

+ 1 - 1
yarn.lock

@@ -3632,7 +3632,7 @@ cookie@0.5.0:
   resolved "https://registry.npmmirror.com/cookie/-/cookie-0.5.0.tgz#d1f5d71adec6558c58f389987c366aa47e994f8b"
   resolved "https://registry.npmmirror.com/cookie/-/cookie-0.5.0.tgz#d1f5d71adec6558c58f389987c366aa47e994f8b"
   integrity sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==
   integrity sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==
 
 
-copy-to-clipboard@^3.2.0:
+copy-to-clipboard@^3.2.0, copy-to-clipboard@^3.3.2:
   version "3.3.2"
   version "3.3.2"
   resolved "https://registry.npmmirror.com/copy-to-clipboard/-/copy-to-clipboard-3.3.2.tgz#5b263ec2366224b100181dded7ce0579b340c107"
   resolved "https://registry.npmmirror.com/copy-to-clipboard/-/copy-to-clipboard-3.3.2.tgz#5b263ec2366224b100181dded7ce0579b340c107"
   integrity sha512-Vme1Z6RUDzrb6xAI7EZlVZ5uvOk2F//GaxKUxajDqm9LhOVM1inxNAD2vy+UZDYsd0uyA9s7b3/FVZPSxqrCfg==
   integrity sha512-Vme1Z6RUDzrb6xAI7EZlVZ5uvOk2F//GaxKUxajDqm9LhOVM1inxNAD2vy+UZDYsd0uyA9s7b3/FVZPSxqrCfg==