- Go backend (server/)
- Frontend (web/, server/static/)
- Database and deployment files
- Scripts and docs
Co-Authored-By: 狸花猫/Claude-Qwen3.6-Plus 🐾
514 lines
15 KiB
JavaScript
514 lines
15 KiB
JavaScript
"use strict";
|
||
|
||
Object.defineProperty(exports, "__esModule", {
|
||
value: true
|
||
});
|
||
exports.default = void 0;
|
||
var _tslib = require("tslib");
|
||
var _util = require("@antv/util");
|
||
var _util2 = _interopRequireDefault(require("../util"));
|
||
var _global = _interopRequireDefault(require("../global"));
|
||
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
||
/*
|
||
* @Author: moyee
|
||
* @LastEditors: moyee
|
||
* @Description: 拖动 Combo
|
||
*/
|
||
|
||
var calculationItemsBBox = _util2.default.calculationItemsBBox;
|
||
/**
|
||
* 遍历拖动的 Combo 下的所有 Combo
|
||
* @param data 拖动的 Combo
|
||
* @param fn
|
||
*/
|
||
var _traverseCombo = function traverseCombo(data, fn) {
|
||
if (fn(data) === false) {
|
||
return;
|
||
}
|
||
if (data) {
|
||
var combos = data.get('combos');
|
||
if (combos.length === 0) {
|
||
return false;
|
||
}
|
||
(0, _util.each)(combos, function (child) {
|
||
_traverseCombo(child, fn);
|
||
});
|
||
}
|
||
};
|
||
var _default = exports.default = {
|
||
getDefaultCfg: function getDefaultCfg() {
|
||
return {
|
||
enableDelegate: false,
|
||
delegateStyle: {},
|
||
// 拖动节点过程中是否只改变 Combo 的大小,而不改变其结构
|
||
onlyChangeComboSize: false,
|
||
// 拖动过程中目标 combo 状态样式
|
||
activeState: '',
|
||
selectedState: 'selected',
|
||
enableStack: true
|
||
};
|
||
},
|
||
getEvents: function getEvents() {
|
||
return {
|
||
'combo:mousedown': 'onMouseDown',
|
||
'combo:dragstart': 'onDragStart',
|
||
'combo:drag': 'onDrag',
|
||
'combo:dragend': 'onDragEnd',
|
||
'combo:drop': 'onDrop',
|
||
'node:drop': 'onNodeDrop',
|
||
'combo:dragenter': 'onDragEnter',
|
||
'combo:dragleave': 'onDragLeave'
|
||
};
|
||
},
|
||
validationCombo: function validationCombo(evt) {
|
||
var item = evt.item;
|
||
if (!item || item.destroyed) {
|
||
return false;
|
||
}
|
||
if (!this.shouldUpdate(evt, this)) {
|
||
return false;
|
||
}
|
||
var type = item.getType();
|
||
if (type !== 'combo') {
|
||
return false;
|
||
}
|
||
return true;
|
||
},
|
||
onMouseDown: function onMouseDown(evt) {
|
||
this.origin = {
|
||
x: evt.x,
|
||
y: evt.y
|
||
};
|
||
},
|
||
onDragStart: function onDragStart(evt) {
|
||
var _this = this;
|
||
var graph = this.graph;
|
||
var item = evt.item;
|
||
this.currentShouldEnd = true;
|
||
if (!this.validationCombo(evt)) return;
|
||
if (item.hasLocked()) {
|
||
return;
|
||
}
|
||
this.targets = [];
|
||
// 获取所有选中的 Combo
|
||
var combos = graph.findAllByState('combo', this.selectedState);
|
||
var currentCombo = item.get('id');
|
||
var dragCombos = combos.filter(function (combo) {
|
||
var comboId = combo.get('id');
|
||
return currentCombo === comboId;
|
||
});
|
||
if (dragCombos.length === 0) {
|
||
this.targets.push(item);
|
||
} else {
|
||
this.targets = combos.filter(function (combo) {
|
||
return !combo.hasLocked();
|
||
});
|
||
}
|
||
var beforeDragItems = [];
|
||
this.targets.forEach(function (t) {
|
||
var _a = t.getModel(),
|
||
x = _a.x,
|
||
y = _a.y,
|
||
id = _a.id;
|
||
beforeDragItems.push({
|
||
x: x,
|
||
y: y,
|
||
id: id
|
||
});
|
||
});
|
||
this.set('beforeDragItems', beforeDragItems);
|
||
if (this.activeState) {
|
||
this.targets.map(function (combo) {
|
||
var model = combo.getModel();
|
||
if (model.parentId) {
|
||
var parentCombo = graph.findById(model.parentId);
|
||
if (parentCombo) {
|
||
graph.setItemState(parentCombo, _this.activeState, true);
|
||
}
|
||
}
|
||
});
|
||
}
|
||
this.point = {};
|
||
this.originPoint = {};
|
||
this.currentItemChildCombos = [];
|
||
_traverseCombo(item, function (param) {
|
||
if (param.destroyed) {
|
||
return false;
|
||
}
|
||
var model = param.getModel();
|
||
_this.currentItemChildCombos.push(model.id);
|
||
return true;
|
||
});
|
||
},
|
||
onDrag: function onDrag(evt) {
|
||
var _this = this;
|
||
if (!this.origin) {
|
||
return;
|
||
}
|
||
if (!this.validationCombo(evt)) return;
|
||
if (this.enableDelegate) {
|
||
this.updateDelegate(evt);
|
||
} else {
|
||
if (this.activeState) {
|
||
var graph_1 = this.graph;
|
||
var item = evt.item;
|
||
var model_1 = item.getModel();
|
||
// 拖动过程中实时计算距离
|
||
var combos = graph_1.getCombos();
|
||
var sourceBBox = item.getBBox();
|
||
var centerX_1 = sourceBBox.centerX,
|
||
centerY_1 = sourceBBox.centerY,
|
||
width_1 = sourceBBox.width;
|
||
// 参与计算的 Combo,需要排除掉:
|
||
// 1、拖动 combo 自己
|
||
// 2、拖动 combo 的 parent
|
||
// 3、拖动 Combo 的 children
|
||
var calcCombos = combos.filter(function (combo) {
|
||
var cmodel = combo.getModel();
|
||
// 被拖动的是最外层的 Combo,无 parent,排除自身和子元素
|
||
if (!model_1.parentId) {
|
||
return cmodel.id !== model_1.id && !_this.currentItemChildCombos.includes(cmodel.id);
|
||
}
|
||
return cmodel.id !== model_1.id && !_this.currentItemChildCombos.includes(cmodel.id);
|
||
});
|
||
calcCombos.map(function (combo) {
|
||
var _a = combo.getBBox(),
|
||
cx = _a.centerX,
|
||
cy = _a.centerY,
|
||
w = _a.width;
|
||
// 拖动的 combo 和要进入的 combo 之间的距离
|
||
var disX = centerX_1 - cx;
|
||
var disY = centerY_1 - cy;
|
||
// 圆心距离
|
||
var distance = 2 * Math.sqrt(disX * disX + disY * disY);
|
||
if (width_1 + w - distance > 0.8 * width_1) {
|
||
graph_1.setItemState(combo, _this.activeState, true);
|
||
} else {
|
||
graph_1.setItemState(combo, _this.activeState, false);
|
||
}
|
||
});
|
||
}
|
||
(0, _util.each)(this.targets, function (item) {
|
||
_this.updateCombo(item, evt);
|
||
});
|
||
if (this.onlyChangeComboSize) {
|
||
// 拖动节点过程中,动态改变 Combo 的大小
|
||
this.updateParentCombos();
|
||
}
|
||
}
|
||
},
|
||
updatePositions: function updatePositions(evt, restore) {
|
||
var _this = this;
|
||
// 当启用 delegate 时,拖动结束时需要更新 combo
|
||
if (this.enableDelegate || restore) {
|
||
(0, _util.each)(this.targets, function (item) {
|
||
_this.updateCombo(item, evt, restore);
|
||
});
|
||
}
|
||
},
|
||
onDrop: function onDrop(evt) {
|
||
var _this = this;
|
||
// 被放下的目标 combo
|
||
var item = evt.item;
|
||
this.currentShouldEnd = this.shouldEnd(evt, item, this);
|
||
this.updatePositions(evt, !this.currentShouldEnd);
|
||
if (!this.currentShouldEnd || !item || !this.targets || item.destroyed) return;
|
||
var graph = this.graph;
|
||
var targetModel = item.getModel();
|
||
this.targets.map(function (combo) {
|
||
var model = combo.getModel();
|
||
if (model.parentId !== targetModel.id) {
|
||
if (_this.activeState) {
|
||
graph.setItemState(item, _this.activeState, false);
|
||
}
|
||
// 将 Combo 放置到某个 Combo 上面时,只有当 onlyChangeComboSize 为 false 时候才更新 Combo 结构
|
||
if (!_this.onlyChangeComboSize) {
|
||
graph.updateComboTree(combo, targetModel.id, false);
|
||
} else {
|
||
graph.updateCombo(combo);
|
||
}
|
||
} else {
|
||
graph.updateCombo(item);
|
||
}
|
||
});
|
||
this.end(item, evt);
|
||
// 如果已经拖放下了,则不需要再通过距离判断了
|
||
this.endComparison = true;
|
||
},
|
||
onNodeDrop: function onNodeDrop(evt) {
|
||
var _this = this;
|
||
if (!this.targets || this.targets.length === 0) return;
|
||
var graph = this.graph;
|
||
var item = evt.item;
|
||
var comboId = item.getModel().comboId;
|
||
var newParentCombo = comboId ? graph.findById(comboId) : undefined;
|
||
this.currentShouldEnd = this.shouldEnd(evt, newParentCombo, this);
|
||
this.updatePositions(evt, !this.currentShouldEnd);
|
||
if (!this.currentShouldEnd) return;
|
||
var droppedCombo;
|
||
// 如果被放置的的节点有 comboId,且这个 comboId 与正在被拖拽的 combo 的父 id 不相同,则更新父亲为 comboId
|
||
if (comboId) {
|
||
if (this.activeState) {
|
||
var combo = graph.findById(comboId);
|
||
graph.setItemState(combo, this.activeState, false);
|
||
}
|
||
this.targets.map(function (combo) {
|
||
if (!_this.onlyChangeComboSize) {
|
||
if (comboId !== combo.getID()) {
|
||
droppedCombo = graph.findById(comboId);
|
||
if (comboId !== combo.getModel().parentId) graph.updateComboTree(combo, comboId, false);
|
||
}
|
||
} else {
|
||
graph.updateCombo(combo);
|
||
}
|
||
});
|
||
} else {
|
||
// 如果被放置的节点没有 comboId,且正在被拖拽的 combo 有父 id,则更新父亲为 undefined
|
||
this.targets.map(function (combo) {
|
||
if (!_this.onlyChangeComboSize) {
|
||
var model = combo.getModel();
|
||
if (model.comboId) {
|
||
graph.updateComboTree(combo, undefined, false);
|
||
}
|
||
} else {
|
||
graph.updateCombo(combo);
|
||
}
|
||
});
|
||
}
|
||
// 如果已经拖放下了,则不需要再通过距离判断了
|
||
this.endComparison = true;
|
||
this.end(droppedCombo, evt);
|
||
},
|
||
onDragEnter: function onDragEnter(evt) {
|
||
if (!this.origin) {
|
||
return;
|
||
}
|
||
if (!this.validationCombo(evt)) return;
|
||
var item = evt.item;
|
||
var graph = this.graph;
|
||
if (this.activeState) {
|
||
graph.setItemState(item, this.activeState, true);
|
||
}
|
||
},
|
||
onDragLeave: function onDragLeave(evt) {
|
||
if (!this.origin) {
|
||
return;
|
||
}
|
||
if (!this.validationCombo(evt)) return;
|
||
var item = evt.item;
|
||
var graph = this.graph;
|
||
if (this.activeState) {
|
||
graph.setItemState(item, this.activeState, false);
|
||
}
|
||
},
|
||
onDragEnd: function onDragEnd(evt) {
|
||
if (!this.targets || this.targets.length === 0) return;
|
||
var item = evt.item;
|
||
if (this.currentShouldEnd) {
|
||
this.updatePositions(evt);
|
||
}
|
||
var parentCombo = this.getParentCombo(item.getModel().parentId);
|
||
var graph = this.graph;
|
||
if (parentCombo && this.activeState) {
|
||
graph.setItemState(parentCombo, this.activeState, false);
|
||
}
|
||
this.end(undefined, evt);
|
||
},
|
||
end: function end(comboDropedOn, evt) {
|
||
var _this = this;
|
||
if (!this.origin) return;
|
||
var graph = this.graph;
|
||
// 删除delegate shape
|
||
if (this.delegateShape) {
|
||
var delegateGroup = graph.get('delegateGroup');
|
||
delegateGroup.clear();
|
||
this.delegateShape = null;
|
||
}
|
||
if (comboDropedOn && this.activeState) {
|
||
graph.setItemState(comboDropedOn, this.activeState, false);
|
||
}
|
||
// 若没有被放置的 combo,则是被放置在画布上
|
||
if (!comboDropedOn) {
|
||
var stack_1 = graph.get('enabledStack') && this.enableStack;
|
||
var stackData_1 = {
|
||
before: {
|
||
nodes: [],
|
||
edges: [],
|
||
combos: [].concat(this.get('beforeDragItems'))
|
||
},
|
||
after: {
|
||
nodes: [],
|
||
edges: [],
|
||
combos: []
|
||
}
|
||
};
|
||
this.targets.map(function (combo) {
|
||
// 将 Combo 放置到某个 Combo 上面时,只有当 onlyChangeComboSize 为 false 时候才更新 Combo 结构
|
||
if (!_this.onlyChangeComboSize) {
|
||
graph.updateComboTree(combo, undefined, stack_1);
|
||
} else {
|
||
graph.updateCombo(combo);
|
||
var _a = combo.getModel(),
|
||
x = _a.x,
|
||
y = _a.y,
|
||
id = _a.id;
|
||
stackData_1.after.combos.push({
|
||
x: x,
|
||
y: y,
|
||
id: id
|
||
});
|
||
graph.pushStack('update', stackData_1);
|
||
}
|
||
});
|
||
}
|
||
this.point = [];
|
||
this.origin = null;
|
||
this.originPoint = null;
|
||
this.targets.length = 0;
|
||
},
|
||
/**
|
||
* 遍历 comboTree,分别更新 node 和 combo
|
||
* @param data
|
||
* @param fn
|
||
*/
|
||
traverse: function traverse(data, fn, edgesToBeUpdate) {
|
||
var _this = this;
|
||
if (edgesToBeUpdate === void 0) {
|
||
edgesToBeUpdate = {};
|
||
}
|
||
if (fn(data, edgesToBeUpdate) === false) {
|
||
return;
|
||
}
|
||
if (data) {
|
||
var combos = data.get('combos');
|
||
(0, _util.each)(combos, function (child) {
|
||
_this.traverse(child, fn, edgesToBeUpdate);
|
||
});
|
||
var nodes = data.get('nodes');
|
||
(0, _util.each)(nodes, function (child) {
|
||
_this.traverse(child, fn, edgesToBeUpdate);
|
||
});
|
||
}
|
||
},
|
||
updateCombo: function updateCombo(item, evt, restore) {
|
||
this.updateSingleItem(item, evt, restore);
|
||
var edgesToBeUpdate = {};
|
||
this.traverse(item, function (paramItem, paramEdgesMap) {
|
||
if (paramItem.destroyed) {
|
||
return false;
|
||
}
|
||
paramItem.getEdges().forEach(function (edge) {
|
||
return paramEdgesMap[edge.getID()] = edge;
|
||
});
|
||
return true;
|
||
}, edgesToBeUpdate);
|
||
Object.values(edgesToBeUpdate).forEach(function (edge) {
|
||
return edge.refresh();
|
||
});
|
||
},
|
||
/**
|
||
*
|
||
* @param item 当前正在拖动的元素
|
||
* @param evt
|
||
*/
|
||
updateSingleItem: function updateSingleItem(item, evt, restore) {
|
||
var origin = this.origin;
|
||
var graph = this.graph;
|
||
var model = item.getModel();
|
||
var itemId = item.get('id');
|
||
if (!this.point[itemId]) {
|
||
this.point[itemId] = {
|
||
x: model.x,
|
||
y: model.y
|
||
};
|
||
}
|
||
var x = evt.x - origin.x + this.point[itemId].x;
|
||
var y = evt.y - origin.y + this.point[itemId].y;
|
||
if (restore) {
|
||
x += origin.x - evt.x;
|
||
y += origin.y - evt.y;
|
||
}
|
||
graph.updateItem(item, {
|
||
x: x,
|
||
y: y
|
||
}, false);
|
||
// item.getEdges()?.forEach(edge => edge.refresh());
|
||
},
|
||
/**
|
||
* 根据 ID 获取父 Combo
|
||
* @param parentId 父 Combo ID
|
||
*/
|
||
getParentCombo: function getParentCombo(parentId) {
|
||
var graph = this.graph;
|
||
if (!parentId) {
|
||
return undefined;
|
||
}
|
||
var parentCombo = graph.findById(parentId);
|
||
if (!parentCombo) {
|
||
return undefined;
|
||
}
|
||
return parentCombo;
|
||
},
|
||
updateDelegate: function updateDelegate(evt) {
|
||
var graph = this.graph;
|
||
// 当没有 delegate shape 时创建
|
||
if (!this.delegateShape) {
|
||
var delegateGroup = graph.get('delegateGroup');
|
||
var bbox = null;
|
||
if (this.targets.length > 1) {
|
||
bbox = calculationItemsBBox(this.targets);
|
||
} else {
|
||
bbox = this.targets[0].getBBox();
|
||
}
|
||
var x = bbox.x,
|
||
y = bbox.y,
|
||
width = bbox.width,
|
||
height = bbox.height,
|
||
minX = bbox.minX,
|
||
minY = bbox.minY;
|
||
this.originPoint = {
|
||
x: x,
|
||
y: y,
|
||
width: width,
|
||
height: height,
|
||
minX: minX,
|
||
minY: minY
|
||
};
|
||
var attrs = (0, _tslib.__assign)((0, _tslib.__assign)({}, _global.default.delegateStyle), this.delegateStyle);
|
||
this.delegateShape = delegateGroup.addShape('rect', {
|
||
attrs: (0, _tslib.__assign)({
|
||
width: bbox.width,
|
||
height: bbox.height,
|
||
x: bbox.x,
|
||
y: bbox.y
|
||
}, attrs),
|
||
name: 'combo-delegate-shape'
|
||
});
|
||
this.delegateShape.set('capture', false);
|
||
this.delegate = this.delegateShape;
|
||
} else {
|
||
var clientX = evt.x - this.origin.x + this.originPoint.minX;
|
||
var clientY = evt.y - this.origin.y + this.originPoint.minY;
|
||
this.delegateShape.attr({
|
||
x: clientX,
|
||
y: clientY
|
||
});
|
||
}
|
||
},
|
||
/**
|
||
* updates the parent combos' size and position
|
||
*/
|
||
updateParentCombos: function updateParentCombos() {
|
||
var _a = this,
|
||
graph = _a.graph,
|
||
targets = _a.targets;
|
||
var comboParentMap = {};
|
||
targets === null || targets === void 0 ? void 0 : targets.forEach(function (target) {
|
||
var comboId = target.getModel().parentId;
|
||
if (comboId) comboParentMap[comboId] = graph.findById(comboId);
|
||
});
|
||
Object.values(comboParentMap).forEach(function (combo) {
|
||
if (combo) graph.updateCombo(combo);
|
||
});
|
||
}
|
||
}; |