w-vue-middle
Version:
统一公共服务组件
1,793 lines (1,740 loc) • 70.1 kB
JavaScript
/*
* @Author: Jason Liu
* @Date: 2022-08-03 13:13:03
* @Desc:
*/
const { Graph, Shape, Addon, Registry } = require('@antv/x6');
const { lineoption, controlsList } = require('@/components/designertackle/config');
/**
* @Author: Jason Liu
* @description: 调度服务接口
*/
const $dispatchcenter = require('@/api/dispatchcenter');
/**
* @Author: Jason Liu
* @description: 数据集成服务
*/
const $dataIntegration = require('@/api/dataIntegration');
const config = require('./components/config');
//设置区域
const esOutputOptoin = require('./components/esOutputOptoin').default;
const LakeOutputOptoin = require('./components/LakeOutputOptoin').default;
const sqlInputOptoin = require('./components/sqlInputOptoin').default;
const tableInputOptoin = require('./components/tableInputOptoin').default;
const messagesOptoin = require('./components/messagesOptoin').default;
const tableOutputOptoin = require('./components/tableOutputOptoin').default;
const tableMigrateOptoin = require('./components/tableMigrateOptoin').default;
const tableJoinOptoin = require('./components/tableJoinOptoin').default;
const kafaInputOptoin = require('./components/kafaInputOptoin').default;
const kafaInputsOptoin = require('./components/kafaInputsOptoin').default;
let runTestTime;
export default {
name: 'jobDesigner',
components: {
esOutputOptoin,
sqlInputOptoin,
tableInputOptoin,
messagesOptoin,
tableOutputOptoin,
tableMigrateOptoin,
tableJoinOptoin,
kafaInputOptoin,
kafaInputsOptoin,
LakeOutputOptoin,
},
props: {
value: {
type: Boolean,
default: false,
},
processId: {
//流程ID
type: [String, Number],
},
jobType: {
type: String,
},
jobGroupId: {
type: String,
},
},
data() {
return {
loading: false,
allLoading: false,
activeKey: '1',
show: this.value,
groupList: [], //作业分组
parentList: [], //父作业列表
flowGroups: [], //流程组
setBase: true, //设置基础信息
putawayNode: true, //收起node设置
logList: [],
logkeys: { log: {}, sql: {} }, //日志缓存记录
running: false,
clusters: [], //集群列表
debugClusters: [], //测试集群列表
sqlFunEditor: {
show: false,
text: undefined,
tables: {},
row: {},
},
debugs: {
testId: undefined,
jobLog: [],
jobSqls: [],
executionIds: [],
failedIds: [],
finishedIds: [],
status: undefined,
}, //调试信息
debuggerProcess: {
//流程调试
show: false,
putaway: true,
limit: 100,
jobDetail: {
steps: [],
hops: [],
},
},
activeJob: {
id: undefined,
data: {
id: undefined,
jobType: undefined,
jobGroupId: undefined,
},
},
jobExtraList: {},
activeNode: {
//选中的node节点
id: undefined,
size: { height: undefined, width: undefined },
position: { x: undefined, y: undefined },
shape: 'custom-input',
data: {
name: undefined,
type: undefined,
tableName: undefined,
tableColumns: [],
columns: [],
},
},
jobs: [],
rules: {
jobName: [{ required: true, message: $t('请输入流程名称!'), trigger: 'blur' }],
jobGroupId: [{ required: true, message: $t('请输入选择作业组!'), trigger: 'change' }],
},
control_str: undefined, //控件查询列表
lastType: undefined,
//作业的控件组
controlsJobList: [],
waitRemovedList: {}, //等待删除列表
setSubJobConfig: {
//子作业参数设置
setSubJobConfig: false, //搜索信息
subEdit: false,
jobs: [], //作业列表
transforms: [],
},
collectiondatas: {
//采集数据源
sourceLoading: false,
dataSource: [], //数据源
schemaLoading: false,
schema: [], //schema列表
dataTables: [], //数据表
showTables: [], //显示的表格信息
tableLoading: false,
columnLoading: false,
dwsAndads: {
dbInfo: {
schema: undefined,
dbName: undefined,
},
dws: [],
ads: [],
showData: [],
},
},
metadatas: {
//元数据平台数据源
sourceLoading: false,
dataSource: [], //数据源
schemaLoading: false,
schema: [], //schema列表
tableLoading: false,
showTables: [], //显示的表格信息
dataTables: [], //数据表
columnLoading: false,
dwds: {
dws: [],
dbInfo: {
schema: undefined,
dbName: undefined,
},
data: [],
},
dwsAndads: {
dbInfo: {
schema: undefined,
dbName: undefined,
},
dws: [],
ads: [],
showData: [],
},
},
setOutTables: {
//输出参数设置
setMap: false, //设置映射
str: undefined,
outstr: undefined,
overlay: false,
},
setPerlConfig: {
//Per参数设置
show: false,
config: {},
},
setTableJoinConfig: {
//设置表不关联配置
setJoin: false, //设置关联方式
setColumns: false, //设置显示字段
},
zoom: undefined, //缩放比例
integrationJobList: [], //基础作业列表
metadataCollectEnabled: '0', //元数据平台采集开关
sourceColumn: {
show: false,
tables: { columns: [] },
column: {},
},
debugSummarys: [], //调试结果
hasSqlInput: false, //是否有sql
mouseType: 'active', //鼠标类型
};
},
created() {
// this.getGroupList();
// this.geiClustersList();
// if (this.jobType == 'flow') {
// this.getFlowGroups();
// } else {
// this.getParentList();
// }
},
methods: {
/**
* @Author: Jason Liu
* @description: 设置画布数据
*/ setCanvas(data = { steps: [], hops: [] }, job) {
console.log(data);
const cells = [];
data.steps.forEach((node) => {
node.attrs = undefined;
if (node.data.type == 'SqlInput') {
this.hasSqlInput = true;
}
if (['TableInput', 'TableOutput'].indexOf(node.data.type) > -1) {
//兼容代码,将老数据的内容处理
node.data.whereString = node.data.whereString || undefined;
node.data.sourceType = node.data.sourceType || 0;
node.data.clusterId = node.data.clusterId || undefined;
node.data.dictColumn = node.data.dictColumn || undefined;
node.data.asName = node.data.asName || node.data.tableCode || 'temp';
node.data.schemaId = node.data.schemaId || node.data.schema;
node.data.data = undefined; //冗余数据清空
//TODO:mapping的兼容处理
} else if (['SubTransform'].indexOf(node.data.type) > -1) {
node.data.sourceType = node.data.sourceType || 0;
} else if (['TableJoin'].indexOf(node.data.type) > -1) {
node.data.tableCode = node.data.tableCode || 'temp';
}
node.component = undefined;
let cell = {
label: node.data.name,
...node,
};
cells.push(job.graph.createNode(cell));
});
data.hops.forEach((edge) => {
cells.push(
job.graph.createEdge({
...lineoption,
...edge,
}),
);
});
job.graph.resetCells(cells);
},
/**
* @Author: Jason Liu
* @description: 初始化画布
*/
initCanvas(
param = {
setBase: true,
putawayNode: true,
},
) {
this.$nextTick(() => {
this.jobs = this.jobs.map((job) => {
if (!job.graph && this.$refs[job.id]) {
//未初始化
this.controlsJobList = []; //重置控件列表
const graphOpetion = this.getGraphOpetion(job.id);
job.graph = new Graph(graphOpetion);
this.bindEvent(job);
job.dnd = new Addon.Dnd({
target: job.graph,
scaled: false,
animation: true,
});
if (job.data.jsonDetail) {
try {
let cells = JSON.parse(job.data.jsonDetail);
this.setCanvas(cells, job);
} catch (e) {}
}
}
if (job.id == this.activeJob.id) {
let jobs = this.jobs;
this.activeJob = {
id: this.activeJob.id,
graph: job.graph,
dnd: job.dnd,
loading: job.loading,
change: job.change,
data: job.data,
sourceStep: job.sourceStep,
};
this.jobExtraList = job.data.jobExtra ? JSON.parse(job.data.jobExtra) : {};
this.setBase = param.setBase; //设置基础信息
this.putawayNode = param.putawayNode; //收起node设置
this.zoom = this.activeJob.graph.zoom();
//对比控件栏位是否要切换
this.lastType = `${this.activeJob.data.jobType}`;
this.controlsJobList = controlsList.filter((item) => {
return item.maps.indexOf(this.activeJob.data.jobType) > -1;
});
this.$refs.controlsJobList.clearTreeExpand();
this.setAllTreeExpand();
}
return job;
});
});
},
/**
* @Author: Jason Liu
* @description: 还原设计状态
*/
reduction() {
this.setBase = true;
this.putawayNode = true;
},
/**
* @Author: Jason Liu
* @description: 对内容发生修改
*/
changeEndJob() {
this.jobs = this.jobs.map((job) => {
if (job.id == this.activeJob.id) {
job.change = true;
}
return job;
});
},
/**
* @Author: Jason Liu
* @description: 绑定事件
*/
bindEvent(_this) {
_this.graph.on('blank:click', ({ e, x, y }) => {
//("blank:click", e);
this.reduction();
});
_this.graph.on('cell:click', ({ e, x, y, cell, view }) => {
this.reduction();
cell.removeTools();
});
// 控制连接桩显示/隐藏
const showPorts = (ports, show) => {
for (let i = 0, len = ports.length; i < len; i = i + 1) {
ports[i].style.visibility = show ? 'visible' : 'hidden';
}
};
_this.graph.on('node:click', ({ e, x, y, node, view }) => {
const container = this.$refs[_this.id][0];
const ports = container.querySelectorAll('.x6-port-body');
showPorts(ports, true);
if (this.loading && this.mouseType != 'active') {
return false;
}
this.putawayNode = false;
let tempNode = node.toJSON();
this.activeNode = tempNode;
//获取选中控件的选择数据
//TODO:废除
this.getSelectData();
});
_this.graph.on('node:dblclick', ({ e, x, y, node, view }) => {
if (this.loading) {
return false;
}
let tempNode = node.toJSON();
this.activeNode = tempNode;
// 双击展开
if (tempNode.data.type == 'SubJob' || tempNode.data.type == 'SubTransform') {
if (tempNode.data.jobId) {
//存在ID进入编辑状态
this.setSubJob(tempNode.data.jobId, node);
} else {
//没有ID,进入新增状态
this.getJobDetail(undefined, tempNode.data.type.toLocaleLowerCase(), node);
}
}
// 关闭调试窗口
this.clearProcessTest();
});
_this.graph.on('node:mouseenter', () => {
const container = this.$refs[_this.id][0];
const ports = container.querySelectorAll('.x6-port-body');
showPorts(ports, true);
});
_this.graph.on('node:mouseleave', () => {
const container = this.$refs[_this.id][0];
const ports = container.querySelectorAll('.x6-port-body');
showPorts(ports, false);
});
_this.graph.on('node:moved', ({ node, index, options }) => {
//节点发生变化
if (node.id == this.activeNode.id) {
this.activeNode = node.toJSON();
}
});
_this.graph.on('node:resized', ({ node, index, options }) => {
//节点发生变化
if (node.id == this.activeNode.id) {
this.activeNode = node.toJSON();
}
});
_this.graph.on('node:removed', ({ node, index, options }) => {
//节点被删除
this.changeEndJob();
this.reduction();
});
_this.graph.on('node:added', ({ node, index, options }) => {
//创建
this.changeEndJob();
let now = new Date();
//更新数据的name
node.updateData({
id: node.id,
code: `${node.data.type}_${$storage.userInfo.userId}_${now.toJSON()}`,
});
this.setBase = true;
this.putawayNode = false;
this.activeNode = node.toJSON();
if (node.data.type == 'SqlInput') {
this.hasSqlInput = true;
}
this.getSelectData();
//this.reduction();
});
_this.graph.on('cell:mouseenter', ({ cell }) => {
let allCell = _this.graph.getCells();
allCell.forEach((_cell) => {
_cell.removeTools();
});
if (cell.isNode()) {
cell.addTools([
{
name: 'button-remove',
args: { x: 0, y: 0, offset: { x: 8, y: 8 } },
},
]);
} else {
cell.addTools([
{
name: 'button-remove',
args: {
x: 0,
y: 0,
offset: { x: 2, y: 2 },
},
},
]);
cell.addTools(
['vertices', 'source-arrowhead', 'target-arrowhead'].map((name) => {
return {
name: name,
args: { attrs: { fill: '#FF8C00' } },
};
}),
);
}
});
_this.graph.on('cell:mouseleave', ({ cell }) => {
// if (cell.isNode()) {
// cell.removeTools();
// } else {
// setTimeout(() => {
// cell.removeTools();
// }, 3000);
// }
});
_this.graph.on('node:change:data', ({ node }) => {
const edges = _this.graph.getIncomingEdges(node);
const { status } = node.getData();
if (edges) {
edges.forEach((edge) => {
if (status === 'running') {
edge.attr('line/strokeDasharray', 5);
edge.attr('line/style/animation', 'running-line 30s infinite linear');
} else {
edge.attr('line/strokeDasharray', '');
edge.attr('line/style/animation', '');
}
});
}
});
this.bindDocumentEvent(_this);
this.bindEdgeEvent(_this);
},
/**
* @Author: Jason Liu
* @description: 绑定页面事件
*/
bindDocumentEvent(_this) {
// 快捷键与事件
// copy cut paste
_this.graph.bindKey(['meta+c', 'ctrl+c'], () => {
const cells = _this.graph.getSelectedCells();
if (cells.length) {
_this.graph.copy(cells);
}
return false;
});
_this.graph.bindKey(['meta+x', 'ctrl+x'], () => {
const cells = _this.graph.getSelectedCells();
if (cells.length) {
_this.graph.cut(cells);
}
return false;
});
_this.graph.bindKey(['meta+v', 'ctrl+v'], () => {
if (!_this.graph.isClipboardEmpty()) {
const cells = _this.graph.paste({ offset: 32 });
_this.graph.cleanSelection();
_this.graph.select(cells);
}
return false;
});
//undo redo
_this.graph.bindKey(['meta+z', 'ctrl+z'], () => {
if (_this.graph.history.canUndo()) {
_this.graph.history.undo();
}
return false;
});
_this.graph.bindKey(['meta+shift+z', 'ctrl+shift+z'], () => {
if (_this.graph.history.canRedo()) {
_this.graph.history.redo();
}
return false;
});
// select all
_this.graph.bindKey(['meta+a', 'ctrl+a'], () => {
const nodes = _this.graph.getNodes();
if (nodes) {
_this.graph.select(nodes);
}
});
//delete
_this.graph.bindKey('backspace', () => {
const cells = _this.graph.getSelectedCells();
if (cells.length) {
_this.graph.removeCells(cells);
}
});
// zoom
_this.graph.bindKey(['ctrl+1', 'meta+1'], () => {
this.zoom = _this.graph.zoom();
if (this.zoom < 1.5) {
_this.graph.zoom(0.1);
}
});
_this.graph.bindKey(['ctrl+2', 'meta+2'], () => {
this.zoom = _this.graph.zoom();
if (this.zoom > 0.5) {
_this.graph.zoom(-0.1);
}
});
},
/**
* @Author: Jason Liu
* @description: 绑定连线事件
*/
bindEdgeEvent(_this) {
const connected = (edge) => {
let line = edge.toJSON();
if (line.source.cell == line.target.cell) {
this.$message.error($t('同一个组件不能及时连线的开始组件又是结束组件,连线将被移除。'));
edge.remove();
} else {
}
};
_this.graph.on('edge:removed', ({ isNew, edge }) => {
//删除线条事件
let line = edge.toJSON();
this.isSet = false;
this.changeEndJob();
this.reduction();
});
_this.graph.on('edge:click', ({ e, x, y, edge, view }) => {
//console.log("edge:click", e);
this.isSet = false;
});
_this.graph.on('edge:connected', ({ isNew, edge }) => {
// 线条链接完成
connected(edge);
});
_this.graph.on('edge:change:source', ({ edge, previous, options }) => {
if (previous.cell) {
edge.updateData({
source: previous,
});
}
let line = edge.toJSON();
if (options.propertyPath == 'source') {
//数据被还原了
connected(edge);
} else if (line.data && line.data.source && line.data.source.cell != line.source.cell) {
let changeNodes = {
source: _this.graph.getCellById(line.data.source.cell), //来源的数据
target: _this.graph.getCellById(line.target.cell), //目标的数据
};
if (changeNodes.source) {
//修改节点的内容
let changeNodesData = {
source: changeNodes.source.toJSON(),
target: changeNodes.target.toJSON(),
};
}
edge.updateData({
source: line.source,
});
}
});
_this.graph.on('edge:change:target', ({ edge, previous, options }) => {
if (previous.cell) {
edge.updateData({
target: previous,
});
}
let line = edge.toJSON();
if (
line.data &&
line.data.target.cell != line.source.cell &&
line.data.target.cell != line.target.cell
) {
if (options.propertyPath == 'target') {
//数据被还原了
connected(edge);
} else if (line.data && line.data.source.cell != line.source.cell) {
let changeNodes = {
source: _this.graph.getCellById(line.source.cell), //来源的数据
target: _this.graph.getCellById(line.data.target.cell), //目标的数据
};
if (changeNodes.source) {
//修改节点的内容
let changeNodesData = {
source: changeNodes.source.toJSON(),
target: changeNodes.target.toJSON(),
};
}
edge.updateData({
source: line.source,
});
}
edge.updateData({
target: line.target,
});
}
});
},
/**
* @Author: Jason Liu
* @description: 更新选中的节点
*/
updataNode(isAll) {
if (this.activeNode.id) {
const node = this.activeJob.graph.getCellById(this.activeNode.id);
if (isAll) {
node.setProp({
...this.activeNode,
});
}
if (node) {
node.updateData({
...this.activeNode.data,
});
}
}
},
/**
* @Author: Jason Liu
* @description: 获取选中控件的数据内容
*/
getSelectData() {
switch (
this.activeNode.data.type //遍历控件类型
) {
case 'SubJob': //子任务,获取任务列表
case 'SubTransform':
this.getJobList();
break;
}
},
/**
* @Author: Jason Liu
* @description: 修改作业列表
*/
changeSubJobList(jobId) {
if (jobId) {
this.getJobList();
this.activeNode.data.jobId = jobId;
}
if (this.activeNode.data.jobId) {
$dataIntegration
.getJobDetail({ id: this.activeNode.data.jobId })
.then((req) => {
this.activeNode.data.jobName = req.data.jobName;
this.activeNode.data.jobType = req.data.jobType;
let jobConfig = JSON.parse(req.data.jsonDetail);
this.activeNode.data.steps = jobConfig.steps.map((item) => {
return {
data: {
type: item.data.type,
name: item.data.type,
},
};
});
})
.finally(() => {
this.updataNode();
});
}
},
/**
* @Author: Jason Liu
* @description: 修改作业列表
*/
changeSubJobList() {
if (this.activeNode.data.jobId) {
$dataIntegration
.getJobDetail({ id: this.activeNode.data.jobId })
.then((req) => {
if (req.data) {
this.activeNode.data.jobName = req.data.jobName;
this.activeNode.data.jobType = req.data.jobType;
let jobConfig = JSON.parse(req.data.jsonDetail);
this.activeNode.data.steps = jobConfig.steps.map((item) => {
return {
data: {
type: item.data.type,
name: item.data.name,
},
};
});
} else {
this.$message.error($t('该设计已被删除'));
}
})
.finally(() => {
this.updataNode();
});
}
},
filterOption(input, option) {
return (
option.componentOptions.children[0].text.toLowerCase().indexOf(input.toLowerCase()) >= 0
);
},
/**
* @Author: Jason Liu
* @description: 添加流程
*/
addProcess(e) {
this.getJobDetail(undefined, e.key);
},
getGraphOpetion(id) {
return {
container: this.$refs[id][0], //容器对象
grid: true, //
autoResize: true, //是否允许更新容器大小
history: true,
height: '100%',
width: '100%',
panning: {
//支持水平平移
enabled: true,
eventTypes: ['leftMouseDown', 'rightMouseDown', 'mouseWheel'],
},
mousewheel: {
//允许缩放
enabled: true, //启动
zoomAtMousePosition: true,
modifiers: 'ctrl',
minScale: 0.5,
maxScale: 3,
/*
公开API
graph.zoom() // 获取缩放级别
graph.zoom(0.2) // 在原来缩放级别上增加 0.2
graph.zoom(-0.2) // 在原来缩放级别上减少 0.2
*/
},
connecting: {
//连线规则
router: {
name: 'manhattan',
args: { padding: 1 },
},
connector: {
name: 'rounded',
args: { radius: 8 },
},
anchor: 'center',
connectionPoint: 'anchor', //指定连接点
allowBlank: false, //是否允许连接到画布空白位置的点
snap: { radius: 20 }, //自动吸附
createEdge() {
//连接的过程中创建新的边
return new Shape.Edge(lineoption);
},
validateConnection({ targetMagnet }) {
//在移动边的时候判断连接是否有效
return !!targetMagnet;
},
},
highlighting: {
//选项来指定触发某种交互时的高亮样式
magnetAdsorbed: {
//连线过程中,自动吸附到链接桩
name: 'stroke',
args: {
attrs: {
fill: '#5F95FF',
stroke: '#5F95FF',
},
},
},
},
resizing: false, //缩放节点
rotating: false, //旋转节点
selecting: {
enabled: true,
rubberband: true,
showNodeSelectionBox: true,
},
minimap: {
enabled: true,
},
snapline: true, //对齐线是移动节点排版的辅助工具
keyboard: true, //键盘快捷键
clipboard: true, //剪切板
};
},
/**
* @Author: Jason Liu
* @description: 获取分组列表
*/
getGroupList() {
$dataIntegration
.getJobGroupList({
queryParams: {
F_isDel_eq: 0,
F_id_eq: this.jobGroupId,
},
})
.then((req) => {
this.groupList = req.data;
})
.finally(() => {});
},
getParentList() {
$dataIntegration
.getJobList({
pageNum: 1,
pageSize: 1000000,
queryParams: {
F_isDel_eq: 0,
F_jobType_eq: 'job',
F_parentId_isEmpty: null,
},
})
.then((req) => {
this.parentList = req.data.map((item) => {
return {
value: item.id,
label: item.jobName,
};
});
})
.catch(() => {});
},
/**
* @Author: Jason Liu
* @description: 获取流程组信息
*/
getFlowGroups() {
$dispatchcenter
.getCategoryList({
pageNum: 1,
pageSize: 10000,
queryParams: {
F_isDel_eq: 0,
},
})
.then((req) => {
this.flowGroups = req.data.map((row) => {
return {
value: row.id,
label: row.flowGroupName,
};
});
})
.finally(() => {});
},
/**
* @Author: Jason Liu
* @description: 设置子任务
*/
setSubJob(id, node) {
let job = this.jobs.find((item) => {
return item.id == id;
});
this.reduction();
if (job) {
this.activeJob.id = id;
this.initCanvas();
} else {
this.getJobDetail(id, this.activeJob.data.jobType, node);
}
},
/**
* @Author: Jason Liu
* @description: 获取job详情
*/
getJobDetail(processId, jobType, sourceStep) {
if (processId) {
this.loading = true;
switch (jobType) {
case 'flow':
$dispatchcenter
.getFlowInfo({ id: processId })
.then((req) => {
let job = {
createBy: undefined,
createTime: undefined,
id: req.data.id,
isDel: 0,
isEnable: 0,
jobType: jobType,
jobDesc: req.data.flowDesc,
jobGroupId: req.data.workflowGroup.id,
jobName: req.data.flowName,
jsonDetail: req.data.flowContent,
parentId: req.data.parentId,
remark: undefined,
updateBy: undefined,
updateTime: undefined,
};
if (job) {
this.activeJob.id = processId;
this.jobs.push({
id: processId,
graph: undefined, //画布
loading: false,
dnd: undefined, //插画
change: false,
data: job,
});
this.initCanvas();
} else {
this.$message.error($t('该设计已被删除'));
}
})
.finally(() => {
this.loading = false;
});
break;
default:
$dataIntegration
.getJobDetail({ id: processId })
.then((req) => {
let job = req.data;
if (job) {
this.activeJob.id = processId;
this.jobs.push({
id: processId,
graph: undefined, //画布
loading: false,
dnd: undefined, //插画
change: false,
data: job,
sourceStep: sourceStep,
});
if (job.jsonDetailBak) {
this.hasSqlInput = true;
} else {
this.hasSqlInput = false;
}
this.initCanvas();
} else {
this.$message.error($t('该设计已被删除'));
}
})
.finally(() => {
this.loading = false;
});
break;
}
} else {
let guid = `new_` + new Date().getTime();
let type = jobType || 'job';
let parentId = undefined;
let jobGroupId = this.jobGroupId;
switch (jobType) {
case 'subtransform':
type = 'transform';
jobGroupId = this.activeJob.data.jobGroupId;
parentId = this.activeJob.data.id;
break;
case 'subjob':
type = 'job';
parentId = this.activeJob.data.id;
jobGroupId = this.activeJob.data.jobGroupId;
break;
}
if (
(jobType == 'subtransform' || jobType == 'subjob') &&
parentId &&
parentId.indexOf('new') > -1
) {
//子数据无父级ID
this.$message.warning({
content: $t('请保存好主作业后再做添加操作'),
key: 'subadd',
});
} else {
let job = {
createBy: undefined,
createTime: undefined,
id: guid,
isDel: 0,
isEnable: 0,
jobType: type,
parentId: parentId,
jobDesc: undefined,
jobGroupId: jobGroupId,
jobName: undefined,
jsonDetail: undefined,
remark: undefined,
updateBy: undefined,
updateTime: undefined,
};
this.jobs.push({
id: guid,
graph: undefined, //画布
loading: false,
dnd: undefined, //插画
change: true,
data: job,
sourceStep: sourceStep,
});
this.activeJob.id = guid;
this.initCanvas();
}
}
},
/**
* @Author: Jason Liu
* @description: 获取集群列表
*/
geiClustersList() {
$dataIntegration
.getClusterManager({
pageNum: 1,
pageSize: 10000,
queryParams: {
F_isDel_eq: 0,
},
})
.then((req) => {
this.clusters = req.data.map((item) => {
return {
value: item.clusterId,
label: item.name,
clusterType: item.clusterType,
};
});
});
},
changeClusterType(val) {
if (!val) {
this.debugClusters = this.clusters;
} else {
this.debugClusters = this.clusters.filter((item) => {
return item.clusterType == this.debuggerProcess.clusterType;
});
}
this.debuggerProcess.clusterId =
this.debugClusters.length > 0 ? this.debugClusters[0].value : undefined;
},
/**
* @Author: Jason Liu
* @description: 启动流程调试
*/
runProcessTest() {
//this.logList = [];
let clusterId = undefined;
let clusterType = undefined;
this.$refs.setBody.$el.style.height = 'calc(100% - 220px)';
if (this.clusters.length > 0) {
clusterType = 1;
this.debugClusters = this.clusters.filter((item) => {
return item.clusterType == 1;
});
clusterId = this.debugClusters.length > 0 ? this.debugClusters[0].value : undefined;
}
this.debuggerProcess = {
//流程调试
show: true,
putaway: false,
limit: 100,
clusterType: clusterType,
clusterId: clusterId,
jobDetail: this.getConfigureData(this.activeJob),
};
this.debugSummarys = [];
// this.runTest();
},
/**
* @Author: Jason Liu
* @description: 关闭调试
*/
clearProcessTest() {
this.$refs.setBody.$el.style.height = '100%';
this.debuggerProcess = {
//流程调试
show: false,
putaway: true,
limit: 100,
jobDetail: this.getConfigureData(this.activeJob),
};
this.reductionTest();
},
/**
* @Author: Jason Liu
* @description: 启动测试执行
*/
runLoading(level = 1) {
let _this = this.activeJob;
this.debuggerProcess.jobDetail.steps.forEach((node) => {
let source = false;
let target = false;
this.debuggerProcess.jobDetail.hops.forEach((hop) => {
if (hop.target.cell == node.id) {
target = true;
}
if (hop.source.cell == node.id) {
source = true;
}
});
if (source && !target) {
let coll = _this.graph.getCellById(node.id);
if (coll.getData().status == 'default') {
coll.updateData({
...node,
status: 'running',
});
}
}
});
},
/**
* @Author: Jason Liu
* @description: 还原测试数据
*/
reductionTest() {
this.running = false;
clearTimeout(runTestTime);
if (this.debuggerProcess.jobDetail && this.debuggerProcess.jobDetail.steps) {
this.debuggerProcess.jobDetail.steps.forEach((node) => {
node.data.status = 'default';
});
this.logList = [];
this.debugSummarys = [];
this.setCanvas(this.debuggerProcess.jobDetail, this.activeJob);
}
},
/**
* @Author: Jason Liu
* @description: 执行测试
*/
runTest() {
this.reductionTest();
this.runLoading();
this.logList.push({
time: new Date(),
message: $t('开始调试,发送调试请求'),
type: 'start',
});
this.logkeys = { log: {}, sql: {} }; //重置历史记录
let query = {
id: this.activeJob.data.id,
jobType: this.activeJob.data.jobType,
jsonDetail: JSON.stringify(this.debuggerProcess.jobDetail),
limit: this.debuggerProcess.limit,
clusterId: this.debuggerProcess.clusterId,
};
this.running = true;
$dataIntegration
.runJobTest(query)
.then((req) => {
this.debugs = req.data;
this.logList.push({
time: new Date(),
type: this.debugs.status,
message: $t('系统已接受调试请求,监控状态中'),
});
this.getTestResult();
})
.catch((eorr) => {
console.log(eorr);
this.running = false;
this.logList.push({
time: new Date(),
type: 'eorr',
message: $t('系统异常,测试失败'),
});
});
},
/**
* @Author: Jason Liu
* @description: 获取测试的内容情况
*/
getTestResult() {
let _this = this.activeJob;
this.debugs.jobLog.forEach((log) => {
if (log) {
for (let key in log) {
if (log[key] && !this.logkeys.log[key]) {
this.logkeys.log[key] = true;
this.logList.push({
time: new Date(),
type: 'message',
message: `${log[key]}`,
});
}
}
}
});
if (this.debugs.jobSqls) {
let log = this.debugs.jobSqls;
for (let key in log) {
if (log[key] && !this.logkeys.sql[key]) {
this.logkeys.sql[key] = true;
this.logList.push({
time: new Date(),
type: 'message',
message: `${log[key]}`,
});
}
}
}
this.debugs.executionIds.forEach((ele) => {
//执行中
let node = this.debuggerProcess.jobDetail.steps.find((item) => {
return item.id == ele;
});
if (node) {
let coll = _this.graph.getCellById(node.id);
coll.updateData({
...node,
status: 'running',
});
this.logList.push({
time: new Date(),
type: 'processing',
item: node.data,
message: $t('[{slot1}]执行调试中...', { slot1: node.data.name }),
});
}
});
this.debugs.finishedIds.forEach((ele) => {
//已完成
let node = this.debuggerProcess.jobDetail.steps.find((item) => {
return item.id == ele;
});
if (node) {
let coll = _this.graph.getCellById(node.id);
coll.updateData({
...node,
status: 'success',
});
this.logList.push({
time: new Date(),
type: 'processing',
item: node.data,
message: $t('[{slot1}]执行完成', { slot1: node.data.name }),
});
}
});
this.debugs.failedIds.forEach((ele) => {
//执行失败
let node = this.debuggerProcess.jobDetail.steps.find((item) => {
return item.id == ele;
});
if (node) {
let coll = _this.graph.getCellById(node.id);
coll.updateData({
...node,
status: 'failed',
});
this.logList.push({
time: new Date(),
type: 'processing',
item: node,
message: $t('[{slot1}]执行失败', { slot1: node.data.name }),
});
}
});
switch (this.debugs.status) {
case 'RUNNING': //启动中
if (this.debugs.jobLog.length == 0) {
this.logList.push({
time: new Date(),
type: this.debugs.status,
message: $t('执行中...'),
});
}
runTestTime = setTimeout(() => {
$dataIntegration.getJobTestResult(this.debugs).then((res) => {
this.debugs = res.data;
if (res.data.debugSummary) {
this.debugSummarys = res.data.debugSummary.filter((item) => {
return !!item;
});
}
this.runLoading(2);
this.getTestResult();
});
}, 10000);
break;
case 'SUSPENDED':
this.logList.push({
time: new Date(),
type: this.debugs.status,
message: $t('当前配置未能启动'),
});
this.running = false;
clearTimeout(runTestTime);
break;
default:
this.running = false;
this.debuggerProcess.jobDetail.steps.forEach((node) => {
let coll = _this.graph.getCellById(node.id);
if (coll.getData().status == 'running') {
coll.updateData({
...node,
status: 'default',
});
}
});
this.logList.push({
time: new Date(),
type: this.debugs.status,
message: $t('调试完毕,最终给结果{slot1}', {
slot1: this.debugs.status == 'FINISHED' ? $t('【成功】') : $t('【失败】'),
}),
});
clearTimeout(runTestTime);
break;
}
//this.setCanvas(this.debuggerProcess.jobDetail, this.activeJob);
},
/**
* @Author: Jason Liu
* @description: 获取配置的内容
*/
getConfigureData(job) {
if (job.graph) {
return {
ver: '2.01',
//节点内容
steps: job.graph.getNodes().map((node) => {
let info = node.toJSON();
info.component = undefined;
info.ports.groups = undefined;
return info;
}),
//连线关系
hops: job.graph.getEdges().map((edge) => {
let info = edge.toJSON();
return info;
}),
};
}
},
/**
* @Author: Jason Liu
* @description: 获取选中的job对象
*/
getActiveJob() {
return this.jobs.find((job) => {
return job.id == this.activeJob.id;
});
},
/**
* @Author: Jason Liu
* @description: 保存选中
*/
saveThis() {
this.$refs.baseForm.validate((valid) => {
if (valid) {
this.loading = true;
this.reduction();
this.submit(this.getActiveJob()).finally(() => {
this.loading = false;
});
} else {
this.setBase = false;
this.putawayNode = true;
return false;
}
});
},
/**
* @Author: Jason Liu
* @description: 保存全部
*/
saveAll() {
let pass = true;
let callId = undefined;
const steps = this.jobs.map((job) => {
if (!job.data.jobName || !job.data.jobGroupId) {
pass = false;
callId = `${job.id}`;
}
return () => {
return this.submit(job);
};
});
if (pass) {
this.allLoading = true;
this.reduction();
Promise.all(
steps.map((step) => {
return step.call();
}),
)
.then((req) => {})
.finally(() => {
this.allLoading = false;
});
} else {
this.activeJob.id = callId;
this.initCanvas({
setBase: false,
putawayNode: true,
});
setTimeout(() => {
this.$refs.baseForm.validate();
}, 300);
}
},
/**
* @Author: Jason Liu
* @description: 提交数据
*/
submit(job) {
let param = this.getConfigureData(job);
job.change = true;
job.loading = true;
if (job.data.id && job.data.id.indexOf('new') > -1) {
job.data.id = undefined;
}
if (job.data.jobType == 'flow') {
let flow = {
flowDesc: job.data.jobDesc,
flowName: job.data.jobName,
id: job.data.id,
isDel: 0,
isEnable: 0,
workflowGroup: { id: job.data.jobGroupId },
flowContent: JSON.stringify(param),
};
return $dispatchcenter
.saveFlowInfo(flow)
.then((req) => {
this.$message.success({ content: $t('流程设置成功!'), key: 'save' });
if (!job.data.id) {
job.data.id = req.data.id;
}
return req;
})
.finally(() => {
job.change = false;
job.loading = false;
});
} else {
job.data.jsonDetail = JSON.stringify(param);
job.data.jobExtra = JSON.stringify(this.jobExtraList);
return $dataIntegration
.saveJob(job.data)
.then((req) => {
this.$message.success({
content: $t('配置保存成功!'),
key: 'save',
});
//this.show = false;
if (!job.data.id) {
job.data.id = req.data.id;
}
if (this.activeJob.sourceStep) {
this.jobs.forEach((job) => {
const sourceStep = job.graph.getCellById(this.activeJob.sourceStep.id);
if (sourceStep) {
sourceStep.updateData({
jobId: req.data.id,
name: req.data.jobName,
});
}
});
}
return req;
//this.$emit("update", req.data.id);
})
.finally(() => {
job.change = false;
job.loading = false;
});
}
},
/**
* @Author: Jason Liu
* @description: 开始拖动事件
*/
startDrag(e) {
if (this.debuggerProcess.show) {
this.$message.warning({
content: $t('调试状态,不可添加组件'),
key: 'startDrag',
});
return;
}
let job = this.activeJob;
let target = e.target.dataset;
let info = undefined;
const getDrag = (list) => {
list.forEach((item) => {
if (item.children && item.children.length > 0) {
getDrag(item.children);
} else if (item.id == target.id) {
info = item;
}
});
};
getDrag(this.controlsJobList);
if (info) {
let node = {};
switch (target.type) {
case 'SubJob':
case 'SubTransform':
case 'IntegrationJob':
node = {
shape: 'custom-input',
label: info.name,
data: {
id: undefined,
name: info.name,
code: undefined,
type: info.type, //组件类型
jobId: info.id == target.type ? undefined : info.id, //子任务ID
jobName: info.id == target.type ? undefined : info.name, //子任务名称
clusterId: undefined, //集群ID
timeout: 1, //超时时间
timeoutUnit: 'h', //超时类型 秒:s 分:m 时:h
steps: [], //子任务相关节点概览信息
hops: [], //子任务连线概览
schema: 'public',
lookUp: false,
sourceType: 0, //数据来源 0:子集 1:公共
description: undefined,
},
};
break;
case 'Start':
case 'End':
node = {
shape: 'custom-rect',
label: info.name,
data: {
id: undefined,
name: info.name,
code: undefined,
type: info.type, //组件类型
description: undefined,
},
};
break;
default:
node = {
shape: 'custom-input',
label: info.name,
data: info,
};
break;
}
job.dnd.start(job.graph.createNode(node), e);
}
},
/**
* @Author: Jason Liu
* @description: 展开树
*/
setAllTreeExpand() {
setTimeout(() => {
this.$nextTick(() => {
//安全数据处理
if (this.$refs.controlsJobList) {
this.$refs.controlsJobList.setAllTreeExpand(true);
}
});
}, 300);
},
/**
* @Author: Jason Liu
* @description: 加载子数据内容
*/
loadToolChildrenMethod({ row }) {
return new Promise((resolve) => {
switch (row.key) {
case 'basic':
resolve(config.basic);
break;
case 'conversioncomponent':
resolve(config.conversioncomponent);
break;
case 'inputcomponent':
resolve(config.inputcomponent);
break;
case 'outputcomponent':
resolve(config.outputcomponent);
break;
case 'flow':
$dispatchcenter
.getJobInfo({
pageNum: 1,
pageSize: 1000000,
queryParams: {
F_isDel_eq: 0,
F_jobType_eq: 'transfer',
F_scheduleType_eq: 'CRON',
},
})
.then((req) => {
const childs = req.data.map((item) => {
item.id = item.jobInfoId;
item.name = item.jobDesc;
item.type = 'IntegrationJob';
return item;
});
// if (childs.length == 0) {
// row.hasChild = false;
// }
this.integrationJobList = childs;
resolve(childs);
});
break;
default:
let parentId = this.activeJob.id;
if (parentId.indexOf('new') > -1 || this.activeJob.data.jobType == 'flow') {
parentId = undefined;
resolve([]);
} else {
$dataIntegration
.getJobList({
pageNum: 1,
pageSize: 1000000,
queryParams: {
F_isDel_eq: 0,
F_jobType_eq: row.id,
F_parentId_eq: parentId,
},
})
.then((req) => {
const childs = req.data.map((item) => {
item.name = item.jobName;
item.type = row.type == 'job' ? 'SubJob' : 'SubTransform';
return item;
});
// if (childs.length == 0) {
// row.hasChild = false;
// }
resolve(childs);
})
.catch(() => {
//row.hasChild = false;
resolve([]);
});
break;
}
}
}).finally(() => {
this.setAllTreeExpand();
});
},
/**
* @Author: Jason Liu
* @description: 修改node的关联数据
*/
changeNodesDssociate(node, changeNodes) {},
/**
* @Author: Jason Liu
* @description: 删除TableJoin的关联节点
*/
removeTableJoinNode(node, changeNodes) {},
/**
* @Author: Jason Liu
* @description: 获取下一层节点
*/
getNextNodes({ id }) {
let nextNodes = [];
this.activeJob.graph.getEdges().forEach((edge) => {
let line = edge.toJSON();
if (line.source.cell == id) {
nextNodes.push(this.activeJob.graph.getCellById(line.target.cell));
}
});
return nextNodes;
},
/**
* @Author: Jason Liu
* @description: 获取job列表
*/
getJobList() {
let parentId = this.activeJob.id;
if (parentId.indexOf('new') > -1 || this.activeJob.data.jobType == 'flow') {
parentId = undefined;
this.setSubJobConfig = {
//子作业参数设置
setSubJobConfig: false, //搜索信息
subEdit: false,
j