Browse Source

merge

tags/v20240126^2
YaHoo94 2 years ago
parent
commit
1392cb7cd6
7 changed files with 220 additions and 26 deletions
  1. +0
    -0
      react-ui/public/assets/images/component-icon-1-Skipped.png
  2. BIN
      react-ui/public/assets/images/component-icon-2-Skipped.png
  3. +14
    -0
      react-ui/src/pages/Experiment/experimentText/editPipeline.less
  4. +48
    -5
      react-ui/src/pages/Experiment/experimentText/index.jsx
  5. +44
    -14
      react-ui/src/pages/Experiment/experimentText/props.jsx
  6. +96
    -7
      react-ui/src/pages/Experiment/index.jsx
  7. +18
    -0
      react-ui/src/services/experiment/index.js

react-ui/public/assets/images/component-icon-1--Omitted.png → react-ui/public/assets/images/component-icon-1-Skipped.png View File


BIN
react-ui/public/assets/images/component-icon-2-Skipped.png View File

Before After
Width: 108  |  Height: 108  |  Size: 3.6 kB

+ 14
- 0
react-ui/src/pages/Experiment/experimentText/editPipeline.less View File

@@ -27,4 +27,18 @@
height:45px; height:45px;
background:#ffffff; background:#ffffff;
box-shadow:0px 3px 6px rgba(146, 146, 146, 0.09); box-shadow:0px 3px 6px rgba(146, 146, 146, 0.09);
}
.detailBox{
color:#1d1d20;
font-size:15px;
margin-bottom: 15px;
display: flex;
align-items: center;
}
.allMessageItem{
display: flex;
align-items: center;
color:rgba(29, 29, 32, 0.8);
font-size:15px;
margin-right: 30px;
} }

+ 48
- 5
react-ui/src/pages/Experiment/experimentText/index.jsx View File

