feature:80%

This commit is contained in:
charlesxie
2022-02-09 18:03:46 +08:00
parent 5ef31b859b
commit 993416ace3
28 changed files with 286 additions and 132 deletions

View File

@@ -12,3 +12,27 @@ node_type = (
(4, "条件分支"),
(5, "汇聚网关"),
)
class StateType(object):
CREATED = "CREATED"
READY = "READY"
RUNNING = "RUNNING"
SUSPENDED = "SUSPENDED"
BLOCKED = "BLOCKED"
FINISHED = "FINISHED"
FAILED = "FAILED"
REVOKED = "REVOKED"
PIPELINE_STATE_TO_FLOW_STATE = {
StateType.READY: "wait",
StateType.RUNNING: "run",
StateType.FAILED: "fail",
StateType.FINISHED: "success",
StateType.SUSPENDED: "pause",
StateType.REVOKED: "cancel",
StateType.BLOCKED: "stop",
StateType.CREATED: "positive",
}

View File

@@ -1,4 +1,4 @@
# Generated by Django 2.2.6 on 2022-01-28 09:40
# Generated by Django 2.2.6 on 2022-02-09 03:29
import datetime
from django.db import migrations, models
@@ -39,41 +39,23 @@ class Migration(migrations.Migration):
('category', models.ManyToManyField(to='flow.Category')),
],
),
migrations.CreateModel(
name='Node',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=255, verbose_name='节点名称')),
('uuid', models.CharField(max_length=255, unique=True, verbose_name='UUID')),
('description', models.CharField(blank=True, max_length=255, null=True, verbose_name='节点描述')),
('show', models.BooleanField(default=True, verbose_name='是否显示')),
('top', models.IntegerField(default=300)),
('left', models.IntegerField(default=300)),
('ico', models.CharField(blank=True, max_length=64, null=True, verbose_name='icon')),
('fail_retry_count', models.IntegerField(default=0, verbose_name='失败重试次数')),
('fail_offset', models.IntegerField(default=0, verbose_name='失败重试间隔')),
('fail_offset_unit', models.CharField(choices=[('seconds', ''), ('hours', ''), ('minutes', '')], max_length=32, verbose_name='重试间隔单位')),
('node_type', models.IntegerField(default=2)),
('component_code', models.CharField(max_length=255, verbose_name='插件名称')),
('is_skip_fail', models.BooleanField(default=False, verbose_name='忽略失败')),
('is_timeout_alarm', models.BooleanField(default=False, verbose_name='超时告警')),
('inputs', django_mysql.models.JSONField(default=dict, verbose_name='输入参数')),
('outputs', django_mysql.models.JSONField(default=dict, verbose_name='输出参数')),
('process', models.ForeignKey(db_constraint=False, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='nodes', to='flow.Process')),
],
options={
'abstract': False,
},
),
migrations.CreateModel(
name='ProcessRun',
fields=[
('process_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='flow.Process')),
('state', models.CharField(max_length=32, verbose_name='工作流状态')),
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=255, verbose_name='作业名称')),
('description', models.CharField(blank=True, max_length=255, null=True, verbose_name='作业描述')),
('run_type', models.CharField(max_length=32, verbose_name='调度类型')),
('gateways', django_mysql.models.JSONField(default=dict, verbose_name='网关信息')),
('constants', django_mysql.models.JSONField(default=dict, verbose_name='内部变量信息')),
('dag', django_mysql.models.JSONField(default=dict, verbose_name='DAG')),
('create_by', models.CharField(max_length=64, null=True, verbose_name='创建者')),
('create_time', models.DateTimeField(default=datetime.datetime.now, verbose_name='创建时间')),
('update_time', models.DateTimeField(auto_now=True, verbose_name='修改时间')),
('update_by', models.CharField(max_length=64, null=True, verbose_name='修改人')),
('root_id', models.CharField(max_length=255, verbose_name='根节点uuid')),
('process', models.ForeignKey(db_constraint=False, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='run', to='flow.Process')),
],
bases=('flow.process',),
),
migrations.CreateModel(
name='NodeRun',
@@ -101,4 +83,30 @@ class Migration(migrations.Migration):
'abstract': False,
},
),
migrations.CreateModel(
name='Node',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=255, verbose_name='节点名称')),
('uuid', models.CharField(max_length=255, unique=True, verbose_name='UUID')),
('description', models.CharField(blank=True, max_length=255, null=True, verbose_name='节点描述')),
('show', models.BooleanField(default=True, verbose_name='是否显示')),
('top', models.IntegerField(default=300)),
('left', models.IntegerField(default=300)),
('ico', models.CharField(blank=True, max_length=64, null=True, verbose_name='icon')),
('fail_retry_count', models.IntegerField(default=0, verbose_name='失败重试次数')),
('fail_offset', models.IntegerField(default=0, verbose_name='失败重试间隔')),
('fail_offset_unit', models.CharField(choices=[('seconds', ''), ('hours', ''), ('minutes', '')], max_length=32, verbose_name='重试间隔单位')),
('node_type', models.IntegerField(default=2)),
('component_code', models.CharField(max_length=255, verbose_name='插件名称')),
('is_skip_fail', models.BooleanField(default=False, verbose_name='忽略失败')),
('is_timeout_alarm', models.BooleanField(default=False, verbose_name='超时告警')),
('inputs', django_mysql.models.JSONField(default=dict, verbose_name='输入参数')),
('outputs', django_mysql.models.JSONField(default=dict, verbose_name='输出参数')),
('process', models.ForeignKey(db_constraint=False, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='nodes', to='flow.Process')),
],
options={
'abstract': False,
},
),
]

