<!DOCTYPE html>
|
<html lang="en">
|
<head>
|
<meta charset="UTF-8">
|
<title>WCS控制中心</title>
|
<link rel="stylesheet" href="../../static/css/animate.min.css">
|
<link rel="stylesheet" href="../../static/vue/element/element.css">
|
<link rel="stylesheet" href="../../static/css/watch/console_vue.css">
|
<script type="text/javascript" src="../../static/js/jquery/jquery-3.3.1.min.js"></script>
|
<script type="text/javascript" src="../../static/layui/layui.js"></script>
|
<script type="text/javascript" src="../../static/js/handlebars/handlebars-v4.5.3.js"></script>
|
<script type="text/javascript" src="../../static/js/common.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>
|
</head>
|
<body>
|
<div id="app">
|
<div style="display: flex;margin-top: 30px;margin-left: 20px;">
|
<div style="width: 20%;height: 60vh;margin-right: 20px;">
|
<el-tabs type="border-card" v-model="activateCard" @tab-click="handleCardClick">
|
<el-tab-pane label="堆垛机" name="crn">
|
<watch-crn-card :param="crnParam"></watch-crn-card>
|
</el-tab-pane>
|
<el-tab-pane label="输送站" name="devp">
|
<devp-card :param="devpParam"></devp-card>
|
</el-tab-pane>
|
<el-tab-pane label="RGV" name="rgv">
|
<watch-rgv-card :param="rgvParam"></watch-rgv-card>
|
</el-tab-pane>
|
<el-tab-pane label="地图配置" name="mapSetting">
|
<map-setting-card :param="mapSettingParam"></map-setting-card>
|
</el-tab-pane>
|
</el-tabs>
|
</div>
|
|
<div style="position: absolute;top: 15px;left: 50%;display: flex;">
|
<div v-if="levList.length > 1" v-for="(lev,index) in levList" :key="index" style="margin-right: 10px;">
|
<el-button :type="currentLev == lev ? 'primary' : ''" @click="switchLev(lev)" size="mini">{{ lev }}F</el-button>
|
</div>
|
</div>
|
|
<div id="mapDataId" style="position: relative;margin-top: 50px;" :style="{zoom: mapSettingParam.zoom / 100}">
|
<table class="excel-table">
|
<tr v-for="(row,index) in map" :key="index">
|
<td
|
v-for="(col,idx) in row" :key="idx"
|
:rowspan="col.rowSpan"
|
:colspan="col.colSpan"
|
:style="{width: col.width}"
|
v-if="col.type != 'merge'"
|
>
|
<div v-if="col.type == 'none'">
|
<div class="item" style="visibility: hidden">{{idx}}</div>
|
</div>
|
<div v-else-if="col.type == 'shelf'">
|
<div class="shelf">{{col.shelfIdx}}</div>
|
</div>
|
<div v-else-if="col.type == 'devp'">
|
<div class="site" :style="{height: col.rowPx}" :id="'site-' + getStationId(col.value)" @click="openSite(getStationId(col.value))">{{getStationId(col.value)}}</div>
|
</div>
|
<div v-else-if="col.type == 'rgv'" style="position: relative;">
|
<div class="rgv-item" v-if="getDeviceNo(col.value) != -1" :style="{width: col.width}" :id="'rgv-' + getDeviceNo(col.value)" @click="openRgv(getDeviceNo(col.value))">{{getDeviceNo(col.value)}}</div>
|
<div class="track-item" v-if="getTrackSiteNo(col.value) == -1"></div>
|
<div class="track-item" v-else :id="'rgvTrackSiteNo-' + getTrackSiteNo(col.value)"></div>
|
</div>
|
<div v-else-if="col.type == 'crn'">
|
<div class="crn-item" v-if="getDeviceNo(col.value) != -1" :style="{width: col.width}" :id="'crn-' + getDeviceNo(col.value)" @click="openCrn(getDeviceNo(col.value))">{{getDeviceNo(col.value)}}</div>
|
<div class="track-item track-crn" v-if="getTrackSiteNo(col.value) == -1"></div>
|
<div class="track-item track-crn" v-else :id="'crnTrackSiteNo-' + getTrackSiteNo(col.value)"></div>
|
</div>
|
</td>
|
|
</tr>
|
</table>
|
</div>
|
</div>
|
|
</div>
|
|
<script src="../../components/WatchCrnCard.js"></script>
|
<script src="../../components/DevpCard.js"></script>
|
<script src="../../components/MapSettingCard.js"></script>
|
<script src="../../components/WatchRgvCard.js"></script>
|
<script>
|
var app = new Vue({
|
el: '#app',
|
data: {
|
map: [],//地图数据
|
levList: [],
|
currentLev: 1,
|
systemStatus: true,//系统运行状态
|
consoleInterval: null,//定时器存储变量
|
rgvPosition: [],
|
activateCard: 'crn',
|
crnParam: {
|
crnNo: 0
|
},
|
mapSettingParam: {
|
zoom: 70
|
},
|
devpParam: {
|
stationId: 0
|
},
|
rgvParam: {
|
rgvNo: 0
|
}
|
},
|
created() {
|
this.init()
|
},
|
watch: {
|
|
},
|
methods: {
|
init() {
|
this.getMap()
|
this.getSystemRunningStatus() //获取系统运行状态
|
this.getLevList() //获取地图层级列表
|
|
this.consoleInterval = setInterval(() => {
|
this.getCrnInfo() //获取堆垛机数据
|
this.getSiteInfo() //获取输送站点数据
|
this.getRgvInfo() //获取RGV数据
|
}, 1000)
|
},
|
getLevList() {
|
let that = this;
|
$.ajax({
|
url: baseUrl + "/basMap/getLevList",
|
headers: {
|
'token': localStorage.getItem('token')
|
},
|
method: "get",
|
success: (res) => {
|
let data = res.data;
|
that.levList = data;
|
}
|
})
|
},
|
//获取地图数据
|
getMap() {
|
let that = this
|
let rowPx = 35;
|
let colPx = 35;
|
|
$.ajax({
|
url: baseUrl + "/basMap/lev/" + this.currentLev + "/auth",
|
headers: {
|
'token': localStorage.getItem('token')
|
},
|
method: "get",
|
success: (res) => {
|
let data = res.data;
|
let mapData = JSON.parse(data)
|
mapData.forEach((row) => {
|
let shelfIdx = 1;
|
row.forEach((col) => {
|
if (col.type == 'shelf') {
|
col.shelfIdx = shelfIdx;
|
shelfIdx++;
|
}
|
|
col.rowPx = (col.rowSpan * rowPx) + "px";
|
col.colPx = (col.colSpan * colPx) + "px";
|
|
col.width = (col.cellWidth / 30) + "px";
|
})
|
})
|
that.map = mapData;
|
}
|
})
|
},
|
switchLev(lev) {
|
this.currentLev = lev;
|
this.getMap()
|
},
|
openCrn(id) {
|
this.crnParam.crnNo = id;
|
this.activateCard = 'crn';
|
},
|
openRgv(id) {
|
this.rgvParam.rgvNo = id;
|
this.activateCard = 'rgv';
|
},
|
openSite(id) {
|
this.devpParam.stationId = id;
|
this.activateCard = 'devp';
|
},
|
getSiteInfo() {
|
//获取输送站点数据
|
$.ajax({
|
url: baseUrl + "/console/latest/data/station",
|
headers: {'token': localStorage.getItem('token')},
|
method: 'POST',
|
success: function (res) {
|
if (res.code === 200) {
|
var sites = res.data;
|
for (var i = 0; i < sites.length; i++){
|
var siteEl = $("#site-"+sites[i].stationId);
|
siteEl.attr("class", "site " + sites[i].stationStatus);
|
if (sites[i].taskNo != null && sites[i].taskNo>0) {
|
siteEl.html(sites[i].stationId + "[" + sites[i].taskNo + "]");
|
} else {
|
siteEl.html(sites[i].stationId);
|
}
|
}
|
} else if (res.code === 403) {
|
parent.location.href = baseUrl + "/login";
|
} else {
|
console.log(res.msg);
|
}
|
}
|
});
|
},
|
getCrnInfo() {
|
let that = this
|
//获取堆垛机数据
|
$.ajax({
|
url: baseUrl + "/console/latest/data/crn",
|
headers: {'token': localStorage.getItem('token')},
|
method: 'POST',
|
success: function (res) {
|
if (res.code === 200) {
|
var crns = res.data;
|
|
let crnList = []
|
for (var i = 0; i < crns.length; i++) {
|
var crnEl = $("#crn-" + crns[i].crnId);
|
crnEl.attr("class", "crn-item " + crns[i].crnStatus);
|
|
let bay = parseInt(crns[i].bay, 10);
|
if (isNaN(bay) || bay < 1 || bay === -2) {
|
bay = 1;
|
}
|
|
// 根据列值定位到当前行的目标单元格,避免随机偏移导致的误差
|
let targetCell = that.getCrnTargetCell(crnEl, bay);
|
if (!targetCell || targetCell.length === 0) {
|
continue;
|
}
|
if (targetCell.offset() == undefined) {
|
continue;
|
}
|
if (crnEl.offsetParent().offset() == undefined) {
|
continue;
|
}
|
|
let parentLeft = crnEl.offsetParent().offset().left;
|
let cellLeft = targetCell.offset().left - parentLeft;
|
let offsetWithinCell = (targetCell.outerWidth() - crnEl.outerWidth()) / 2;
|
let zoomFactor = that.mapSettingParam.zoom ? (that.mapSettingParam.zoom / 100) : 1;
|
if (zoomFactor <= 0) { zoomFactor = 1; }
|
|
let finalOffset = (cellLeft + offsetWithinCell) / zoomFactor;
|
if(finalOffset < 0) {
|
finalOffset = 0;
|
}
|
|
crnEl.animate({left: finalOffset + 'px'}, 500);
|
|
crnList.push({
|
crnNo: crns[i].crnId,
|
crnStatus: crns[i].crnStatus
|
})
|
}
|
} else if (res.code === 403) {
|
parent.location.href = baseUrl + "/login";
|
} else {
|
console.log(res.msg);
|
}
|
}
|
});
|
},
|
getRgvInfo() {
|
let that = this
|
//获取RGV数据
|
$.ajax({
|
url: baseUrl + "/console/latest/data/rgv",
|
headers: {'token': localStorage.getItem('token')},
|
method: 'POST',
|
success: function (res) {
|
if (res.code === 200) {
|
var rgvs = res.data;
|
|
if (that.rgvPosition.length == 0) {
|
let position = []
|
for (var i = 0; i < rgvs.length; i++) {
|
var rgvEl = $("#rgv-" + rgvs[i].rgvNo);
|
if(rgvEl.offset() == undefined) {
|
continue;
|
}
|
position.push({
|
id: rgvs[i].rgvNo,
|
trackSiteNo: rgvs[i].trackSiteNo,
|
initLeft: rgvEl.offset().left
|
})
|
}
|
that.rgvPosition = position
|
return;
|
}
|
|
for (var i = 0; i < rgvs.length; i++) {
|
var rgvEl = $("#rgv-" + rgvs[i].rgvNo);
|
if (rgvs[i].rgvStatus == 'idle') {
|
rgvEl.attr("class", "rgv-item");
|
}else if (rgvs[i].rgvStatus == 'working') {
|
rgvEl.attr("class", "rgv-item machine-working");
|
}else if (rgvs[i].rgvStatus == 'waiting') {
|
rgvEl.attr("class", "rgv-item machine-working");
|
}else {
|
rgvEl.attr("class", "rgv-item machine-un-auto");
|
}
|
|
let trackSiteNo = rgvs[i].trackSiteNo;
|
let trackSiteEl = $("#rgvTrackSiteNo-" + trackSiteNo);
|
|
if(rgvEl.offsetParent().offset() == undefined) {
|
continue;
|
}
|
|
let parentLeft = rgvEl.offsetParent().offset().left;
|
let targetPosition = trackSiteEl.parent().parent().offset().left - parentLeft;
|
let rgvPosition = rgvEl.position().left;
|
let zoomFactor = that.mapSettingParam.zoom ? (that.mapSettingParam.zoom / 100) : 1;
|
if (zoomFactor <= 0) { zoomFactor = 1; }
|
let finalOffset = targetPosition / zoomFactor;
|
rgvEl.animate({left: finalOffset + "px"}, 500);
|
}
|
} else if (res.code === 403) {
|
parent.location.href = baseUrl + "/login";
|
} else {
|
console.log(res.msg);
|
}
|
}
|
});
|
},
|
systemSwitch() {
|
// 系统开关
|
let that = this
|
if (this.systemStatus) {
|
this.$prompt('请输入口令,并停止WCS系统', '提示', {
|
confirmButtonText: '确定',
|
cancelButtonText: '取消',
|
}).then(({
|
value
|
}) => {
|
that.doSwitch(0, value)
|
}).catch(() => {
|
|
});
|
} else {
|
this.doSwitch(1)
|
}
|
},
|
doSwitch(operatorType, password) {
|
let that = this
|
$.ajax({
|
url: baseUrl + "/console/system/switch",
|
headers: {
|
'token': localStorage.getItem('token')
|
},
|
data: {
|
operatorType: operatorType,
|
password: password
|
},
|
method: 'POST',
|
success: function(res) {
|
if (res.code === 200) {
|
if (res.data.status) {
|
$('#system-toggle-checked').attr("checked", true);
|
$('#system-run-desc').html("系统运行中...");
|
that.systemStatus = true;
|
parent.systemRunning = true;
|
} else {
|
$('#system-toggle-checked').attr("checked", false);
|
$('#system-run-desc').html("系统已停止!");
|
that.systemStatus = false;
|
parent.systemRunning = false;
|
}
|
} else if (res.code === 403) {
|
parent.location.href = baseUrl + "/login";
|
} else {
|
that.$message({
|
message: res.msg,
|
type: 'error'
|
});
|
}
|
}
|
});
|
},
|
getSystemRunningStatus() {
|
// 获取wcs系统运行状态
|
let that = this
|
$.ajax({
|
url: baseUrl + "/console/system/running/status",
|
headers: {
|
'token': localStorage.getItem('token')
|
},
|
method: 'POST',
|
success: function(res) {
|
if (res.code === 200) {
|
if (res.data.status) {
|
$('#system-toggle-checked').attr("checked", true);
|
$('#system-run-desc').html("系统运行中...");
|
that.systemStatus = true;
|
parent.systemRunning = true;
|
} else {
|
$('#system-toggle-checked').attr("checked", false);
|
$('#system-run-desc').html("系统已停止!");
|
that.systemStatus = false;
|
parent.systemRunning = false;
|
}
|
} else if (res.code === 403) {
|
parent.location.href = baseUrl + "/login";
|
} else {
|
that.$message({
|
message: res.msg,
|
type: 'error'
|
});
|
}
|
}
|
});
|
},
|
getCrnTargetCell(crnEl, bay) {
|
if (!crnEl || bay == null) {
|
return null;
|
}
|
let rowEl = crnEl.closest('tr');
|
if (!rowEl || rowEl.length === 0) {
|
return null;
|
}
|
let targetCell = null;
|
let colCounter = 0;
|
let startCount = false;
|
rowEl.find('td').each(function () {
|
// 以当前行中首次出现的track-item为起点进行列计数
|
const isTrackCrn = $(this).find('.track-crn').length > 0;
|
if (!startCount && !isTrackCrn) {
|
return;
|
}
|
let span = parseInt($(this).attr('colspan'), 10);
|
if (isNaN(span) || span < 1) {
|
span = 1;
|
}
|
if (!startCount && isTrackCrn) {
|
startCount = true;
|
}
|
colCounter += span;
|
if (targetCell == null && colCounter >= bay) {
|
targetCell = $(this);
|
return false;
|
}
|
});
|
return targetCell;
|
},
|
getDeviceNo(obj) {
|
if (this.isJson(obj)) {
|
let data = JSON.parse(obj)
|
if (data.deviceNo == null || data.deviceNo == undefined) {
|
return -1;
|
}
|
return data.deviceNo;
|
}else {
|
return -1;
|
}
|
},
|
getStationId(obj) {
|
if (this.isJson(obj)) {
|
let data = JSON.parse(obj)
|
if (data.stationId == null || data.stationId == undefined) {
|
return -1;
|
}
|
return data.stationId;
|
}else {
|
return -1;
|
}
|
},
|
getTrackSiteNo(obj) {
|
if (this.isJson(obj)) {
|
let data = JSON.parse(obj)
|
if (data.trackSiteNo == null || data.trackSiteNo == undefined) {
|
return -1;
|
}
|
return data.trackSiteNo;
|
}else {
|
return -1;
|
}
|
},
|
isJson(str) {
|
try {
|
JSON.parse(str);
|
return true;
|
} catch (e) {
|
return false;
|
}
|
},
|
handleCardClick(tab, event) {
|
|
}
|
}
|
})
|
</script>
|
</body>
|
</html>
|