<!DOCTYPE html>
|
<html lang="en">
|
|
<head>
|
<meta charset="UTF-8">
|
<title>库位地图</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/console_vue.css">
|
<link rel="stylesheet" href="../../static/css/toggle-switch.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>
|
<script src="../../static/js/gsap.min.js"></script>
|
<script src="../../static/js/pixi-legacy.min.js"></script>
|
<style>
|
* {
|
margin: 0;
|
padding: 0;
|
}
|
</style>
|
</head>
|
|
<body>
|
<div id="app">
|
<div id="pixiView">
|
|
</div>
|
|
<!--输出操作和FPS-->
|
<div style="position: absolute;top: 20px;right: 50px;">
|
<div>FPS:{{mapFps}}</div>
|
<el-button @click="drawer = true">操作</el-button>
|
</div>
|
|
<el-drawer title="操作区域" :visible.sync="drawer" :with-header="true" :modal="false">
|
<div class="floorBtnBox" v-for="(lev,idx) in floorList">
|
<el-button :style="{background:currentLev === lev ? '#7DCDFF':''}"
|
@click="changeFloor(lev)">{{lev}}F</el-button>
|
</div>
|
</el-drawer>
|
|
<el-drawer title="库位详情" :visible.sync="drawerLocNo" :with-header="true" :modal="false">
|
<div v-if="drawerLocNoData!=null">
|
<div style="margin: 10px;">
|
<div style="margin-top: 5px;">排:{{drawerLocNoData.row}}</div>
|
<div style="margin-top: 5px;">列:{{drawerLocNoData.bay}}</div>
|
<div style="margin-top: 5px;">层:{{drawerLocNoData.lev}}</div>
|
<div style="margin-top: 5px;">库位号:{{drawerLocNoData.locNo}}</div>
|
<div style="margin-top: 5px;">库位状态:{{drawerLocNoData.locSts}}</div>
|
</div>
|
</div>
|
</el-drawer>
|
|
<el-drawer title="小车信息" :visible.sync="drawerShuttle" :with-header="true" :modal="false">
|
<div v-if="drawerShuttleData!=null">
|
<div style="margin: 10px;">
|
<div style="margin-top: 5px;">小车:{{drawerShuttleData.shuttleNo}}</div>
|
<div style="margin-top: 5px;">工作号:{{drawerShuttleData.wrkNo}}</div>
|
<div style="margin-top: 5px;">状态:{{drawerShuttleData}}</div>
|
</div>
|
</div>
|
</el-drawer>
|
|
<el-drawer title="站点信息" :visible.sync="drawerSta" :with-header="true" :modal="false">
|
<div v-if="drawerStaData!=null">
|
<div style="margin: 10px;">
|
<div style="margin-top: 5px;">站点:{{drawerStaData.siteId}}</div>
|
<div style="margin-top: 5px;">工作号:{{drawerStaData.workNo}}</div>
|
<div style="margin-top: 5px;">工作状态:{{drawerStaData.wrkSts}}</div>
|
<div style="margin-top: 5px;">工作类型:{{drawerStaData.ioType}}</div>
|
<div style="margin-top: 5px;">源站:{{drawerStaData.sourceStaNo}}</div>
|
<div style="margin-top: 5px;">目标站:{{drawerStaData.staNo}}</div>
|
<div style="margin-top: 5px;">源库位:{{drawerStaData.sourceLocNo}}</div>
|
<div style="margin-top: 5px;">目标库位:{{drawerStaData.locNo}}</div>
|
<div style="margin-top: 5px;">自动:{{drawerStaData.autoing}}</div>
|
<div style="margin-top: 5px;">有物:{{drawerStaData.loading}}</div>
|
<div style="margin-top: 5px;">能入:{{drawerStaData.canining}}</div>
|
<div style="margin-top: 5px;">能出:{{drawerStaData.canouting}}</div>
|
<div style="margin-top: 5px;">能出:{{drawerStaData.canouting}}</div>
|
</div>
|
</div>
|
</el-drawer>
|
|
<el-drawer title="提升机信息" :visible.sync="drawerLift" :with-header="true" :modal="false">
|
<div v-if="drawerLiftData!=null">
|
<div style="margin: 10px;">
|
<div style="margin-top: 5px;">提升机:{{liftList[drawerLiftData-1].liftNo}}</div>
|
<div style="margin-top: 5px;">工作号:{{liftList[drawerLiftData-1].taskNo}}</div>
|
<div style="margin-top: 5px;">状态:{{liftList[drawerLiftData-1]}}</div>
|
</div>
|
</div>
|
</el-drawer>
|
|
</div>
|
<script>
|
let width = 25;
|
let height = 25;
|
let pixiApp;
|
let pixiStageList = [];
|
let pixiShuttleMap = new Map();
|
let pixiShuttleMoveAdvancePathMap = new Map();
|
let pixiShuttleMoveAdvancePathList = [];
|
let pixiStaMap = new Map();
|
let pixiCrnMap = new Map();
|
let objectsContainer;
|
let objectsContainer2;
|
let graphicsShelf;
|
let graphicsDevp;
|
let graphicsCrn;
|
let graphicsCrnTrack;
|
let ws;
|
|
var app = new Vue({
|
el: '#app',
|
data: {
|
map: [],
|
currentLev: 1,
|
floorList: [], //当前项目楼层
|
currentLevShuttleList: [],//当前楼层四向穿梭车集合
|
shuttleColorList: [],//四向穿梭车颜色集合
|
drawer: false,
|
drawerLocNo: false,
|
drawerLocNoData: null,
|
drawerLocDetls: [],
|
reloadMap: true,
|
mapFps: 0,
|
drawerShuttle: false,
|
drawerShuttleData: null,
|
currentLevStaList: [],//当前楼层站点list
|
reloadSta: true,
|
drawerSta: false,
|
drawerStaData: null,
|
drawerLift: false,
|
drawerLiftData: null,
|
liftList: [],
|
},
|
mounted() {
|
this.init()
|
this.createMap()
|
},
|
watch: {
|
map: {
|
deep: true,
|
handler(val) {
|
|
}
|
},
|
drawerLocNo: {
|
deep: true,
|
handler(val) {
|
if (!val) {
|
var sprite = pixiStageList[this.drawerLocNoData.x][this.drawerLocNoData.y];
|
updateColor(sprite, 0xFFFFFF);//恢复颜色
|
}
|
}
|
}
|
},
|
methods: {
|
init() {
|
let that = this
|
ws = new WebSocket("ws://" + window.location.host + baseUrl + "/console/websocket");
|
ws.onopen = this.webSocketOnOpen
|
ws.onerror = this.webSocketOnError
|
ws.onmessage = this.webSocketOnMessage
|
ws.onclose = this.webSocketClose
|
|
|
this.initLev()//初始化楼层信息
|
setTimeout(() => {
|
that.getMap(this.currentLev)
|
}, 1000);
|
|
// this.consoleInterval = setInterval(() => {
|
// this.getMap(this.currentLev) //获取实时地图数据
|
// this.getShuttleStateInfo() //获取四向穿梭车信息
|
// this.getLiftStateInfo() //获取提升机信息
|
// this.getSiteInfo() //获取输送站点数据
|
// // this.getCodeData()//获取条码
|
// }, 1000)
|
|
},
|
initLev() {
|
let that = this
|
$.ajax({
|
url: baseUrl + "/console/map/lev/list",
|
headers: {
|
'token': localStorage.getItem('token')
|
},
|
data: {},
|
method: 'get',
|
success: function (res) {
|
if (res.code === 200) {
|
that.floorList = res.data;
|
} else if (res.code === 403) {
|
parent.location.href = baseUrl + "/login";
|
} else {
|
that.$message({
|
message: res.msg,
|
type: 'error'
|
});
|
}
|
}
|
});
|
},
|
//获取地图数据
|
getMap(lev) {
|
let that = this;
|
$.ajax({
|
url: baseUrl + "/basMap/lev/" + this.currentLev + "/auth",
|
headers: {
|
'token': localStorage.getItem('token')
|
},
|
data: {},
|
method: 'get',
|
success: function (res) {
|
//获取地图数据
|
let data = res.data
|
let mapData = JSON.parse(data)
|
that.createMapData(mapData)
|
}
|
})
|
},
|
changeFloor(lev) {
|
this.currentLev = lev
|
this.currentLevShuttleList = []
|
this.reloadMap = true
|
this.reloadSta = true
|
this.getMap(lev)
|
|
//清空预计路径
|
objectsContainer2.removeChildren();
|
pixiShuttleMoveAdvancePathMap = new Map();
|
pixiShuttleMoveAdvancePathList = []
|
},
|
createMap() {
|
//Create a Pixi Application
|
pixiApp = new PIXI.Application({
|
// width: 1500,
|
// height: 800,
|
backgroundColor: 0xF5F7F9FF,
|
resizeTo: window
|
});
|
//Add the canvas that Pixi automatically created for you to the HTML document
|
$("#pixiView").append(pixiApp.view)
|
|
//加载小车资源
|
pixiApp.loader.add('shuttle', '../static/images/sxcar.png');
|
|
// 从Graphics对象创建一个纹理
|
graphicsShelf = pixiApp.renderer.generateTexture(getContainer('shelf'));
|
graphicsDevp = pixiApp.renderer.generateTexture(getContainer('devp'));
|
graphicsCrn = createCrnTexture();
|
graphicsCrnTrack = createTrackTexture();
|
|
// 创建一个容器来管理大批量的显示对象
|
objectsContainer = new PIXI.Container();
|
pixiApp.stage.addChild(objectsContainer);
|
|
// 创建一个容器来管理大批量的显示对象
|
objectsContainer2 = new PIXI.Container();
|
pixiApp.stage.addChild(objectsContainer2);
|
|
//*******************拖动画布*******************
|
let stageOriginalPos;
|
let mouseDownPoint;
|
let touchBlank = false;
|
pixiApp.renderer.plugins.interaction.on(
|
'pointerdown',
|
(event) => {
|
const globalPos = event.data.global;
|
// 记录下stage原来的位置
|
stageOriginalPos = [pixiApp.stage.position._x, pixiApp.stage.position._y];
|
// 记录下mouse down的位置
|
mouseDownPoint = [globalPos.x, globalPos.y];
|
if (!event.target) {
|
// 点到了画布的空白位置
|
touchBlank = true;
|
}
|
}
|
);
|
|
pixiApp.renderer.plugins.interaction.on(
|
'pointermove',
|
(event) => {
|
const globalPos = event.data.global;
|
|
if (touchBlank) {
|
// 拖拽画布
|
const dx = globalPos.x - mouseDownPoint[0];
|
const dy = globalPos.y - mouseDownPoint[1];
|
pixiApp.stage.position.set(
|
stageOriginalPos[0] + dx,
|
stageOriginalPos[1] + dy
|
);
|
}
|
}
|
);
|
|
pixiApp.renderer.plugins.interaction.on(
|
'pointerup',
|
(event) => {
|
touchBlank = false;
|
}
|
);
|
//*******************拖动画布*******************
|
|
//*******************缩放画布*******************
|
pixiApp.view.addEventListener('wheel', (event) => {
|
event.stopPropagation();
|
event.preventDefault();
|
// 因为画布是充满视窗的,所以clientX等于mouse point在renderer上的x坐标
|
const globalPos = [event.clientX, event.clientY];
|
const delta = event.deltaY;
|
const oldZoom = pixiApp.stage.scale.x;
|
let newZoom = oldZoom * 0.999 ** delta;
|
|
// const oldStageMatrix = app.stage.localTransform.clone();
|
// const oldStagePos = oldStageMatrix.applyInverse(pointerGlobalPos);
|
const oldStagePos = globalPos;
|
const dx = oldStagePos[0] * oldZoom - oldStagePos[0] * newZoom;
|
const dy = oldStagePos[1] * oldZoom - oldStagePos[1] * newZoom;
|
|
pixiApp.stage.setTransform(
|
pixiApp.stage.position.x + dx,
|
pixiApp.stage.position.y + dy,
|
newZoom,
|
newZoom,
|
0,
|
0,
|
0,
|
0,
|
0
|
);
|
|
});
|
//*******************缩放画布*******************
|
|
//*******************FPS*******************
|
var g_Time = 0;
|
pixiApp.ticker.add((delta) => {
|
var timeNow = (new Date()).getTime();
|
var timeDiff = timeNow - g_Time;
|
g_Time = timeNow;
|
var fps = 1000 / timeDiff;
|
this.mapFps = parseInt(fps)
|
});
|
//*******************FPS*******************
|
|
},
|
createMapData(map) {
|
if (this.reloadMap) {
|
this.reloadMap = false
|
pixiStageList = [map.length]//初始化列表
|
pixiStaMap = new Map();//重置
|
objectsContainer.removeChildren()
|
map.forEach((item, index) => {
|
pixiStageList[index] = [item.length]
|
for (let idx = 0; idx < item.length; idx++) {
|
let val = item[idx]
|
|
// 跳过合并单元格的占位符
|
if (val.type === 'merge') {
|
continue;
|
}
|
|
if (val.type == undefined || val.type === 'none') {
|
continue;
|
}
|
|
// 计算合并单元格的实际宽高
|
let cellWidth = val.colSpan ? val.colSpan * width : width;
|
let cellHeight = val.rowSpan ? val.rowSpan * height : height;
|
|
let sprite = getSpriteWithSize(val.value, idx * width, index * height, cellWidth, cellHeight, val, (e) => {
|
// if (val.value == 4) {
|
// //站点
|
// this.openDrawerSta(val)
|
// } else if (val.value == 67) {
|
// //提升机
|
// this.openDrawerLift(val)
|
// } else {
|
// //库位
|
// this.rightEvent(index, idx, e);
|
// updateColor(sprite, 0x9900ff);
|
// }
|
});
|
|
if (sprite == null) {
|
continue;
|
}
|
|
// if (val.value == 4) {
|
// // 创建文本对象
|
// const style = new PIXI.TextStyle({
|
// fontFamily: 'Arial',
|
// fontSize: 10,
|
// fill: '#000000',
|
// });
|
// const text = new PIXI.Text(val.data, style);
|
// text.anchor.set(0.5); // 设置文本锚点为中心点
|
// text.position.set(sprite.width / 2, sprite.height / 2); // 将文本位置设置为Graphics对象的中心点
|
// // 将文本对象添加到Graphics对象中
|
// sprite.addChild(text);
|
// sprite.textObj = text;
|
// pixiStaMap.set(parseInt(val.data), sprite);//站点数据添加到map中
|
// }else if (val.value == 67) {
|
// // 创建提升机文本对象
|
// const style = new PIXI.TextStyle({
|
// fontFamily: 'Arial',
|
// fontSize: 10,
|
// fill: '#000000',
|
// });
|
// const text = new PIXI.Text(val.data, style);
|
// text.anchor.set(0.5); // 设置文本锚点为中心点
|
// text.position.set(sprite.width / 2, sprite.height / 2); // 将文本位置设置为Graphics对象的中心点
|
// // 将文本对象添加到Graphics对象中
|
// sprite.addChild(text);
|
// sprite.textObj = text;
|
// pixiStaMap.set(parseInt(val.data), sprite);//站点数据添加到map中
|
// }
|
|
objectsContainer.addChild(sprite);
|
pixiStageList[index][idx] = sprite
|
}
|
});
|
|
//视角居中
|
let containerWidth = (pixiApp.view.width - objectsContainer.width) / 2;
|
let containerHeight = (pixiApp.view.height - objectsContainer.height) / 2;
|
pixiApp.stage.position.set(containerWidth, containerHeight);
|
} else {
|
let diff = this.findDiffList(this.map, map);
|
diff.forEach((item, index) => {
|
//获取old元素
|
let oldSprite = pixiStageList[item.x][item.y]
|
if (!oldSprite) return; // 跳过不存在的元素
|
|
//移除old元素
|
objectsContainer.removeChild(oldSprite);
|
|
// 计算合并单元格的实际宽高
|
let cellWidth = item.colSpan ? item.colSpan * width : width;
|
let cellHeight = item.rowSpan ? item.rowSpan * height : height;
|
|
let sprite = getSpriteWithSize(item.data, item.y * width, item.x * height, cellWidth, cellHeight, item, (e) => {
|
this.rightEvent(item.x, item.y, e);
|
updateColor(sprite, 0x9900ff);
|
});
|
|
//添加元素
|
objectsContainer.addChild(sprite);
|
|
//保存新元素
|
pixiStageList[item.x][item.y] = sprite
|
});
|
}
|
|
this.map = map;
|
},
|
rightEvent(x, y, e) {
|
this.drawerLocNo = true
|
this.drawerLocNoData = {
|
x: x, y: y, z: this.currentLev, locNo: this.map[x][y].locNo,
|
locSts: this.map[x][y].locSts, row: this.map[x][y].row, bay: this.map[x][y].bay, lev: this.currentLev
|
};
|
},
|
findDiffList(arr1, arr2) {
|
let diff = []
|
arr1.forEach((item, index) => {
|
item.forEach((val, idx) => {
|
if (val.value != arr2[index][idx].value) {
|
diff.push({
|
x: index,
|
y: idx,
|
data: arr2[index][idx].value,
|
originData: val.value,
|
locSts: val.locSts
|
})
|
}
|
})
|
})
|
|
return diff;
|
},
|
findShuttleDiffList(list1, list2) {
|
//检测集合1里面的小车是否在集合2中有变动
|
if (list1.length == 0) {
|
return false;//集合为空
|
}
|
if (list1.length != list2.length) {
|
return false;//两个集合长度不一致
|
}
|
|
let flag = false;
|
list1.forEach((item, index) => {
|
for (var i = 0; i < list2.length; i++) {
|
if (item.shuttleNo == list2[i].shuttleNo) {
|
flag = true;
|
break;
|
}
|
}
|
});
|
|
return flag;
|
},
|
findShuttlePathDiffList(list1, list2) {
|
//检测集合1里面的小车预计路径是否在集合2中有变动
|
if (list1.length == 0) {
|
return false;//集合为空
|
}
|
if (list1.length != list2.length) {
|
return false;//两个集合长度不一致
|
}
|
|
for (var index = 0; index < list1.length; index++) {
|
let item = list1[index];
|
for (var i = 0; i < list2.length; i++) {
|
if (item.shuttleNo != list2[i].shuttleNo) {
|
continue;//找不到小车号
|
}
|
|
if (item.moveAdvancePath == null) {
|
item.moveAdvancePath = [];
|
}
|
|
if (list2[i].moveAdvancePath == null) {
|
list2[i].moveAdvancePath = [];
|
}
|
|
if (!(item.moveAdvancePath.length == list2[i].moveAdvancePath.length)) {
|
return false;//小车预计路径长度不一致
|
}
|
}
|
}
|
return true;
|
},
|
checkStaInListDiff(sta, list) {
|
//检测站点是否在集合中有变动
|
if (list.length == 0) {
|
return false;//集合为空
|
}
|
|
let tmp = null;
|
for (var i = 0; i < list.length; i++) {
|
if (sta.siteId == list[i].siteId) {
|
tmp = list[i];//找到相同站点
|
break
|
}
|
}
|
|
if (tmp == null) {
|
return false;//没有找到相同站点
|
}
|
|
if (sta.siteStatus != tmp.siteStatus) {
|
return false;//站点状态不相同
|
}
|
|
if (sta.workNo != tmp.workNo) {
|
return false;//站点工作号不相同
|
}
|
|
return true;//无变化
|
},
|
webSocketOnOpen(e) {
|
console.log("open");
|
},
|
webSocketOnError(e) {
|
console.log(e);
|
},
|
webSocketOnMessage(e) {
|
const result = JSON.parse(e.data);
|
if (result.url == "/shuttle/table/shuttle/state") {
|
this.setShuttleStateInfo(JSON.parse(result.data))
|
} else if (result.url == "/lift/table/lift/state") {
|
this.setLiftStateInfo(JSON.parse(result.data))
|
} else if (result.url == "/console/latest/data/site") {
|
this.setSiteInfo(JSON.parse(result.data))
|
} else if (result.url == "/console/map/auth") {
|
this.setMap(JSON.parse(result.data))
|
} else if (result.url == "/console/locMap/auth") {
|
this.setMap(JSON.parse(result.data))
|
} else if (result.url == "/console/barcode/output/site") {
|
this.setCodeData(JSON.parse(result.data))
|
}
|
},
|
webSocketClose(e) {
|
console.log("close");
|
},
|
sendWs(message) {
|
if (ws.readyState == WebSocket.OPEN) {
|
ws.send(message)
|
}
|
},
|
colorRGB() {
|
//随机颜色
|
const r = Math.floor(Math.random() * 256);
|
const g = Math.floor(Math.random() * 256);
|
const b = Math.floor(Math.random() * 256);
|
return `rgb(${r},${g},${b})`;
|
},
|
updateShuttleXY(item) {
|
const shuttle = pixiShuttleMap.get(item.shuttleNo);
|
if (shuttle.updateMoveStatus) {//动画执行完成才可继续执行动画
|
shuttle.updateMoveStatus = false;//动画执行中
|
// 计算两点之间的距离1
|
const distance = Math.sqrt(Math.pow((item.wcsPoint.x * width) - shuttle.x, 2) + Math.pow((item.wcsPoint.y * height) - shuttle.y, 2));
|
gsap.killTweensOf(shuttle); // 杀死所有针对".class"的动画
|
gsap.to(shuttle, {
|
x: (item.wcsPoint.y - 0) * width, // 目标位置
|
y: (item.wcsPoint.x - 1) * height, // 目标位置
|
duration: 0.2, // 动画持续时间(秒)
|
ease: "power1.inOut", // 缓动类型
|
onComplete: () => {
|
shuttle.updateMoveStatus = true;//动画执行完成
|
}
|
});
|
}
|
},
|
getSiteInfo() {
|
//获取输送站点数据
|
this.sendWs(JSON.stringify({
|
"url": "/console/latest/data/site",
|
"data": {}
|
}))
|
},
|
setSiteInfo(res) {
|
// var test = "{\"msg\":\"操作成功\",\"code\":200,\"data\":[{\"siteId\":\"300\",\"siteStatus\":\"site-auto\",\"workNo\":0},{\"siteId\":\"301\",\"siteStatus\":\"site-auto\",\"workNo\":0},{\"siteId\":\"302\",\"siteStatus\":\"site-auto\",\"workNo\":0},{\"siteId\":\"303\",\"siteStatus\":\"site-auto\",\"workNo\":0},{\"siteId\":\"304\",\"siteStatus\":\"site-auto\",\"workNo\":0},{\"siteId\":\"305\",\"siteStatus\":\"site-auto\",\"workNo\":0},{\"siteId\":\"306\",\"siteStatus\":\"site-auto\",\"workNo\":0},{\"siteId\":\"307\",\"siteStatus\":\"site-auto\",\"workNo\":0},{\"siteId\":\"308\",\"siteStatus\":\"site-auto\",\"workNo\":0},{\"siteId\":\"309\",\"siteStatus\":\"site-auto\",\"workNo\":0},{\"siteId\":\"310\",\"siteStatus\":\"site-auto\",\"workNo\":0},{\"siteId\":\"311\",\"siteStatus\":\"site-auto\",\"workNo\":0},{\"siteId\":\"312\",\"siteStatus\":\"site-auto\",\"workNo\":0},{\"siteId\":\"313\",\"siteStatus\":\"site-auto\",\"workNo\":0},{\"siteId\":\"314\",\"siteStatus\":\"site-auto\",\"workNo\":0},{\"siteId\":\"315\",\"siteStatus\":\"site-auto\",\"workNo\":0},{\"siteId\":\"316\",\"siteStatus\":\"site-auto-run\",\"workNo\":0},{\"siteId\":\"317\",\"siteStatus\":\"site-auto\",\"workNo\":0},{\"siteId\":\"318\",\"siteStatus\":\"site-auto\",\"workNo\":0},{\"siteId\":\"319\",\"siteStatus\":\"site-auto\",\"workNo\":0},{\"siteId\":\"320\",\"siteStatus\":\"site-auto\",\"workNo\":0},{\"siteId\":\"321\",\"siteStatus\":\"site-auto\",\"workNo\":0},{\"siteId\":\"322\",\"siteStatus\":\"site-auto-run\",\"workNo\":0},{\"siteId\":\"323\",\"siteStatus\":\"site-auto\",\"workNo\":0},{\"siteId\":\"324\",\"siteStatus\":\"site-auto-run\",\"workNo\":0},{\"siteId\":\"325\",\"siteStatus\":\"site-auto\",\"workNo\":0},{\"siteId\":\"326\",\"siteStatus\":\"site-auto-id\",\"workNo\":5451},{\"siteId\":\"327\",\"siteStatus\":\"site-auto\",\"workNo\":0},{\"siteId\":\"200\",\"siteStatus\":\"site-auto\",\"workNo\":0},{\"siteId\":\"328\",\"siteStatus\":\"site-auto\",\"workNo\":0},{\"siteId\":\"201\",\"siteStatus\":\"site-auto\",\"workNo\":0},{\"siteId\":\"329\",\"siteStatus\":\"site-auto\",\"workNo\":0},{\"siteId\":\"202\",\"siteStatus\":\"site-auto\",\"workNo\":0},{\"siteId\":\"330\",\"siteStatus\":\"site-auto\",\"workNo\":0},{\"siteId\":\"203\",\"siteStatus\":\"site-auto\",\"workNo\":0},{\"siteId\":\"331\",\"siteStatus\":\"site-auto\",\"workNo\":0},{\"siteId\":\"204\",\"siteStatus\":\"site-auto\",\"workNo\":0},{\"siteId\":\"332\",\"siteStatus\":\"site-auto\",\"workNo\":0},{\"siteId\":\"205\",\"siteStatus\":\"site-auto\",\"workNo\":0},{\"siteId\":\"333\",\"siteStatus\":\"site-auto\",\"workNo\":0},{\"siteId\":\"334\",\"siteStatus\":\"site-auto\",\"workNo\":0},{\"siteId\":\"335\",\"siteStatus\":\"site-auto\",\"workNo\":0},{\"siteId\":\"336\",\"siteStatus\":\"site-auto\",\"workNo\":0},{\"siteId\":\"337\",\"siteStatus\":\"site-auto\",\"workNo\":0},{\"siteId\":\"338\",\"siteStatus\":\"site-auto-run\",\"workNo\":0},{\"siteId\":\"339\",\"siteStatus\":\"site-auto-run-id\",\"workNo\":5447},{\"siteId\":\"340\",\"siteStatus\":\"site-auto\",\"workNo\":0},{\"siteId\":\"341\",\"siteStatus\":\"site-auto\",\"workNo\":0},{\"siteId\":\"342\",\"siteStatus\":\"site-auto\",\"workNo\":0},{\"siteId\":\"343\",\"siteStatus\":\"site-auto-run\",\"workNo\":0},{\"siteId\":\"344\",\"siteStatus\":\"site-auto\",\"workNo\":0},{\"siteId\":\"345\",\"siteStatus\":\"site-auto\",\"workNo\":0},{\"siteId\":\"346\",\"siteStatus\":\"site-auto\",\"workNo\":0},{\"siteId\":\"100\",\"siteStatus\":\"site-auto-run-id\",\"workNo\":8851},{\"siteId\":\"101\",\"siteStatus\":\"site-auto-run-id\",\"workNo\":8855},{\"siteId\":\"102\",\"siteStatus\":\"site-auto\",\"workNo\":0},{\"siteId\":\"103\",\"siteStatus\":\"site-auto\",\"workNo\":0},{\"siteId\":\"104\",\"siteStatus\":\"site-auto-run\",\"workNo\":0},{\"siteId\":\"105\",\"siteStatus\":\"site-auto\",\"workNo\":0}]}";
|
// res = JSON.parse(test)
|
//获取输送站点数据
|
if (res.code === 200) {
|
var sites = res.data;
|
if (this.reloadSta && pixiStaMap.size > 0) {
|
//重新渲染所有输送站点
|
this.currentLevStaList = sites;
|
this.reloadSta = false;
|
sites.forEach((item, index) => {
|
let sta = pixiStaMap.get(parseInt(item.siteId));
|
if (sta != undefined) {
|
if (item.workNo > 0) {
|
sta.textObj.text = item.siteId + "(" + item.workNo + ")";
|
}
|
|
//创建遮罩层
|
if (item.siteStatus == "site-auto") {
|
//自动状态,移除遮罩层
|
if (sta.statusObj != null) {
|
objectsContainer.removeChild(sta.statusObj)
|
sta.statusObj = null;
|
}
|
} else if (item.siteStatus == "site-auto-run" || item.siteStatus == "site-auto-run-id") {
|
//自动有物
|
let graphics = getGraphics(0xfa51f6, width, height, sta.x, sta.y);
|
graphics.addChild(sta.textObj);//继承文字信息
|
sta.statusObj = graphics;
|
objectsContainer.addChild(graphics);
|
} else if (item.siteStatus == "site-unauto") {
|
//非自动
|
let graphics = getGraphics(0xb8b8b8, width, height, sta.x, sta.y);
|
graphics.addChild(sta.textObj);//继承文字信息
|
sta.statusObj = graphics;
|
objectsContainer.addChild(graphics);
|
}
|
}
|
});
|
} else {
|
//检测不相同站点进行局部更新
|
this.currentLevStaList.forEach((item, index) => {
|
let result = this.checkStaInListDiff(item, sites);
|
if (!result) {
|
//需要更新
|
let sta = pixiStaMap.get(parseInt(item.siteId));
|
if (item.workNo > 0) {
|
sta.textObj.text = item.siteId + "(" + item.workNo + ")";
|
} else {
|
sta.textObj.text = item.siteId;
|
}
|
|
//创建遮罩层
|
if (item.siteStatus == "site-auto") {
|
//自动状态,移除遮罩层
|
if (sta.statusObj != null) {
|
objectsContainer.removeChild(sta.statusObj)
|
sta.statusObj = null;
|
}
|
} else if (item.siteStatus == "site-auto-run") {
|
//自动有物
|
let graphics = getGraphics(0xfa51f6, width, height, sta.x, sta.y);
|
graphics.addChild(sta.textObj);//继承文字信息
|
sta.statusObj = graphics;
|
objectsContainer.addChild(graphics);
|
} else if (item.siteStatus == "site-unauto") {
|
//非自动
|
let graphics = getGraphics(0xb8b8b8, width, height, sta.x, sta.y);
|
graphics.addChild(sta.textObj);//继承文字信息
|
sta.statusObj = graphics;
|
objectsContainer.addChild(graphics);
|
}
|
}
|
});
|
}
|
} else if (res.code === 403) {
|
parent.location.href = baseUrl + "/login";
|
} else {
|
console.log(res.msg);
|
}
|
},
|
openDrawerSta(data) {
|
let that = this
|
this.drawerSta = true;
|
$.ajax({
|
url: baseUrl + "/console/site/detail",
|
headers: {
|
'token': localStorage.getItem('token')
|
},
|
data: {
|
siteId: data.data
|
},
|
method: 'post',
|
success: function (res) {
|
//解析数据
|
let siteInfo = res.data;
|
if (res.code == 200) {
|
that.drawerStaData = siteInfo;
|
}
|
}
|
})
|
},
|
openDrawerLift(data) {
|
this.drawerLift = true;
|
this.drawerLiftData = parseInt(data.data)
|
},
|
getLiftStateInfo() {
|
// 提升机信息表获取
|
this.sendWs(JSON.stringify({
|
"url": "/lift/table/lift/state",
|
"data": {}
|
}))
|
},
|
setLiftStateInfo(res) {
|
// 提升机信息表获取
|
if (res.code == 200) {
|
this.liftList = res.data
|
}
|
},
|
addMoveAdvancePath(moveAdvancePath, shuttleNo) {//添加预计路径
|
let that = this;
|
moveAdvancePath.forEach((path, idx) => {
|
let locNo = this.map[path.x, path.y];
|
if (!pixiShuttleMoveAdvancePathMap.has(locNo)) {
|
let graphics = getGraphics(0x9966ff, width, height, path.y * width, (path.x - 1) * height);
|
let shuttleNos = [shuttleNo];
|
// 创建文本对象
|
const style = new PIXI.TextStyle({
|
fontFamily: 'Arial',
|
fontSize: 10,
|
fill: '#000000',
|
});
|
const text = new PIXI.Text(JSON.stringify(shuttleNos), style);
|
text.anchor.set(0.5); // 设置文本锚点为中心点
|
text.position.set(graphics.width / 2, graphics.height / 2); // 将文本位置设置为Graphics对象的中心点
|
// 将文本对象添加到Graphics对象中
|
graphics.addChild(text);
|
graphics.textObj = text;
|
objectsContainer2.addChild(graphics)
|
pixiShuttleMoveAdvancePathMap.set(locNo, {
|
path: path,
|
sprite: graphics,
|
textObj: text,
|
shuttleNos: shuttleNos
|
})
|
|
if (pixiShuttleMoveAdvancePathList[shuttleNo] == null) {
|
let locNos = new Set()
|
locNos.add(locNo);
|
pixiShuttleMoveAdvancePathList[shuttleNo] = locNos;
|
} else {
|
pixiShuttleMoveAdvancePathList[shuttleNo].add(locNo);
|
}
|
} else {
|
let pathMap = pixiShuttleMoveAdvancePathMap.get(locNo)
|
let shuttleNos = pathMap.shuttleNos;
|
shuttleNos.push(shuttleNo);
|
pathMap.textObj.text = JSON.stringify(shuttleNos);
|
pixiShuttleMoveAdvancePathMap.set(locNo, pathMap);
|
if (pixiShuttleMoveAdvancePathList[shuttleNo] == null) {
|
let locNos = new Set()
|
locNos.add(locNo);
|
pixiShuttleMoveAdvancePathList[shuttleNo] = locNos;
|
} else {
|
pixiShuttleMoveAdvancePathList[shuttleNo].add(locNo);
|
}
|
}
|
});
|
},
|
removeMoveAdvancePath(shuttleNo) {//删除预计路径
|
let locNos = pixiShuttleMoveAdvancePathList[shuttleNo];
|
if (locNos != null) {
|
locNos.forEach((locNo, index) => {
|
let pathMap = pixiShuttleMoveAdvancePathMap.get(locNo);
|
if (pathMap != null) {
|
let shuttleNos = pathMap.shuttleNos;
|
let shuttleNosNew = [];
|
shuttleNos.forEach((shuttle, idx) => {
|
if (shuttle != shuttleNo) {
|
shuttleNosNew.push(shuttle);
|
}
|
});
|
|
if (shuttleNosNew.length === 0) {
|
//预计路径没有小车,直接删除路径
|
objectsContainer2.removeChild(pathMap.sprite);
|
pixiShuttleMoveAdvancePathMap.delete(locNo)
|
} else {
|
//预计路径存在其他小车,更新文字信息
|
pathMap.textObj.text = JSON.stringify(shuttleNosNew);
|
pathMap.shuttleNos = shuttleNosNew;
|
pixiShuttleMoveAdvancePathMap.set(locNo, pathMap);
|
}
|
}
|
})
|
}
|
},
|
}
|
})
|
|
function getContainer(type) {
|
let graphics = new PIXI.Graphics();
|
let drawBorder = true;
|
if (type == 'shelf') {
|
graphics.beginFill(0x55aaff);
|
} else if (type == 'devp') {
|
graphics.beginFill(0xffff00);
|
graphics.visible = true;
|
} else if (type == 'crn') {
|
graphics.beginFill(0xaaffff);
|
}
|
if (drawBorder) {
|
graphics.lineStyle(1, 0xffffff, 1);
|
graphics.drawRect(0, 0, width, height);
|
}
|
graphics.endFill();
|
|
return graphics;
|
}
|
|
function createTrackTexture() {
|
const g = new PIXI.Graphics();
|
const t = Math.max(2, Math.round(height * 0.08));
|
const gap = Math.round(height * 0.30);
|
const mid = Math.round(height / 2);
|
const y1 = mid - Math.round(gap / 2);
|
const y2 = mid + Math.round(gap / 2);
|
const tHalf = Math.round(t / 2);
|
const topRailTopY = y1 - tHalf;
|
const bottomRailTopY = y2 - tHalf;
|
g.beginFill(0x666666);
|
g.drawRect(0, topRailTopY, width, t);
|
g.drawRect(0, bottomRailTopY, width, t);
|
g.endFill();
|
g.beginFill(0x777777);
|
const sTop = topRailTopY + t;
|
const sBottom = bottomRailTopY;
|
const sHeight = Math.max(1, sBottom - sTop);
|
for (let i = 0; i < width; i += 5) {
|
g.drawRect(i, sTop, 2, sHeight);
|
}
|
g.endFill();
|
const rt = PIXI.RenderTexture.create({ width: width, height: height });
|
pixiApp.renderer.render(g, rt);
|
return rt;
|
}
|
|
function createCrnTexture() {
|
const g = new PIXI.Graphics();
|
const yTop = Math.round(height * 0.1);
|
g.beginFill(0x999999);
|
g.drawRect(2, yTop, 3, height - yTop - 2);
|
g.drawRect(width - 5, yTop, 3, height - yTop - 2);
|
g.endFill();
|
g.beginFill(0x999999);
|
g.drawRect(0, yTop, width, 3);
|
g.endFill();
|
const cabW = Math.round(width * 0.42);
|
const cabH = Math.round(height * 0.38);
|
const cabX = Math.round((width - cabW) / 2);
|
const cabY = Math.round(height * 0.52 - cabH / 2);
|
g.beginFill(0x3a78c2);
|
g.drawRect(cabX, cabY, cabW, cabH);
|
g.endFill();
|
const winW = Math.round(cabW * 0.6);
|
const winH = Math.round(cabH * 0.45);
|
const winX = cabX + Math.round((cabW - winW) / 2);
|
const winY = cabY + Math.round((cabH - winH) / 2);
|
g.beginFill(0xd0e8ff);
|
g.drawRect(winX, winY, winW, winH);
|
g.endFill();
|
const forkW = Math.round(width * 0.5);
|
const forkH = Math.max(2, Math.round(height * 0.08));
|
const forkX = Math.round((width - forkW) / 2);
|
const forkY = cabY + cabH;
|
g.beginFill(0x666666);
|
g.drawRect(forkX, forkY, forkW, forkH);
|
g.endFill();
|
const rt = PIXI.RenderTexture.create({ width: width, height: height });
|
pixiApp.renderer.render(g, rt);
|
return rt;
|
}
|
|
function getContainerWithSize(value, w, h) {
|
let graphics = new PIXI.Graphics();
|
if (value === 0) {
|
graphics.beginFill(0x55aaff);
|
} else if (value === 3) {//母轨道
|
graphics.beginFill(0x00ff7f);
|
graphics.visible = true;
|
} else if (value === 4) {//站点
|
graphics.beginFill(0xffff00);
|
graphics.visible = true;
|
} else if (value === 5) {//充电桩
|
graphics.beginFill(0xffaa7f);
|
graphics.visible = true;
|
} else if (value === 9) {//轨迹
|
graphics.beginFill(0xff0000);
|
} else if (value === 67) {//提升机
|
graphics.beginFill(0xaaffff);
|
} else if (value === -999) {//路径锁定
|
graphics.beginFill(0xf83333);
|
} else if (value === 1000) {//满库位
|
graphics.beginFill(0xf83333);
|
}
|
graphics.lineStyle(1, 0xffffff, 1);
|
graphics.drawRect(0, 0, w, h);
|
graphics.endFill();
|
|
return graphics;
|
}
|
|
function getGraphics(color, width, height, x, y) {
|
let graphics = new PIXI.Graphics();
|
graphics.beginFill(color);
|
graphics.lineStyle(1, 0xffffff, 1);
|
graphics.drawRect(0, 0, width, height);
|
graphics.position.set(x, y);
|
graphics.endFill();
|
return graphics;
|
}
|
|
function getSprite(value, x, y, item, pointerDownEvent) {
|
let sprite;
|
console.log(item.type);
|
if (item.type == 'shelf') {
|
sprite = new PIXI.Sprite(graphicsShelf);
|
} else if (item.type == 'devp') {
|
sprite = new PIXI.Sprite(graphicsDevp);
|
} else if (item.type == 'crn') {
|
if (getDeviceNo(value) == -1) {
|
sprite = new PIXI.Sprite(graphicsCrnTrack);
|
} else {
|
sprite = new PIXI.Sprite(graphicsCrn);
|
const deviceNo = getDeviceNo(value);
|
const taskNo = getTaskNo(value);
|
const style = new PIXI.TextStyle({ fontFamily: 'Arial', fontSize: 10, fill: '#000000' });
|
const txt = taskNo > 0 ? (deviceNo + "(" + taskNo + ")") : String(deviceNo);
|
const text = new PIXI.Text(txt, style);
|
text.anchor.set(0.5);
|
text.position.set(sprite.width / 2, sprite.height / 2);
|
sprite.addChild(text);
|
sprite.textObj = text;
|
pixiCrnMap.set(parseInt(deviceNo), sprite);
|
}
|
} else {
|
return null;
|
}
|
sprite.position.set(x, y);
|
sprite.interactive = true; // 必须要设置才能接收事件
|
sprite.buttonMode = true; // 让光标在hover时变为手型指针
|
|
sprite.on('pointerdown', (e) => {
|
pointerDownEvent(e)
|
})
|
|
return sprite;
|
}
|
|
function getSpriteWithSize(value, x, y, w, h, item, pointerDownEvent) {
|
let sprite;
|
|
// 如果是标准尺寸,使用缓存的纹理
|
if (w === width && h === height) {
|
return getSprite(value, x, y, item, pointerDownEvent);
|
}
|
|
// 合并单元格需要动态创建纹理
|
let graphics = getContainerWithSize(value, w, h);
|
let texture = pixiApp.renderer.generateTexture(graphics);
|
sprite = new PIXI.Sprite(texture);
|
|
sprite.position.set(x, y);
|
sprite.interactive = true;
|
sprite.buttonMode = true;
|
|
sprite.on('pointerdown', (e) => {
|
pointerDownEvent(e)
|
})
|
|
return sprite;
|
}
|
|
/**
|
* 更新颜色
|
*/
|
function updateColor(sprite, color) {
|
// graphics.clear()
|
// graphics.beginFill(color);
|
// graphics.drawRect(0, 0, width, height);
|
sprite.tint = color;
|
}
|
|
function isJson(str) {
|
try {
|
JSON.parse(str);
|
return true;
|
} catch (e) {
|
return false;
|
}
|
}
|
|
function 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;
|
}
|
}
|
|
function getTaskNo(obj) {
|
if (this.isJson(obj)) {
|
let data = JSON.parse(obj)
|
if (data.taskNo == null || data.taskNo == undefined) {
|
return -1;
|
}
|
return data.taskNo;
|
} else {
|
return -1;
|
}
|
}
|
|
function 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;
|
}
|
}
|
|
function 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;
|
}
|
}
|
|
</script>
|
</body>
|
</html>
|