This commit is contained in:
YaHoo94 2024-01-27 09:08:30 +08:00
parent 07fd70c7c3
commit 1392cb7cd6
7 changed files with 220 additions and 26 deletions

View File

Before

Width:  |  Height:  |  Size: 3.0 KiB

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

View File

@ -27,4 +27,18 @@
height:45px;
background:#ffffff;
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;
}

View File

@ -8,14 +8,45 @@ import { s8 } from '../../../utils';
import { Button, message} from 'antd';
import {SaveOutlined} from '@ant-design/icons';
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 momnet from 'moment'
const ExperimentText = React.FC = () => {
const propsRef=useRef()
const navgite=useNavigate();
const locationParams =useParams () //
let graph=null
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(() => {
return {
display: 'flex',
@ -88,11 +119,13 @@ const ExperimentText = React.FC = () => {
console.log(JSON.parse(ret.data.dag));
getExperimentIns(locationParams.id).then(res=>{
if(res.code==200){
console.log(ret.data,'data');
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))
}
@ -327,6 +360,16 @@ const ExperimentText = React.FC = () => {
return (<div className={pipelineContainer}>
<div className={Styles.centerContainer}>
<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 className={graphStyle} ref={graphRef} id={Styles.graphStyle}></div>
</div>

View File

@ -3,19 +3,48 @@ import { Button, Drawer,Form, Input ,Tabs } from 'antd';
import Styles from './editPipeline.less'
import{getQueryByExperimentLog}from '@/services/experiment/index.js'
import { ProfileOutlined, DatabaseOutlined} from '@ant-design/icons';
import momnet from 'moment'
const { TextArea } = Input;
const Props = forwardRef(({onParentChange}, ref) =>{
const [form] = Form.useForm();
const [stagingItem,setStagingItem]=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 = [
{
key: '1',
label: '日志详情',
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'
}} dangerouslySetInnerHTML={{ __html: messageItem }}></div>,
icon:<ProfileOutlined/>
@ -226,11 +255,6 @@ const Props = forwardRef(({onParentChange}, ref) =>{
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)})
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);
})
}
@ -238,11 +262,6 @@ const Props = forwardRef(({onParentChange}, ref) =>{
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)})
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);
}
// console.log(e.item.getModel().in_parameters);
@ -252,7 +271,18 @@ const Props = forwardRef(({onParentChange}, ref) =>{
}));
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
defaultActiveKey="1"
items={items}/>

View File

@ -1,8 +1,8 @@
import React ,{ useState,useEffect,useRef }from 'react';
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 { useNavigate} from 'react-router-dom';
import momnet from 'moment'
@ -14,9 +14,12 @@ const Experiment = React.FC = () => {
const statusObj={
"Running":'运行中',
"Succeeded":'成功',
"Pending":'等待中',
"Failed":'失败',
"Error":'错误',
"Teminated":'终止'
"Terminated":'终止',
"Skipped":'未执行',
"Omitted":'未执行',
}
const [experimentList, setExperimentList] = useState([]);
@ -258,7 +261,41 @@ const Experiment = React.FC = () => {
>
编辑
</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>
),
},
@ -278,14 +315,66 @@ const Experiment = React.FC = () => {
<div style={{width:'200px'}}>状态</div>
<div style={{width:'300px'}}>运行时长</div>
<div style={{width:'300px'}}>开始时间</div>
<div style={{width:'300px'}}>操作</div>
</div>:''}
{experimentInList&&experimentInList.length>0?experimentInList.map((item,index)=>(
<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>
<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>

View File

@ -21,12 +21,30 @@ export function getExperimentById(id) {
method: 'GET',
});
}
// 根据id删除实验
export function deleteExperimentById(id) {
return request(`/api/mmp/experiment/${id}`, {
method: 'DELETE',
});
}
// 根据id查询实验实例
export function getQueryByExperimentId(id) {
return request(`/api/mmp/experimentIns/queryByExperimentId/${id}`, {
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查询查询日志
export function getQueryByExperimentLog(params) {
return request(`/api/mmp/experimentIns/log/`, {