var app = new Vue({
|
el: '#app',
|
data: {
|
stations: [],
|
devices: [],
|
relations: [], // {stationId, deviceNo, deviceType}
|
|
lines: [], // {x1, y1, x2, y2, stationId, deviceNo}
|
|
draggingItem: null, // Currently dragged item
|
draggingLine: null, // Temporary line for visual feedback
|
|
saving: false,
|
|
containerOffset: { top: 0, left: 0 }
|
},
|
mounted: function() {
|
this.loadData();
|
|
// Listen to window resize to redraw lines
|
window.addEventListener('resize', this.updateLines);
|
|
// Listen to scroll events on lists to redraw lines
|
this.$refs.stationList.addEventListener('scroll', this.updateLines);
|
this.$refs.deviceList.addEventListener('scroll', this.updateLines);
|
},
|
beforeDestroy: function() {
|
window.removeEventListener('resize', this.updateLines);
|
},
|
methods: {
|
loadData: function() {
|
var that = this;
|
var loading = this.$loading({ lock: true, text: '加载数据中...', spinner: 'el-icon-loading', background: 'rgba(0, 0, 0, 0.7)' });
|
|
$.ajax({
|
url: baseUrl + '/basStationDevice/data/auth',
|
headers: { 'token': localStorage.getItem('token') },
|
method: 'GET',
|
success: function(res) {
|
loading.close();
|
if (res.code === 200) {
|
that.stations = res.data.stations || [];
|
that.devices = res.data.devices || [];
|
that.relations = res.data.relations || [];
|
|
// Delay to wait for DOM rendering
|
that.$nextTick(function() {
|
that.updateLines();
|
});
|
} else if (res.code === 403) {
|
top.location.href = baseUrl + "/";
|
} else {
|
that.$message.error('加载数据失败: ' + res.msg);
|
}
|
},
|
error: function() {
|
loading.close();
|
that.$message.error('加载请求异常');
|
}
|
});
|
},
|
|
saveData: function() {
|
var that = this;
|
this.saving = true;
|
|
$.ajax({
|
url: baseUrl + '/basStationDevice/save/auth',
|
type: 'POST',
|
headers: { 'token': localStorage.getItem('token') },
|
contentType: 'application/json',
|
data: JSON.stringify(this.relations),
|
success: function (res) {
|
that.saving = false;
|
if (res.code === 200) {
|
that.$message.success('保存成功');
|
that.loadData();
|
} else {
|
that.$message.error('保存失败: ' + res.msg);
|
}
|
},
|
error: function () {
|
that.saving = false;
|
that.$message.error('保存请求异常');
|
}
|
});
|
},
|
|
isStationConnected: function(stationId) {
|
return this.relations.some(function(r) { return r.stationId == stationId; });
|
},
|
|
isDeviceConnected: function(deviceNo, type) {
|
return this.relations.some(function(r) { return r.deviceNo == deviceNo && r.deviceType == type; });
|
},
|
|
// --- Drag and Drop Logic ---
|
|
onDragStart: function(event, item, type) {
|
this.draggingItem = { item: item, type: type };
|
event.dataTransfer.effectAllowed = 'link';
|
// Optional: set custom drag image
|
},
|
|
onDragEnd: function() {
|
this.draggingItem = null;
|
},
|
|
onDrop: function(event, targetDevice) {
|
if (!this.draggingItem || this.draggingItem.type !== 'station') {
|
return;
|
}
|
|
var station = this.draggingItem.item;
|
|
// Check if exists
|
var exists = this.relations.some(function(r) {
|
return r.stationId == station.stationId && r.deviceNo == targetDevice.deviceNo && r.deviceType == targetDevice.type;
|
});
|
|
if (exists) {
|
this.$message.warning('该关联已存在');
|
return;
|
}
|
|
// Add relation
|
this.relations.push({
|
stationId: station.stationId,
|
deviceNo: targetDevice.deviceNo,
|
deviceType: targetDevice.type
|
});
|
|
this.$message.success('已建立关联: 站点 ' + station.stationId + ' -> ' + targetDevice.name);
|
|
this.$nextTick(this.updateLines);
|
},
|
|
confirmDelete: function(index) {
|
var that = this;
|
var link = this.relations[index]; // Note: lines index must match relations index? No.
|
|
// We need to map line click to actual relation.
|
// The lines array is rebuilt from relations, so we can store the index or relation object in the line object.
|
// But let's check updateLines logic first.
|
|
// In updateLines, we iterate relations. So index matches if filtered correctly?
|
// Wait, updateLines maps relations 1-to-1 to lines IF DOM exists.
|
// If DOM doesn't exist (scrolled out?), line might not exist.
|
// But we should draw all lines?
|
// Actually, if scrolled out, we might want to hide lines or point to edge.
|
// For simplicity, we only draw lines for visible nodes or calculate positions for all.
|
// Since lists are scrollable, calculating positions for invisible nodes is tricky (top/bottom are relative to viewport).
|
|
// Better approach: Store the relation object in the line object.
|
|
var rel = this.lines[index].relation;
|
|
this.$confirm('确定删除该关联吗?', '提示', {
|
confirmButtonText: '确定',
|
cancelButtonText: '取消',
|
type: 'warning'
|
}).then(function() {
|
// Find index in relations array
|
var idx = that.relations.indexOf(rel);
|
if (idx > -1) {
|
that.relations.splice(idx, 1);
|
that.$nextTick(that.updateLines);
|
that.$message.success('已删除');
|
}
|
}).catch(function() {});
|
},
|
|
updateLines: function() {
|
var that = this;
|
var newLines = [];
|
|
// Get SVG offset
|
var svgElement = this.$el.querySelector('svg');
|
if (!svgElement) return;
|
var svgRect = svgElement.getBoundingClientRect();
|
|
// We need positions relative to the SVG
|
|
this.relations.forEach(function(rel) {
|
var sDom = document.getElementById('station-' + rel.stationId);
|
var dDom = document.getElementById('device-' + rel.deviceType + '-' + rel.deviceNo);
|
|
if (sDom && dDom) {
|
var sRect = sDom.getBoundingClientRect();
|
var dRect = dDom.getBoundingClientRect();
|
|
// Coordinates relative to SVG
|
var x1 = sRect.right - svgRect.left;
|
var y1 = sRect.top + sRect.height / 2 - svgRect.top;
|
|
var x2 = dRect.left - svgRect.left;
|
var y2 = dRect.top + dRect.height / 2 - svgRect.top;
|
|
newLines.push({
|
x1: x1,
|
y1: y1,
|
x2: x2,
|
y2: y2,
|
relation: rel,
|
stationId: rel.stationId,
|
deviceNo: rel.deviceNo
|
});
|
}
|
});
|
|
this.lines = newLines;
|
}
|
}
|
});
|