#
Junjie
3 天以前 706eabba4750cf92282378ae5d2414f497a4578c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
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;
        }
    }
});