View File

@@ -26,6 +26,17 @@ class Process(models.Model):
update_time = models.DateTimeField("修改时间", auto_now=True)
update_by = models.CharField("修改人", max_length=64, null=True)
@property
def clone_data(self):
return {
"name": self.name,
"description": self.description,
"run_type": self.run_type,
"gateways": self.gateways,
"constants": self.constants,
"dag": self.dag,
}
class BaseNode(models.Model):
name = models.CharField("节点名称", max_length=255, blank=False, null=False)
@@ -58,14 +69,30 @@ class Node(BaseNode):
related_name="nodes")
class ProcessRun(Process):
class ProcessRun(models.Model):
# new
process = models.ForeignKey(Process, on_delete=models.SET_NULL, null=True, db_constraint=False,
related_name="run")
state = models.CharField("工作流状态", max_length=32)
name = models.CharField("作业名称", max_length=255, blank=False, null=False)
description = models.CharField("作业描述", max_length=255, blank=True, null=True)
run_type = models.CharField("调度类型", max_length=32)
gateways = JSONField("网关信息", default=dict)
constants = JSONField("内部变量信息", default=dict)
dag = JSONField("DAG", default=dict)
create_by = models.CharField("创建者", max_length=64, null=True)
create_time = models.DateTimeField("创建时间", default=datetime.now)
update_time = models.DateTimeField("修改时间", auto_now=True)
update_by = models.CharField("修改人", max_length=64, null=True)
root_id = models.CharField("根节点uuid", max_length=255)
class NodeRun(BaseNode):
process_run = models.ForeignKey(ProcessRun, on_delete=models.SET_NULL, null=True, db_constraint=False,
related_name="nodes_run")
@staticmethod
def field_names():
return [field.name for field in NodeRun._meta.get_fields() if field.name not in ["id"]]

View File