@@ -8,14 +8,45 @@ import { s8 } from '../../../utils';
import { Button, message} from 'antd'; import { Button, message} from 'antd';
import {SaveOutlined} from '@ant-design/icons'; import {SaveOutlined} from '@ant-design/icons';
import {saveWorkflow,getWorkflowById,} from '@/services/pipeline/index.js' import {saveWorkflow,getWorkflowById,} from '@/services/pipeline/index.js'
import {getExperimentIns} from '@/services/experiment/index.js'
import {getExperimentIns,} from '@/services/experiment/index.js'
import { useNavigate} from 'react-router-dom'; import { useNavigate} from 'react-router-dom';
import momnet from 'moment'
const ExperimentText = React.FC = () => { const ExperimentText = React.FC = () => {
const propsRef=useRef() const propsRef=useRef()
const navgite=useNavigate(); const navgite=useNavigate();
const locationParams =useParams () //新版本获取路由参数接口 const locationParams =useParams () //新版本获取路由参数接口
let graph=null let graph=null
const [experimentStatusObj,setExperimentStatusObj]=useState({}) const [experimentStatusObj,setExperimentStatusObj]=useState({})
const [experimentAllMessage,setExperimentAllMessage]=useState({})
const statusObj={
"Running":'运行中',
"Succeeded":'成功',
"Pending":'等待中',
"Failed":'失败',
"Error":'错误',
"Terminated":'终止',
"Skipped":'未执行',
"Omitted":'未执行',
}
const statusColorObj={
"Running":'#165bff',
"Succeeded":'#63a728',
"Pending":'#f981eb',
"Failed":'#c73131',
"Error":'#c73131',
"Terminated":'#8a8a8a',
"Skipped":'#8a8a8a',
"Omitted":'#8a8a8ae',
}
const timers=(time)=>{
let timer=new Date(time)
let hours = timer.getHours(); //转换成时
let minutes = timer.getMinutes(); //转换成分
let secend = timer.getSeconds(); //转换成秒
let str = `${minutes}分${secend}秒`;
return str;
}
const pipelineContainer = useEmotionCss(() => { const pipelineContainer = useEmotionCss(() => {
return { return {
display: 'flex', display: 'flex',
@@ -88,11 +119,13 @@ const ExperimentText = React.FC = () => {
console.log(JSON.parse(ret.data.dag)); console.log(JSON.parse(ret.data.dag));
getExperimentIns(locationParams.id).then(res=>{ getExperimentIns(locationParams.id).then(res=>{
if(res.code==200){ if(res.code==200){
console.log(ret.data,'data');
const experimentStatusObjs=JSON.parse(res.data.nodes_status) const experimentStatusObjs=JSON.parse(res.data.nodes_status)
const newNodeList= JSON.parse(ret.data.dag).nodes.map(item=>{console.log(experimentStatusObjs); return {...item,component_id:experimentStatusObjs&&experimentStatusObjs[item.id]&&experimentStatusObjs[item.id].id,img:experimentStatusObjs&&experimentStatusObjs[item.id]&&experimentStatusObjs[item.id].phase?item.img.slice(0,item.img.length-4)+'-'+experimentStatusObjs[item.id].phase+'.png':item.img}})
const newData={...JSON.parse(ret.data.dag),nodes:newNodeList}
console.log(newData);
getGraphData(newData)
const newNodeList= JSON.parse(ret.data.dag).nodes.map(item=>{console.log(experimentStatusObjs); return {...item,experimentEndTime:experimentStatusObjs&&experimentStatusObjs[item.id]&&experimentStatusObjs[item.id].finishedAt,experimentStartTime:experimentStatusObjs&&experimentStatusObjs[item.id]&&experimentStatusObjs[item.id].startedAt,experimentStatus:experimentStatusObjs&&experimentStatusObjs[item.id]&&experimentStatusObjs[item.id].phase,component_id:experimentStatusObjs&&experimentStatusObjs[item.id]&&experimentStatusObjs[item.id].id,img:experimentStatusObjs&&experimentStatusObjs[item.id]&&experimentStatusObjs[item.id].phase?item.img.slice(0,item.img.length-4)+'-'+experimentStatusObjs[item.id].phase+'.png':item.img}})
const newData={...JSON.parse(ret.data.dag),nodes:newNodeList}
console.log(newData);
setExperimentAllMessage(res.data)
getGraphData(newData)
// setExperimentStatusObj(JSON.parse(ret.data.nodes_status)) // setExperimentStatusObj(JSON.parse(ret.data.nodes_status))
} }
@@ -327,6 +360,16 @@ const ExperimentText = React.FC = () => {
return (<div className={pipelineContainer}> return (<div className={pipelineContainer}>
<div className={Styles.centerContainer}> <div className={Styles.centerContainer}>
<div className={Styles.buttonList}> <div className={Styles.buttonList}>
<div className={Styles.allMessageItem}>启动时间:{momnet(experimentAllMessage.create_time).format('YYYY-MM-DD HH:mm:ss')}</div>
<div className={Styles.allMessageItem}>执行时长:{experimentAllMessage.finish_time?timers(new Date(experimentAllMessage.finish_time).getTime()-new Date(experimentAllMessage.create_time).getTime()):timers(new Date().getTime()-new Date(experimentAllMessage.create_time).getTime())}</div>
<div className={Styles.allMessageItem}>状态:
<div style={{width:'8px',
height:'8px',
borderRadius:'50%',
marginRight:'6px',
backgroundColor:statusColorObj[experimentAllMessage.status]
}}></div>
<span style={{color:statusColorObj[experimentAllMessage.status]}}>{statusObj[experimentAllMessage.status]}</span></div>
</div> </div>
<div className={graphStyle} ref={graphRef} id={Styles.graphStyle}></div> <div className={graphStyle} ref={graphRef} id={Styles.graphStyle}></div>
</div> </div>


+ 44
- 14
react-ui/src/pages/Experiment/experimentText/props.jsx View File

@@ -3,19 +3,48 @@ import { Button, Drawer,Form, Input ,Tabs } from 'antd';
import Styles from './editPipeline.less' import Styles from './editPipeline.less'
import{getQueryByExperimentLog}from '@/services/experiment/index.js' import{getQueryByExperimentLog}from '@/services/experiment/index.js'
import { ProfileOutlined, DatabaseOutlined} from '@ant-design/icons'; import { ProfileOutlined, DatabaseOutlined} from '@ant-design/icons';
import momnet from 'moment'
const { TextArea } = Input; const { TextArea } = Input;
const Props = forwardRef(({onParentChange}, ref) =>{ const Props = forwardRef(({onParentChange}, ref) =>{
const [form] = Form.useForm(); const [form] = Form.useForm();
const [stagingItem,setStagingItem]=useState({}) const [stagingItem,setStagingItem]=useState({})
const [messageItem,setMessageItem]=useState('') const [messageItem,setMessageItem]=useState('')

const statusObj={
"Running":'运行中',
"Succeeded":'成功',
"Pending":'等待中',
"Failed":'失败',
"Error":'错误',
"Terminated":'终止',
"Skipped":'未执行',
"Omitted":'未执行',
}
const statusColorObj={
"Running":'#165bff',
"Succeeded":'#63a728',
"Pending":'#f981eb',
"Failed":'#c73131',
"Error":'#c73131',
"Terminated":'#8a8a8a',
"Skipped":'#8a8a8a',
"Omitted":'#8a8a8ae',
}
const timers=(time)=>{
let timer=new Date(time)
let hours = timer.getHours(); //转换成时
let minutes = timer.getMinutes(); //转换成分
let secend = timer.getSeconds(); //转换成秒
let str = `${minutes}分${secend}秒`;
return str;
}
const items = [ const items = [
{ {
key: '1', key: '1',
label: '日志详情', label: '日志详情',
children: <div style={{height:'740px', children: <div style={{height:'740px',
background:'rgba(234, 234, 234, 0.5)',
color:'rgba(29, 29, 32, 0.8)',
background:'#19253b',
color:'#fff',
fontSize:'14px' fontSize:'14px'
}} dangerouslySetInnerHTML={{ __html: messageItem }}></div>, }} dangerouslySetInnerHTML={{ __html: messageItem }}></div>,
icon:<ProfileOutlined/> icon:<ProfileOutlined/>
@@ -226,11 +255,6 @@ const Props = forwardRef(({onParentChange}, ref) =>{
form.resetFields(); form.resetFields();
form.setFieldsValue({...e.item.getModel(),in_parameters:JSON.parse(e.item.getModel().in_parameters),out_parameters:JSON.parse(e.item.getModel().out_parameters),control_strategy:JSON.parse(e.item.getModel().control_strategy)}) form.setFieldsValue({...e.item.getModel(),in_parameters:JSON.parse(e.item.getModel().in_parameters),out_parameters:JSON.parse(e.item.getModel().out_parameters),control_strategy:JSON.parse(e.item.getModel().control_strategy)})
setStagingItem({...e.item.getModel(),in_parameters:JSON.parse(e.item.getModel().in_parameters),out_parameters:JSON.parse(e.item.getModel().out_parameters),control_strategy:JSON.parse(e.item.getModel().control_strategy)}) setStagingItem({...e.item.getModel(),in_parameters:JSON.parse(e.item.getModel().in_parameters),out_parameters:JSON.parse(e.item.getModel().out_parameters),control_strategy:JSON.parse(e.item.getModel().control_strategy)})
// form.setFieldsValue({...e.item.getModel(),in_parameters:JSON.parse(e.item.getModel().in_parameters),out_parameters:JSON.parse(e.item.getModel().out_parameters)})
// setStagingItem({...e.item.getModel(),in_parameters:JSON.parse(e.item.getModel().in_parameters),out_parameters:JSON.parse(e.item.getModel().out_parameters)})
// setTimeout(() => {
// console.log(stagingItem);
// }, (500));
setOpen(true); setOpen(true);
}) })
} }
@@ -238,11 +262,6 @@ const Props = forwardRef(({onParentChange}, ref) =>{
form.resetFields(); form.resetFields();
form.setFieldsValue({...e.item.getModel(),in_parameters:JSON.parse(e.item.getModel().in_parameters),out_parameters:JSON.parse(e.item.getModel().out_parameters),control_strategy:JSON.parse(e.item.getModel().control_strategy)}) form.setFieldsValue({...e.item.getModel(),in_parameters:JSON.parse(e.item.getModel().in_parameters),out_parameters:JSON.parse(e.item.getModel().out_parameters),control_strategy:JSON.parse(e.item.getModel().control_strategy)})
setStagingItem({...e.item.getModel(),in_parameters:JSON.parse(e.item.getModel().in_parameters),out_parameters:JSON.parse(e.item.getModel().out_parameters),control_strategy:JSON.parse(e.item.getModel().control_strategy)}) setStagingItem({...e.item.getModel(),in_parameters:JSON.parse(e.item.getModel().in_parameters),out_parameters:JSON.parse(e.item.getModel().out_parameters),control_strategy:JSON.parse(e.item.getModel().control_strategy)})
// form.setFieldsValue({...e.item.getModel(),in_parameters:JSON.parse(e.item.getModel().in_parameters),out_parameters:JSON.parse(e.item.getModel().out_parameters)})
// setStagingItem({...e.item.getModel(),in_parameters:JSON.parse(e.item.getModel().in_parameters),out_parameters:JSON.parse(e.item.getModel().out_parameters)})
// setTimeout(() => {
// console.log(stagingItem);
// }, (500));
setOpen(true); setOpen(true);
} }
// console.log(e.item.getModel().in_parameters); // console.log(e.item.getModel().in_parameters);
@@ -252,7 +271,18 @@ const Props = forwardRef(({onParentChange}, ref) =>{
})); }));
return ( return (
<> <>
<Drawer title="编辑任务" placement="right" closeIcon={false} onClose={onClose} afterOpenChange={afterOpenChange} open={open}>
<Drawer title="任务执行详情" placement="right" closeIcon={false} onClose={onClose} afterOpenChange={afterOpenChange} open={open}>
<div className={Styles.detailBox}>任务名称:{stagingItem.label}</div>
<div className={Styles.detailBox} >执行状态:
<div style={{width:'8px',
height:'8px',
borderRadius:'50%',
marginRight:'6px',
backgroundColor:statusColorObj[stagingItem.experimentStatus]
}}></div>
<span style={{color:statusColorObj[stagingItem.experimentStatus]}}>{statusObj[stagingItem.experimentStatus]}</span></div>
<div className={Styles.detailBox}>启动时间:{momnet(stagingItem.experimentStartTime).format('YYYY-MM-DD HH:mm:ss')}</div>
<div className={Styles.detailBox}>耗时:{stagingItem.experimentEndTime?timers(new Date(stagingItem.experimentEndTime).getTime()-new Date(stagingItem.experimentStartTime).getTime()):timers(new Date().getTime()-new Date(stagingItem.experimentStartTime).getTime())}</div>
<Tabs <Tabs
defaultActiveKey="1" defaultActiveKey="1"
items={items}/> items={items}/>


+ 96
- 7
react-ui/src/pages/Experiment/index.jsx View File

@@ -1,8 +1,8 @@
import React ,{ useState,useEffect,useRef }from 'react'; import React ,{ useState,useEffect,useRef }from 'react';
import { Space, Table, Tag,Button,Modal, Form, Input ,message, Select,} from 'antd'; import { Space, Table, Tag,Button,Modal, Form, Input ,message, Select,} from 'antd';
import { PlusOutlined, EditOutlined ,PlayCircleOutlined} from '@ant-design/icons';
import {getWorkflow,addWorkflow,removeWorkflow,cloneWorkflow} from '@/services/pipeline/index.js'
import {getExperiment,runExperiments,getExperimentById,postExperiment,putExperiment,getQueryByExperimentId} from '@/services/experiment/index.js'
import { PlusOutlined, EditOutlined ,PlayCircleOutlined,DeleteOutlined,FieldTimeOutlined} from '@ant-design/icons';
import {getWorkflow,} from '@/services/pipeline/index.js'
import {getExperiment,runExperiments,getExperimentById,postExperiment,putExperiment,getQueryByExperimentId,deleteExperimentById,deleteQueryByExperimentInsId,putQueryByExperimentInsId} from '@/services/experiment/index.js'
import Styles from './index.less' import Styles from './index.less'
import { useNavigate} from 'react-router-dom'; import { useNavigate} from 'react-router-dom';
import momnet from 'moment' import momnet from 'moment'
@@ -14,9 +14,12 @@ const Experiment = React.FC = () => {
const statusObj={ const statusObj={
"Running":'运行中', "Running":'运行中',
"Succeeded":'成功', "Succeeded":'成功',
"Pending":'等待中',
"Failed":'失败', "Failed":'失败',
"Error":'错误', "Error":'错误',
"Teminated":'终止'
"Terminated":'终止',
"Skipped":'未执行',
"Omitted":'未执行',
} }
const [experimentList, setExperimentList] = useState([]); const [experimentList, setExperimentList] = useState([]);
@@ -258,7 +261,41 @@ const Experiment = React.FC = () => {
> >
编辑 编辑
</Button> </Button>

<Button
type="link"
size="small"
danger
key="batchRemove"
icon = {< DeleteOutlined />}
onClick={async () => {
Modal.confirm({
title: '删除',
content: '确定删除该条实验吗?',
okText: '确认',
cancelText: '取消',
onOk: () => {
console.log(record);
deleteExperimentById(record.id).then(ret=>{
if(ret.code==200){
message.success('删除成功')
getList()
}
else{
message.error(ret.msg)
}
});
// if (success) {
// if (actionRef.current) {
// actionRef.current.reload();
// }
// }
},
});
}}
>
删除
</Button>
</Space> </Space>
), ),
}, },
@@ -278,14 +315,66 @@ const Experiment = React.FC = () => {
<div style={{width:'200px'}}>状态</div> <div style={{width:'200px'}}>状态</div>
<div style={{width:'300px'}}>运行时长</div> <div style={{width:'300px'}}>运行时长</div>
<div style={{width:'300px'}}>开始时间</div> <div style={{width:'300px'}}>开始时间</div>
<div style={{width:'300px'}}>操作</div>
</div>:''} </div>:''}
{experimentInList&&experimentInList.length>0?experimentInList.map((item,index)=>( {experimentInList&&experimentInList.length>0?experimentInList.map((item,index)=>(
<div className={Styles.tableExpandBox} style={{border:'1px solid #eaeaea',backgroundColor:'#fff',height:'45px'}}> <div className={Styles.tableExpandBox} style={{border:'1px solid #eaeaea',backgroundColor:'#fff',height:'45px'}}>
<a style={{width:'50px'}} onClick={(e)=>routerToText(e,item,record)}>{index+1}</a> <a style={{width:'50px'}} onClick={(e)=>routerToText(e,item,record)}>{index+1}</a>
<div style={{width:'200px'}}>{statusObj[item.status]}</div> <div style={{width:'200px'}}>{statusObj[item.status]}</div>
<div style={{width:'300px'}}>{item.finish_time?timers(new Date(item.finish_time).getTime()-new Date(item.start_time).getTime()):timers(new Date().getTime()-new Date(item.start_time).getTime())}</div>
<div style={{width:'300px'}}>{momnet(item.start_time).format('YYYY-MM-DD HH:mm:ss')}</div>
<div style={{width:'300px'}}>{item.finish_time?timers(new Date(item.finish_time).getTime()-new Date(item.create_time).getTime()):timers(new Date().getTime()-new Date(item.create_time).getTime())}</div>
<div style={{width:'300px'}}>{momnet(item.create_time).format('YYYY-MM-DD HH:mm:ss')}</div>
<div style={{width:'300px'}}>
<Button
type="link"
size="small"
key="batchRemove"
disabled={item.status=='Succeeded'||item.status=='Failed'||item.status=='Terminated'}
icon = {<FieldTimeOutlined />}
onClick={async () => {
putQueryByExperimentInsId(item.id).then(ret=>{
if(ret.code==200){
message.success('终止成功')
getQueryByExperiment(record.id)
}
else{
message.error(ret.msg)
}
})
}}
>
终止
</Button>
<Button
type="link"
size="small"
danger
key="batchRemove"
disabled={item.status=='Running'||item.status=='Pending'}
icon = {< DeleteOutlined />}
onClick={async () => {
Modal.confirm({
title: '删除',
content: '确定删除该条实例吗?',
okText: '确认',
cancelText: '取消',
onOk: () => {
deleteQueryByExperimentInsId(item.id).then(ret=>{
if(ret.code==200){
message.success('删除成功')
getQueryByExperiment(record.id)
}
else{
message.error(ret.msg)
}
});
},
});
}}
>
删除
</Button>
</div>
</div> </div>
)):''} )):''}
</div> </div>


+ 18
- 0
react-ui/src/services/experiment/index.js View File

@@ -21,12 +21,30 @@ export function getExperimentById(id) {
method: 'GET', method: 'GET',
}); });
} }
// 根据id删除实验
export function deleteExperimentById(id) {
return request(`/api/mmp/experiment/${id}`, {
method: 'DELETE',
});
}
// 根据id查询实验实例 // 根据id查询实验实例
export function getQueryByExperimentId(id) { export function getQueryByExperimentId(id) {
return request(`/api/mmp/experimentIns/queryByExperimentId/${id}`, { return request(`/api/mmp/experimentIns/queryByExperimentId/${id}`, {
method: 'GET', method: 'GET',
}); });
} }
// 根据id删除实验实例
export function deleteQueryByExperimentInsId(id) {
return request(`/api/mmp/experimentIns/${id}`, {
method: 'DELETE',
});
}
// 根据id终止实验实例
export function putQueryByExperimentInsId(id) {
return request(`/api/mmp/experimentIns/${id}`, {
method: 'PUT',
});
}
// 根据id查询查询日志 // 根据id查询查询日志
export function getQueryByExperimentLog(params) { export function getQueryByExperimentLog(params) {
return request(`/api/mmp/experimentIns/log/`, { return request(`/api/mmp/experimentIns/log/`, {


Loading…
Cancel
Save