#
Junjie
2026-01-14 664d9030efca22edd8e43b4db4b2c0700fff44af
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
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="utf-8">
    <title>出库站与出库区域绑定配置</title>
    <meta name="renderer" content="webkit">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
    <link rel="stylesheet" href="../../static/vue/element/element.css">
    <link rel="stylesheet" href="../../static/css/cool.css">
    <style>
        html, body { height: 100%; margin: 0; padding: 0; background-color: #f0f2f5; }
        #app { height: 100%; padding: 20px; box-sizing: border-box; display: flex; flex-direction: column; }
        .main-card { flex: 1; display: flex; flex-direction: column; overflow: hidden; }
        .flow-container { flex: 1; display: flex; position: relative; background: #fff; border: 1px solid #ebeef5; overflow: hidden; }
        .column { width: 300px; display: flex; flex-direction: column; border-right: 1px solid #ebeef5; background-color: #fcfcfc; z-index: 10; }
        .column.right { border-right: none; border-left: 1px solid #ebeef5; position: absolute; right: 0; top: 0; bottom: 0; }
        .column-header { padding: 15px; text-align: center; font-weight: bold; background-color: #f5f7fa; border-bottom: 1px solid #ebeef5; color: #606266; }
        .list-container { flex: 1; overflow-y: auto; padding: 10px; }
        .node-item { padding: 12px; margin-bottom: 10px; background-color: #fff; border: 1px solid #dcdfe6; border-radius: 4px; cursor: grab; transition: all 0.3s; position: relative; color: #606266; font-size: 14px; display: flex; justify-content: space-between; align-items: center; }
        .node-item:hover { box-shadow: 0 2px 12px 0 rgba(0,0,0,0.1); border-color: #409eff; }
        .node-item.active { background-color: #ecf5ff; border-color: #409eff; color: #409eff; }
        .station-node { border-left: 4px solid #67c23a; }
        .area-node { border-left: 4px solid #e6a23c; }
        .canvas-area { flex: 1; position: relative; margin-right: 300px; background-color: #fafafa; overflow: hidden; }
        svg { position: absolute; top: 0; left: 0; width: 100%; height: 100%; pointer-events: none; }
        svg line { stroke: #909399; stroke-width: 2; cursor: pointer; pointer-events: stroke; transition: stroke-width 0.2s, stroke 0.2s; }
        svg line:hover { stroke: #f56c6c; stroke-width: 4; }
        .toolbar { padding: 10px 0; display: flex; justify-content: space-between; align-items: center; }
        .area-toolbar { padding: 10px; border-bottom: 1px solid #ebeef5; }
    </style>
    </head>
<body>
<div id="app" v-cloak>
    <el-card class="main-card" :body-style="{ padding: '0px', display: 'flex', flexDirection: 'column', height: '100%' }">
        <div slot="header" class="clearfix">
            <span style="font-weight: bold; font-size: 16px;">出库站与出库区域绑定配置</span>
            <div style="float: right;">
                <el-button type="primary" icon="el-icon-check" size="small" @click="saveData" :loading="saving">保存配置</el-button>
                <el-button icon="el-icon-refresh" size="small" @click="loadData">刷新</el-button>
            </div>
        </div>
        <div class="toolbar" style="padding: 10px 20px; border-bottom: 1px solid #ebeef5;">
            <el-alert title="操作说明:拖拽左侧【出库站点】到右侧【出库区域】上建立绑定。点击连线可删除绑定。" type="info" show-icon :closable="false"></el-alert>
        </div>
        <div class="flow-container" ref="flowContainer">
            <div class="column">
                <div class="column-header">出库站点 ({{ stations.length }})</div>
                <div class="list-container" ref="stationList">
                    <div v-for="item in stations" :key="'s-' + item.stationId" :id="'station-' + item.stationId" class="node-item station-node" :class="{ active: isStationBound(item.stationId) }" draggable="true" @dragstart="onDragStart($event, item, 'station')" @dragend="onDragEnd">
                        <span>{{ item.stationId }}</span>
                    </div>
                </div>
            </div>
            <div class="canvas-area">
                <svg width="100%" height="100%">
                    <line v-for="(link, index) in lines" :key="index" :x1="link.x1" :y1="link.y1" :x2="link.x2" :y2="link.y2" @click="confirmDelete(index)">
                        <title>点击删除绑定: 站点 {{ link.stationId }} -> 区域 {{ link.areaCode }}</title>
                    </line>
                    <line v-if="draggingLine" :x1="draggingLine.x1" :y1="draggingLine.y1" :x2="draggingLine.x2" :y2="draggingLine.y2" stroke="#409eff" stroke-dasharray="5,5" stroke-width="2" />
                </svg>
            </div>
            <div class="column right">
                <div class="column-header">出库区域 ({{ areas.length }})</div>
                <div class="area-toolbar">
                    <el-input size="small" placeholder="区域编码" v-model="newAreaCode" style="width: 140px; margin-right: 8px;"></el-input>
                    <el-input size="small" placeholder="区域名称" v-model="newAreaName" style="width: 140px; margin-right: 8px;"></el-input>
                    <el-button size="small" type="primary" icon="el-icon-plus" @click="addArea">新增区域</el-button>
                </div>
                <div class="list-container" ref="areaList">
                    <div v-for="item in areas" :key="'a-' + item.areaCode" :id="'area-' + item.areaCode" class="node-item area-node" :class="{ active: isAreaBound(item.areaCode) }" @dragover.prevent @drop="onDrop($event, item)">
                        <span>{{ item.areaCode }} - {{ item.areaName }}</span>
                        <el-button type="text" size="mini" @click="removeArea(item.areaCode)">删除</el-button>
                    </div>
                </div>
            </div>
        </div>
    </el-card>
</div>
<script type="text/javascript" src="../../static/js/jquery/jquery-3.3.1.min.js"></script>
<script type="text/javascript" src="../../static/vue/js/vue.min.js"></script>
<script type="text/javascript" src="../../static/vue/element/element.js"></script>
<script type="text/javascript" src="../../static/js/common.js" charset="utf-8"></script>
<script type="text/javascript" src="../../static/js/basOutStationArea/basOutStationArea.js"></script>
</body>
</html>