@@ -1,7 +1,12 @@
import json
from django.db import transaction
from rest_framework import serializers
from bamboo_engine import api
from pipeline.eri.runtime import BambooDjangoRuntime
from applications.flow.models import Process, Node, ProcessRun
from applications.flow.constants import PIPELINE_STATE_TO_FLOW_STATE
from applications.flow.models import Process, Node, ProcessRun, NodeRun
class ProcessViewSetsSerializer(serializers.Serializer):
@@ -105,11 +110,6 @@ class RetrieveProcessViewSetsSerializer(serializers.ModelSerializer):
class RetrieveProcessRunViewSetsSerializer(serializers.ModelSerializer):
pipeline_tree = serializers.SerializerMethodField()
# category = serializers.SerializerMethodField()
#
# def get_category(self, obj):
# return obj.category.all()
def get_pipeline_tree(self, obj):
lines = []
nodes = []
@@ -119,16 +119,28 @@ class RetrieveProcessRunViewSetsSerializer(serializers.ModelSerializer):
"from": _from,
"to": _to
})
node_list = Node.objects.filter(process_id=obj.id).values()
runtime = BambooDjangoRuntime()
process_info = api.get_pipeline_states(runtime, root_id=obj.root_id)
process_state = PIPELINE_STATE_TO_FLOW_STATE.get(process_info.data[obj.root_id]["state"])
state_map = process_info.data[obj.root_id]["children"]
node_list = NodeRun.objects.filter(process_run_id=obj.id).values()
for node in node_list:
pipeline_state = state_map.get(node["uuid"], {}).get("state", "READY")
flow_state = PIPELINE_STATE_TO_FLOW_STATE[pipeline_state]
outputs = ""
if node["node_type"] not in [0, 1] and flow_state == "success":
output_data = api.get_execution_data_outputs(runtime, node_id=node["uuid"])
outputs = json.dumps(output_data.data["outputs"])
nodes.append({"show": node["show"],
"top": node["top"],
"left": node["left"],
"ico": node["ico"],
"type": node["node_type"],
"name": node["name"],
"state": flow_state,
"node_data": {
"inputs": node["inputs"],
"outputs": outputs,
"run_mark": 0,
"node_name": node["name"],
"description": node["description"],
@@ -138,11 +150,11 @@ class RetrieveProcessRunViewSetsSerializer(serializers.ModelSerializer):
"is_skip_fail": node["is_skip_fail"],
"is_timeout_alarm": node["is_timeout_alarm"]},
"uuid": node["uuid"]})
return {"lines": lines, "nodes": nodes}
return {"lines": lines, "nodes": nodes, "process_state": process_state}
class Meta:
model = ProcessRun
fields = ("id", "name", "description", "category", "run_type", "pipeline_tree")
fields = ("id", "name", "description", "run_type", "pipeline_tree")
class ExecuteProcessSerializer(serializers.Serializer):

View File

@@ -3,5 +3,5 @@ from rest_framework.routers import DefaultRouter
from . import views
flow_router = DefaultRouter()
flow_router.register(r"", viewset=views.ProcessViewSets, base_name="flow")
flow_router.register(r"flow", viewset=views.ProcessViewSets, base_name="flow")
flow_router.register(r"run", viewset=views.ProcessRunViewSets, base_name="run")

View File

