#
Junjie
2026-01-14 b77d09f258ef7d5458f61ff1a90d1a686cb2f181
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
var app = new Vue({
    el: '#app',
    data: {
        stations: [],
        areas: [],
        relations: [],
        lines: [],
        draggingItem: null,
        draggingLine: null,
        saving: false,
        newAreaCode: '',
        newAreaName: ''
    },
    mounted: function() {
        this.loadData();
        window.addEventListener('resize', this.updateLines);
        this.$nextTick(function() {
            if (this.$refs.stationList) this.$refs.stationList.addEventListener('scroll', this.updateLines);
            if (this.$refs.areaList) this.$refs.areaList.addEventListener('scroll', this.updateLines);
        }.bind(this));
    },
    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 + '/basOutStationArea/data/auth',
                headers: { 'token': localStorage.getItem('token') },
                method: 'GET',
                success: function(res) {
                    loading.close();
                    if (res.code === 200) {
                        that.stations = res.data.stations || [];
                        that.areas = res.data.areas || [];
                        that.relations = res.data.relations || [];
                        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;
            var payload = {
                areas: this.areas,
                relations: this.relations
            };
            $.ajax({
                url: baseUrl + '/basOutStationArea/save/auth',
                type: 'POST',
                headers: { 'token': localStorage.getItem('token') },
                contentType: 'application/json',
                data: JSON.stringify(payload),
                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('保存请求异常');
                }
            });
        },
        addArea: function() {
            var code = (this.newAreaCode || '').trim();
            var name = (this.newAreaName || '').trim();
            if (!code || !name) {
                this.$message.warning('请输入区域编码和名称');
                return;
            }
            var exists = this.areas.some(function(a) { return a.areaCode === code; });
            if (exists) {
                this.$message.warning('区域已存在');
                return;
            }
            this.areas.push({ areaCode: code, areaName: name });
            this.newAreaCode = '';
            this.newAreaName = '';
            this.$nextTick(this.updateLines);
        },
        removeArea: function(areaCode) {
            this.areas = this.areas.filter(function(a) { return a.areaCode !== areaCode; });
            this.relations = this.relations.filter(function(r) { return r.areaCode !== areaCode; });
            this.$nextTick(this.updateLines);
        },
        isStationBound: function(stationId) {
            return this.relations.some(function(r) { return r.stationId == stationId; });
        },
        isAreaBound: function(areaCode) {
            return this.relations.some(function(r) { return r.areaCode == areaCode; });
        },
        onDragStart: function(event, item, type) {
            this.draggingItem = { item: item, type: type };
            event.dataTransfer.effectAllowed = 'link';
        },
        onDragEnd: function() {
            this.draggingItem = null;
            this.draggingLine = null;
        },
        onDrop: function(event, targetArea) {
            if (!this.draggingItem || this.draggingItem.type !== 'station') return;
            var station = this.draggingItem.item;
            var exists = this.relations.some(function(r) {
                return r.stationId == station.stationId && r.areaCode == targetArea.areaCode;
            });
            if (exists) {
                this.$message.warning('该绑定已存在');
                return;
            }
            this.relations.push({
                stationId: station.stationId,
                areaCode: targetArea.areaCode
            });
            this.$message.success('已建立绑定: 站点 ' + station.stationId + ' -> 区域 ' + (targetArea.areaName || targetArea.areaCode));
            this.$nextTick(this.updateLines);
        },
        confirmDelete: function(index) {
            var rel = this.lines[index] && this.lines[index].relation;
            if (!rel) return;
            this.relations = this.relations.filter(function(r) {
                return !(r.stationId == rel.stationId && r.areaCode == rel.areaCode);
            });
            this.$nextTick(this.updateLines);
        },
        updateLines: function() {
            var svg = document.querySelector('svg');
            if (!svg) return;
            var svgRect = svg.getBoundingClientRect();
            var newLines = [];
            this.relations.forEach(function(rel) {
                var sDom = document.getElementById('station-' + rel.stationId);
                var aDom = document.getElementById('area-' + rel.areaCode);
                if (sDom && aDom) {
                    var sRect = sDom.getBoundingClientRect();
                    var aRect = aDom.getBoundingClientRect();
                    var x1 = sRect.right - svgRect.left;
                    var y1 = sRect.top + sRect.height / 2 - svgRect.top;
                    var x2 = aRect.left - svgRect.left;
                    var y2 = aRect.top + aRect.height / 2 - svgRect.top;
                    newLines.push({
                        x1: x1, y1: y1, x2: x2, y2: y2,
                        relation: rel,
                        stationId: rel.stationId,
                        areaCode: rel.areaCode
                    });
                }
            });
            this.lines = newLines;
        }
    }
});