@@ -6,17 +6,18 @@ from rest_framework import mixins
from rest_framework.decorators import action
from rest_framework.response import Response
from applications.flow.models import Process, Node, ProcessRun
from applications.flow.models import Process, Node, ProcessRun, NodeRun
from applications.flow.serializers import ProcessViewSetsSerializer, ListProcessViewSetsSerializer, \
RetrieveProcessViewSetsSerializer, ExecuteProcessSerializer, ListProcessRunViewSetsSerializer, \
RetrieveProcessRunViewSetsSerializer
from applications.utils.dag_helper import DAG
from applications.utils.dag_helper import DAG, instance_dag
from component.drf.viewsets import GenericViewSet
class ProcessViewSets(mixins.ListModelMixin,
mixins.CreateModelMixin,
mixins.RetrieveModelMixin,
mixins.DestroyModelMixin,
GenericViewSet):
queryset = Process.objects.order_by("-update_time")
@@ -38,8 +39,10 @@ class ProcessViewSets(mixins.ListModelMixin,
dag_obj = DAG()
dag_obj.from_dict(process.dag)
topological_sort = dag_obj.topological_sort()
start = pipeline_tree = EmptyStartEvent()
start = pipeline_tree = EmptyStartEvent()
# 运行实例的uuid
process_run_uuid = {topological_sort[0]: start.id}
for pipeline_id in topological_sort[1:]:
if node_map[pipeline_id].node_type == 0:
act = EmptyStartEvent()
@@ -47,12 +50,24 @@ class ProcessViewSets(mixins.ListModelMixin,
act = EmptyEndEvent()
else:
act = ServiceActivity(component_code="http_request")
act.component.inputs.inputs = Var(type=Var.PLAIN, value=node_map[pipeline_id].inputs)
process_run_uuid[pipeline_id] = act.id
pipeline_tree = getattr(pipeline_tree, "extend")(act)
pipeline_data = Data()
pipeline = builder.build_tree(start, data=pipeline_data)
runtime = BambooDjangoRuntime()
api.run_pipeline(runtime=runtime, pipeline=pipeline)
process_run_data = process.clone_data
process_run_data["dag"] = instance_dag(process_run_data["dag"], process_run_uuid)
process_run = ProcessRun.objects.create(process_id=process.id, root_id=pipeline["id"], **process_run_data)
node_run_bulk = []
for pipeline_id, node in node_map.items():
_node = {k: v for k, v in node.__dict__.items() if k in NodeRun.field_names()}
_node["uuid"] = process_run_uuid[pipeline_id]
node_run_bulk.append(NodeRun(process_run=process_run, **_node))
NodeRun.objects.bulk_create(node_run_bulk, batch_size=500)
return Response({})

View File

@@ -191,6 +191,14 @@ class DAG(object):
return len(self.graph)
def instance_dag(dag_dict, process_run_uuid):
new_dag_dict = defaultdict(list)
for k, v_list in dag_dict.items():
for v in v_list:
new_dag_dict[process_run_uuid[k]].append(process_run_uuid[v])
return dict(new_dag_dict)
if __name__ == '__main__':
dag = DAG()
dag.add_node("a")

View File

@@ -5,6 +5,7 @@ from pipeline.component_framework.component import Component
import json
import eventlet
import time
requests = eventlet.import_patched('requests')
@@ -12,9 +13,33 @@ class HttpRequestService(Service):
__need_schedule__ = False
def execute(self, data, parent_data):
print("执行了")
time.sleep(5)
return True
try:
inputs = data.get_one_of_inputs("inputs")
headers = self.parse_headers(inputs["header"])
inputs["body"] = json.loads(inputs["body"])
req_data = [{"params": inputs["body"]}, {"json": inputs["body"]}][inputs["method"] != "get"]
res = requests.request(inputs["method"], url=inputs["url"], headers=headers, timeout=inputs["timeout"],
**req_data).content
print("执行了", res)
res = json.loads(res)
data.outputs.outputs = res
time.sleep(5)
return True
except Exception:
return False
def parse_headers(self, headers):
return {header["key"]: header["value"] for header in headers if header["key"]}
def inputs_format(self):
return [
Service.InputItem(name="输入参数", key="inputs", type="dict", required=True)
]
def outputs_format(self):
return [
Service.OutputItem(name="输出参数", key="outputs", type="dict", required=True)
]
class HttpRequestComponent(Component):

View File

@@ -1,4 +1,3 @@
import os
from pathlib import Path
# Build paths inside the project like this: BASE_DIR / 'subdir'.
@@ -108,15 +107,11 @@ AUTH_PASSWORD_VALIDATORS = [
},
]
LANGUAGE_CODE = 'en-us'
TIME_ZONE = 'UTC'
USE_I18N = True
USE_L10N = True
USE_TZ = True
USE_TZ = False
STATIC_URL = '/static/'
@@ -144,3 +139,7 @@ REST_FRAMEWORK = {
"DATETIME_FORMAT": "%Y-%m-%d %H:%M:%S",
"NON_FIELD_ERRORS_KEY": "params_error",
}
# 本地调试
# CELERY_ALWAYS_EAGER = True
# CELERY_TASK_ALWAYS_EAGER = True

View File

@@ -3,7 +3,7 @@
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>调度平台</title>
<title>任务调度平台</title>
<link href="{{ STATIC_URL }}dist/css/app.css" rel="stylesheet">
<link href="{{ STATIC_URL }}img/{{ APP_CODE }}.png" rel="shortcut icon" type="image/x-icon">
</head>

View File

@@ -3,7 +3,7 @@
<head>
<meta charset=utf-8>
<meta name=viewport content="width=device-width,initial-scale=1">
<title>调度平台</title>
<title>任务调度平台</title>
</head>
<body>
<script>

View File

@@ -1,3 +1,3 @@
<!DOCTYPE html><html><head><meta charset=utf-8><meta name=viewport content="width=device-width,initial-scale=1"><title>调度平台</title><link href=./static/dist/css/app.css rel=stylesheet></head><body><script>window.siteUrl = "http://dev.cwbk.com:8000"
<!DOCTYPE html><html><head><meta charset=utf-8><meta name=viewport content="width=device-width,initial-scale=1"><title>任务调度平台</title><link href=./static/dist/css/app.css rel=stylesheet></head><body><script>window.siteUrl = "http://dev.cwbk.com:8000"
window.APP_CODE = 'run-batch';
window.CSRF_COOKIE_NAME = 'run-batch_csrftoken'</script><div id=app></div><script type=text/javascript src=./static/dist/js/manifest.js></script><script type=text/javascript src=./static/dist/js/vendor.js></script><script type=text/javascript src=./static/dist/js/app.js></script></body></html>

View File

@@ -3,25 +3,25 @@ import {GET, POST, PUT, DELETE, reUrl} from '../../axiosconfig/axiosconfig'
export default {
// 作业台
list: function(params) {
return GET(reUrl + '/process/', params)
return GET(reUrl + '/process/flow/', params)
},
create: function(params) {
return POST(reUrl + '/process/', params)
return POST(reUrl + '/process/flow/', params)
},
retrieve: function(id) {
return GET(reUrl + '/process/' + JSON.stringify(id) + '/')
return GET(reUrl + '/process/flow/' + JSON.stringify(id) + '/')
},
update: function(id, params) {
return PUT(reUrl + '/process/' + JSON.stringify(id) + '/', params)
return PUT(reUrl + '/process/flow/' + JSON.stringify(id) + '/', params)
},
clone: function(params) {
return POST(reUrl + '/process/clone/', params)
},
delete: function(id) {
return DELETE(reUrl + '/process/' + JSON.stringify(id) + '/')
return DELETE(reUrl + '/process/flow/' + JSON.stringify(id) + '/')
},
execute: function(params) {
return POST(reUrl + '/process/execute/', params)
return POST(reUrl + '/process/flow/execute/', params)
},
get_process_node: function(params) {
return GET(reUrl + '/process/get_process_node/', params)

View File

@@ -29,7 +29,7 @@
},
data() {
return {
title: '调度平台',
title: '任务调度平台',
headerTitle: '',
imgSrc: '',
}

View File

@@ -66,6 +66,7 @@
},
initEditor() {
// 初始化编辑器确保dom已经渲染
console.log(this.codes)
this.monacoEditor = monaco.editor.create(this.$refs.codeEditor, {
value: this.codes, //编辑器初始显示文字
language: this.language, //语言支持自行查阅demo

View File

@@ -205,7 +205,7 @@
setting: {
size: 'small', // 表格大小
fields: fields, // 表格所有列
selectedFields: fields.slice(0, 8) // 表格当前显示列
selectedFields: fields.slice(0, 1) // 表格当前显示列
},
opreateFlag: false,
midSearchForm: {},

View File

@@ -4,53 +4,76 @@
<div class="box">
<p class="title">基本信息</p>
<div class="info">
<bk-form ref="form" :label-width="144">
<bk-form-item label="开始时间:">
<span>{{form.nodeData.eta}}</span>
<bk-form ref="form" :label-width="144" :model="form">
<bk-form-item label="节点名称:" :required="true" :error-display-type="'normal'" :property="'node_name'">
<bk-input v-model="form.node_name" type="text" style="width: 350px;margin-right: 9px;" :disabled="disabled"></bk-input>
</bk-form-item>
<bk-form-item label="执行前人工复核:">
<span v-if="form.nodeData.need_confirm === 0"></span>
<span v-else-if="form.nodeData.need_confirm === 1">单人复核</span>
<span v-else-if="form.nodeData.need_confirm === 2">双人复核</span>
<bk-form-item label="运行标志:" :required="true" :error-display-type="'normal'" :property="'run_mark'">
<bk-radio-group v-model="form.run_mark">
<bk-radio :value="item.value" v-for="(item, index) in reviewList" :key="index" style="margin-right: 24px;"
:disabled="disabled">
{{item.label}}
</bk-radio>
</bk-radio-group>
</bk-form-item>
<bk-form-item label="执行后自动暂停:">
<bk-switcher v-model="form.nodeData.is_book_pause" theme="primary" :disabled="disabled"></bk-switcher>
<bk-form-item label="描述:">
<bk-input v-model="form.description" type="textarea" style="width: 350px;margin-right: 9px;" :disabled="disabled" :min="0"></bk-input>
</bk-form-item>
<bk-form-item label="执行时长告警:">
<bk-form-item label="失败重试次数:" :required="true" :error-display-type="'normal'" :property="'fail_retry_count'">
<bk-input v-model="form.fail_retry_count" type="number" style="width: 350px;margin-right: 9px;" :disabled="disabled" :min="0"></bk-input>
</bk-form-item>
<bk-form-item label="失败重试间隔:">
<bk-compose-form-item>
<span>{{form.nodeData.alarm_policy.duration.period}}</span>
<span>{{getUnit1}}</span>
<span v-if="form.nodeData.alarm_policy.duration.period && getUnit1">产生告警</span>
<bk-input v-model="form.fail_offset" type="number" style="width: 139px;margin-right: 9px;"
:disabled="disabled" :min="0"></bk-input>
<bk-select :clearable="true" style="background-color: #fff;width: 138px;margin-right: 14px;"
v-model="form.fail_offset_unit" placeholder="请选择" :disabled="disabled">
<bk-option v-for="(item, index) in timeTypeList" :key="index" :id="item.value"
:name="item.label">
</bk-option>
</bk-select>
<span>产生重试</span>
</bk-compose-form-item>
</bk-form-item>
<bk-form-item label="执行时间点告警:">
<span style="margin-right: 12px;" v-if="form.nodeData.alarm_policy.time_point">时间点超过</span>
<span>{{form.nodeData.alarm_policy.time_point}}</span>
<span v-if="form.nodeData.alarm_policy.time_point">产生告警</span>
<bk-form-item label="忽略失败:">
<bk-switcher v-model="form.is_skip_fail" :disabled="disabled"></bk-switcher>
</bk-form-item>
<bk-form-item label="前置文件路径:">
<span>{{form.nodeData.file_dependence.file_path}}</span>
<bk-form-item label="超时告警:">
<bk-switcher v-model="form.is_timeout_alarm" :disabled="disabled"></bk-switcher>
</bk-form-item>
<bk-form-item label="巡检次数:">
<span>{{form.nodeData.file_dependence.max_num}}</span>
<bk-divider style="width: 540px;position: relative;right: 20px;border-color: #dcdee5;"></bk-divider>
<p class="title">输入参数</p>
<bk-form-item label="请求地址:">
<bk-input v-model="form.inputs.url" type="textarea" style="width: 350px;margin-right: 9px;" :disabled="disabled" :min="0"></bk-input>
</bk-form-item>
<bk-form-item label="巡检周期:">
<span>{{form.nodeData.file_dependence.cycle.value}}</span>
<span>{{getUnit2}}</span>
<bk-form-item label="请求类型:">
<bk-select :clearable="true" style="background-color: #fff;width: 130px;margin-right: 14px;" v-model="form.inputs.method" placeholder="请选择" :disabled="disabled">
<bk-option v-for="(item, index) in requestTypeList" :key="index" :id="item.value" :name="item.label">
</bk-option>
</bk-select>
</bk-form-item>
<bk-form-item label="前置条件检测命令:">
<div v-for="(item, index) in form.nodeData.pre_commands" class="pre-commands" :key="index"
style="margin-bottom: 12px;">
<span>{{item.key}}</span>
<bk-form-item label="Header:">
<div v-for="(item, index) in form.inputs.header" class="pre-commands" :key="index" style="margin-bottom: 12px;">
<bk-compose-form-item>
<bk-input v-model="item.key" type="text" style="width: 130px;margin-right: 9px;" :disabled="disabled" :min="0"></bk-input>
<bk-input v-model="item.value" type="text" style="width: 130px;margin-right: 9px;" :disabled="disabled" :min="0"></bk-input>
</bk-compose-form-item>
<i class="iconfont icon-changyongtubiao-chahao btn" style="margin-left: 8px;" @click="handleDeleteCommand(index)"
v-if="!disabled && form.inputs.header.length > 1"></i>
<i class="iconfont icon-changyongtubiao-jiahao btn" @click="handleAddCommand" v-if="!disabled"></i>
</div>
</bk-form-item>
<bk-form-item label="状态:">{{statusList[statusList.findIndex(item => item.key === form.state)].label}}</bk-form-item>
<bk-form-item label="执行时间:">{{form.start_time}}</bk-form-item>
<bk-form-item label="结束时间:">{{form.end_time}}</bk-form-item>
<bk-form-item label="执行脚本:">
<editor :height="'200px'" ref="editor" :codes="form.script_content" :read-only="true" :language="'shell'"></editor>
<bk-form-item label="Body:">
<bk-input v-model="form.inputs.body" type="textarea" style="width: 350px;margin-right: 9px;" :disabled="disabled" :min="0"></bk-input>
</bk-form-item>
<bk-form-item label="超时时间:">
<bk-input v-model="form.inputs.timeout" type="number" style="width: 350px;margin-right: 9px;" :disabled="disabled" :min="0"></bk-input>
</bk-form-item>
<bk-divider style="width: 540px;position: relative;right: 20px;border-color: #dcdee5;"></bk-divider>
<p class="title">输出结果</p>
<bk-form-item label="输出日志:">
<editor :height="'200px'" ref="editor" :codes="form.outputs" :read-only="true" :language="'shell'"></editor>
</bk-form-item>
<bk-form-item label="执行日志:">{{form.log}}</bk-form-item>
</bk-form>
</div>
</div>
@@ -72,8 +95,9 @@
</template>
<script>
import editor from '@/components/monacoEditor'
import statusList from './statusList.js'
import editor from '@/components/monacoEditor'
export default {
components: {
editor
@@ -111,19 +135,43 @@
label: '双人复核',
value: 2
}],
timeTypeList1: [{ // 执行时长告警时间类型下拉列表
value: 'hours',
label: '时'
},
{
value: 'minutes',
label: '分'
timeTypeList: [
{ // 执行时长告警时间类型下拉列表
value: 'hours',
label: '时'
},
{
value: 'minutes',
label: '分'
},
{
value: 'seconds',
label: '秒'
}
},
{
value: 'seconds',
label: '秒'
}
],
requestTypeList: [
{
value: 'get',
label: 'GET'
},
{
value: 'post',
label: 'POST'
},
{
value: 'put',
label: 'PUT'
},
{
value: 'head',
label: 'HEAD'
},
{
value: 'delete',
label: 'DELETE'
}
],
form: {
nodeData: {
@@ -169,28 +217,11 @@
}
},
created() {
this.form.nodeData = this.nodeData.data
if (!Object.keys(this.form.nodeData.file_dependence).length) {
this.form.nodeData.file_dependence = {
file_path: '', // 前置文件路径
max_num: '', // 巡检次数
cycle: { // 巡检周期
type: '', // 时间类型
value: '' // 时间值
}
}
}
this.form.log = this.nodeData.log
this.form = this.nodeData.data
this.form.state = this.nodeData.state
this.form.start_time = this.nodeData.start_time
this.form.end_time = this.nodeData.end_time
this.form.script_content = this.nodeData.script_content
if (this.form.nodeData.pre_commands.length === 0) {
this.form.pre_commands = [{ // 命令前置依赖检测
key: '',
value: ''
}]
}
}
}
</script>

View File

@@ -87,7 +87,6 @@
</template>
<script>
import editor from '@/components/monacoEditor'
import {
deepClone, getUUID
} from '../../../common/util.js'
@@ -95,6 +94,7 @@
import G6 from '@antv/g6'
import statusList from './job_flow_view_detail/statusList.vue'
import nodeInfo from './job_flow_view_detail/nodeInfo.vue'
import editor from '@/components/monacoEditor'
export default {
components: {
statusList,
@@ -216,7 +216,7 @@
this.timer = setInterval(() => {
// 不需要清空画布,非首屏刷新
this.handleLoad(false, false)
}, 15000)
}, 3000)
window.addEventListener('resize', this.handleChangeCavasSize, false)
},
beforeDestroy() {
@@ -595,6 +595,10 @@
}
// this.nodeDrawer.show = false
this.renderCanvas(true, first)
const processState = res.data.pipeline_tree.process_state
if (processState === 'success') {
clearInterval(this.timer)
}
} else {
this.$cwMessage(res.message, 'error')
}