pom.xml | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/main/java/com/zy/asrs/controller/ShuttleController.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/main/java/com/zy/asrs/ws/ConsoleWebSocket.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/main/java/com/zy/asrs/ws/ShuttleWebSocket.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/main/java/com/zy/common/config/WebSocketConfig.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/main/java/com/zy/common/model/WebSocketMessage.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/main/webapp/views/console.html | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/main/webapp/views/console3.html | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/main/webapp/views/shuttle2.html | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 |
pom.xml
@@ -103,6 +103,10 @@ <artifactId>okhttp</artifactId> <version>3.10.0</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-websocket</artifactId> </dependency> <!-- led sdk --> <dependency> src/main/java/com/zy/asrs/controller/ShuttleController.java
@@ -7,6 +7,7 @@ import com.core.common.BaseRes; import com.core.common.Cools; import com.core.common.R; import com.core.common.SpringUtils; import com.core.exception.CoolException; import com.zy.asrs.domain.param.ShuttleOperatorParam; import com.zy.asrs.domain.vo.*; @@ -100,6 +101,12 @@ } } Integer chargeLine = basShuttleService.selectById(slave.getId()).getChargeLine(); String lowerPower = "N"; if (chargeLine != null && shuttleProtocol.getPowerPercent() != null) { lowerPower = shuttleProtocol.getPowerPercent() <= chargeLine ? "Y" : "N"; } shuttleData.put("lowerPower", lowerPower);//是否低电量 baseObj.putAll(shuttleData); } return R.ok().add(list); src/main/java/com/zy/asrs/ws/ConsoleWebSocket.java
New file @@ -0,0 +1,168 @@ package com.zy.asrs.ws; import com.alibaba.fastjson.JSON; import com.core.common.R; import com.core.common.SpringUtils; import com.zy.asrs.controller.ConsoleController; import com.zy.asrs.controller.LiftController; import com.zy.asrs.controller.ShuttleController; import com.zy.common.model.WebSocketMessage; import lombok.Data; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; import org.springframework.stereotype.Service; import javax.websocket.*; import javax.websocket.server.ServerEndpoint; import java.io.IOException; import java.util.concurrent.CopyOnWriteArraySet; @Component @Slf4j @Service @ServerEndpoint("/console/websocket") @Data public class ConsoleWebSocket { //客户端在线人数 private static int onlineClient = 0; //客户端池 private static CopyOnWriteArraySet<ConsoleWebSocket> webSocketServers = new CopyOnWriteArraySet<>(); private Session session; //是否鉴权,默认未鉴权 private boolean auth = false; //是否为管理员 private boolean isAdmin = false; //管道ID private String sessionId; @OnOpen public void onOpen(Session session) { this.session = session; this.sessionId = session.getId(); //将websocket对象进行保存 webSocketServers.add(this); //添加在线人数 addOnlineClient(); log.info("有新窗口开始监听:" + session.getId() + ",当前在线人数为:" + getOnlineClient()); } /** * 连接关闭调用的方法 */ @OnClose public void onClose() { webSocketServers.remove(this); //从set中删除 subOnlineClient(); //在线数减1 log.info("关闭的连接:" + sessionId); log.info("有一连接关闭!当前在线人数为" + getOnlineClient()); } /** * 收到客户端消息后调用的方法 * @ Param message 客户端发送过来的消息 */ @OnMessage public void onMessage(String message, Session session) throws IOException { ShuttleController shuttleController = SpringUtils.getBean(ShuttleController.class); LiftController liftController = SpringUtils.getBean(LiftController.class); ConsoleController consoleController = SpringUtils.getBean(ConsoleController.class); WebSocketMessage socketMessage = JSON.parseObject(message, WebSocketMessage.class); if (socketMessage.getUrl().equals("/shuttle/table/shuttle/state")) { R result = shuttleController.shuttleStateTable(); socketMessage.setData(JSON.toJSONString(result)); this.sendMessage(JSON.toJSONString(socketMessage)); } else if (socketMessage.getUrl().equals("/lift/table/lift/state")) { R result = liftController.liftStateTable(); socketMessage.setData(JSON.toJSONString(result)); this.sendMessage(JSON.toJSONString(socketMessage)); } else if (socketMessage.getUrl().equals("/console/latest/data/site")) { R result = consoleController.siteLatestData(); socketMessage.setData(JSON.toJSONString(result)); this.sendMessage(JSON.toJSONString(socketMessage)); } else if (socketMessage.getUrl().equals("/console/map/auth")) { R result = consoleController.getMapFromRedis(Integer.parseInt(socketMessage.getData())); socketMessage.setData(JSON.toJSONString(result)); this.sendMessage(JSON.toJSONString(socketMessage)); } else if (socketMessage.getUrl().equals("/console/barcode/output/site")) { R result = consoleController.crnOutput(); socketMessage.setData(JSON.toJSONString(result)); this.sendMessage(JSON.toJSONString(socketMessage)); } // log.info("收到来自连接:" + sessionId + "的信息:" + message); } /** * @ Param session * @ Param error */ @OnError public void onError(Session session, Throwable error) { log.error("发生错误"); error.printStackTrace(); } /** * 实现服务器主动推送 */ public void sendMessage(String message) throws IOException { this.session.getBasicRemote().sendText(message); } /** * 服务器主动推送给指定用户 */ public void sendMessage(String message, String account) throws IOException { for (ConsoleWebSocket item : webSocketServers) { item.sendMessage(message); } } public void sendMessage(String message, int userId) throws IOException { for (ConsoleWebSocket item : webSocketServers) { item.sendMessage(message); } } /** * 服务器主动推送给指定用户 */ public static boolean sendMessageGlobal(String message, String account) throws IOException { boolean tag = false; for (ConsoleWebSocket item : webSocketServers) { tag = true; item.sendMessage(message); } return tag; } public static boolean sendMessageGlobal(String message, int userId) throws IOException { boolean tag = false; for (ConsoleWebSocket item : webSocketServers) { tag = true; item.sendMessage(message); } return tag; } public static synchronized int getOnlineClient() { return onlineClient; } public static synchronized void addOnlineClient() { ConsoleWebSocket.onlineClient++; } public static synchronized void subOnlineClient() { if (ConsoleWebSocket.onlineClient > 0) { ConsoleWebSocket.onlineClient--; } } } src/main/java/com/zy/asrs/ws/ShuttleWebSocket.java
New file @@ -0,0 +1,152 @@ package com.zy.asrs.ws; import com.alibaba.fastjson.JSON; import com.core.common.R; import com.core.common.SpringUtils; import com.zy.asrs.controller.ShuttleController; import com.zy.common.model.WebSocketMessage; import lombok.Data; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; import org.springframework.stereotype.Service; import javax.websocket.*; import javax.websocket.server.ServerEndpoint; import java.io.IOException; import java.util.concurrent.CopyOnWriteArraySet; @Component @Slf4j @Service @ServerEndpoint("/shuttle/websocket") @Data public class ShuttleWebSocket { //客户端在线人数 private static int onlineClient = 0; //客户端池 private static CopyOnWriteArraySet<ShuttleWebSocket> webSocketServers = new CopyOnWriteArraySet<>(); private Session session; //是否鉴权,默认未鉴权 private boolean auth = false; //是否为管理员 private boolean isAdmin = false; //管道ID private String sessionId; @OnOpen public void onOpen(Session session) { this.session = session; this.sessionId = session.getId(); //将websocket对象进行保存 webSocketServers.add(this); //添加在线人数 addOnlineClient(); log.info("有新窗口开始监听:" + session.getId() + ",当前在线人数为:" + getOnlineClient()); } /** * 连接关闭调用的方法 */ @OnClose public void onClose() { webSocketServers.remove(this); //从set中删除 subOnlineClient(); //在线数减1 log.info("关闭的连接:" + sessionId); log.info("有一连接关闭!当前在线人数为" + getOnlineClient()); } /** * 收到客户端消息后调用的方法 * @ Param message 客户端发送过来的消息 */ @OnMessage public void onMessage(String message, Session session) throws IOException { ShuttleController shuttleController = SpringUtils.getBean(ShuttleController.class); WebSocketMessage socketMessage = JSON.parseObject(message, WebSocketMessage.class); if (socketMessage.getUrl().equals("/shuttle/table/shuttle/state")) { R result = shuttleController.shuttleStateTable(); socketMessage.setData(JSON.toJSONString(result)); this.sendMessage(JSON.toJSONString(socketMessage)); } else if (socketMessage.getUrl().equals("/shuttle/output/shuttle")) { R result = shuttleController.steOutput(); socketMessage.setData(JSON.toJSONString(result)); this.sendMessage(JSON.toJSONString(socketMessage)); } // log.info("收到来自连接:" + sessionId + "的信息:" + message); } /** * @ Param session * @ Param error */ @OnError public void onError(Session session, Throwable error) { log.error("发生错误"); error.printStackTrace(); } /** * 实现服务器主动推送 */ public void sendMessage(String message) throws IOException { this.session.getBasicRemote().sendText(message); } /** * 服务器主动推送给指定用户 */ public void sendMessage(String message, String account) throws IOException { for (ShuttleWebSocket item : webSocketServers) { item.sendMessage(message); } } public void sendMessage(String message, int userId) throws IOException { for (ShuttleWebSocket item : webSocketServers) { item.sendMessage(message); } } /** * 服务器主动推送给指定用户 */ public static boolean sendMessageGlobal(String message, String account) throws IOException { boolean tag = false; for (ShuttleWebSocket item : webSocketServers) { tag = true; item.sendMessage(message); } return tag; } public static boolean sendMessageGlobal(String message, int userId) throws IOException { boolean tag = false; for (ShuttleWebSocket item : webSocketServers) { tag = true; item.sendMessage(message); } return tag; } public static synchronized int getOnlineClient() { return onlineClient; } public static synchronized void addOnlineClient() { ShuttleWebSocket.onlineClient++; } public static synchronized void subOnlineClient() { if (ShuttleWebSocket.onlineClient > 0) { ShuttleWebSocket.onlineClient--; } } } src/main/java/com/zy/common/config/WebSocketConfig.java
New file @@ -0,0 +1,24 @@ package com.zy.common.config; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker; import org.springframework.web.socket.config.annotation.StompEndpointRegistry; import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer; import org.springframework.web.socket.server.standard.ServerEndpointExporter; @Configuration @EnableWebSocketMessageBroker public class WebSocketConfig implements WebSocketMessageBrokerConfigurer { @Bean public ServerEndpointExporter serverEndpointExporter() { return new ServerEndpointExporter(); } @Override public void registerStompEndpoints(StompEndpointRegistry registry) { registry.addEndpoint("/api/socket"); } } src/main/java/com/zy/common/model/WebSocketMessage.java
New file @@ -0,0 +1,12 @@ package com.zy.common.model; import lombok.Data; @Data public class WebSocketMessage { private String url; private String data; } src/main/webapp/views/console.html
@@ -342,6 +342,7 @@ consoleInterval: null,//定时器存储变量 codeList1: [],//条码List codeList2: [],//条码List ws: null, }, created() { this.init() @@ -351,6 +352,12 @@ }, methods: { init() { this.ws = new WebSocket("ws://" + window.location.host + baseUrl + "/console/websocket"); this.ws.onopen = this.webSocketOnOpen this.ws.onerror = this.webSocketOnError this.ws.onmessage = this.webSocketOnMessage this.ws.onclose = this.webSocketClose this.getMap(this.currentLev) this.getSystemRunningStatus() //获取系统运行状态 @@ -364,22 +371,20 @@ }, //获取地图数据 getMap(lev) { $.ajax({ type: "get", url: baseUrl + "/console/map/" + lev + "/auth", headers: { 'token': localStorage.getItem('token') }, success: (res) => { let data = res.data let tmp = [] for (let i = 1; i < data.length - 1; i++) { tmp.push(data[i]) } // console.log(tmp) this.map = tmp } }) this.sendWs(JSON.stringify({ "url": "/console/map/auth", "data": lev })) }, setMap(res) { //获取地图数据 let data = res.data let tmp = [] for (let i = 1; i < data.length - 1; i++) { tmp.push(data[i]) } // console.log(tmp) this.map = tmp }, openSite(id) { this.siteWindow = true; //打开站点信息弹窗 @@ -409,29 +414,26 @@ }, getSiteInfo() { //获取输送站点数据 $.ajax({ url: baseUrl+ "/console/latest/data/site", 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].siteId); siteEl.attr("class", "site " + sites[i].siteStatus); if (sites[i].workNo != null && sites[i].workNo>0) { siteEl.html(sites[i].siteId + "[" + sites[i].workNo + "]"); } else { siteEl.html(sites[i].siteId); } } } else if (res.code === 403){ parent.location.href = baseUrl+"/login"; } else { console.log(res.msg); this.sendWs("{\"url\":\"/console/latest/data/site\",\"data\":{}}") }, setSiteInfo(res) { //获取输送站点数据 if (res.code === 200){ var sites = res.data; for (var i = 0; i < sites.length; i++){ var siteEl = $("#site-"+sites[i].siteId); siteEl.attr("class", "site " + sites[i].siteStatus); if (sites[i].workNo != null && sites[i].workNo>0) { siteEl.html(sites[i].siteId + "[" + sites[i].workNo + "]"); } else { siteEl.html(sites[i].siteId); } } }); } else if (res.code === 403){ parent.location.href = baseUrl+"/login"; } else { console.log(res.msg); } }, changFloor(lev) { this.currentLev = lev @@ -439,53 +441,41 @@ this.getMap(lev) }, getShuttleStateInfo() { this.sendWs("{\"url\":\"/shuttle/table/shuttle/state\",\"data\":{}}") }, setShuttleStateInfo(res) { // 四向穿梭车信息表获取 let that = this $.ajax({ url: baseUrl + "/shuttle/table/shuttle/state", headers: { 'token': localStorage.getItem('token') }, method: 'POST', success: function(res) { if (res.code == 200) { let currentLevShuttle = []//当前楼层小车集合 res.data.forEach((item,idx) => { if (item != null && item.point != undefined && item.point != null) { if (item.point.z == that.currentLev) { currentLevShuttle.push(item); } } }) that.currentLevShuttleList = currentLevShuttle that.shuttleList = res.data if (that.shuttleColorList.length == 0) { let colorList = []//随机小车颜色 res.data.forEach((item,idx) => { colorList[item.shuttleNo] = that.colorRGB() }) that.shuttleColorList = colorList if (res.code == 200) { let currentLevShuttle = []//当前楼层小车集合 res.data.forEach((item,idx) => { if (item != null && item.point != undefined && item.point != null) { if (item.point.z == that.currentLev) { currentLevShuttle.push(item); } } }) that.currentLevShuttleList = currentLevShuttle that.shuttleList = res.data if (that.shuttleColorList.length == 0) { let colorList = []//随机小车颜色 res.data.forEach((item,idx) => { colorList[item.shuttleNo] = that.colorRGB() }) that.shuttleColorList = colorList } }); } }, getLiftStateInfo() { // 提升机信息表获取 let that = this $.ajax({ url: baseUrl + "/lift/table/lift/state", headers: { 'token': localStorage.getItem('token') }, method: 'POST', success: function(res) { if (res.code == 200) { that.liftList = res.data } } }); this.sendWs("{\"url\":\"/lift/table/lift/state\",\"data\":{}}") }, setLiftStateInfo(res) { // 提升机信息表获取 if (res.code == 200) { this.liftList = res.data } }, systemSwitch() { // 系统开关 @@ -664,22 +654,49 @@ }) }, getCodeData(){ let that = this $.ajax({ url:baseUrl +'/console/barcode/output/site', method:'GET', success:function (res) { if(res.code === 200){ let data = JSON.parse(res.data) if (data.length <= 5) { that.codeList1 = data; } else { that.codeList1 = data.slice(0, 5); that.codeList2 = data.splice(5, 10); } } this.sendWs(JSON.stringify({ "url": "/console/barcode/output/site", "data": {} })) }, setCodeData(res) { if(res.code === 200){ let data = JSON.parse(res.data) if (data.length <= 5) { this.codeList1 = data; } else { this.codeList1 = data.slice(0, 5); this.codeList2 = data.splice(5, 10); } }) } }, 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/barcode/output/site") { this.setCodeData(JSON.parse(result.data)) } }, webSocketClose(e) { console.log("close"); }, sendWs(message) { if (this.ws.readyState == WebSocket.OPEN) { this.ws.send(message) } } } }) src/main/webapp/views/console3.html
New file @@ -0,0 +1,688 @@ <!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/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> </head> <body> <div id="app"> <div style="display: flex;justify-content: center;align-items: center;width: 100%;margin-top: 150px;"> <div id="mapDataId" style="zoom: 0.7;position: relative;"> <div class="pointContainer" v-for="(row,index) in map" :key="index"> <div v-for="(col,idx) in row" :key="idx"> <div v-if="col.value == 0"> <!-- 子轨道 路径为穿梭车预计路径则显示穿梭车颜色和穿梭车号 --> <div :style="{background: checkAdvancePath(index,idx).length == 0 ? '':shuttleColorList[checkAdvancePath(index,idx)[0]]}" class="item" v-if="col.data.length > 0">{{col.data}}</div> <div :style="{background: checkAdvancePath(index,idx).length == 0 ? '':shuttleColorList[checkAdvancePath(index,idx)[0]]}" class="item" v-else>{{checkAdvancePath(index,idx).length == 0 ? idx:checkAdvancePath(index,idx)}}</div> </div> <div v-else-if="col.value == 3"> <!-- 母轨道 路径为穿梭车预计路径则显示穿梭车颜色和穿梭车号 --> <div :style="{background: checkAdvancePath(index,idx).length == 0 ? '#5af':shuttleColorList[checkAdvancePath(index,idx)[0]]}" class="item">{{checkAdvancePath(index,idx).length == 0 ? '⇅⇄':checkAdvancePath(index,idx)}}</div> </div> <div v-else-if="col.value == 4"> <!-- 站点 --> <div class="site" :id="'site-' + col.data" @click="openSite(col.data)">{{col.data}}</div> </div> <div v-else-if="col.value == 5"> <!-- 充电桩 --> <div class="item" style="font-size: 24px">⚡</div> </div> <div v-else-if="col.value == -999"> <!-- 路径占用区域 --> <div class="item" style="background:#f83333;color: #fff;">{{idx}}</div> </div> <div v-else-if="col.value < 0"> <!-- 禁止显示区域 --> <div class="item" style="visibility: hidden">{{idx}}</div> </div> <div v-else> <div class="item" v-if="col.data.length > 0">{{col.data}}</div> <div class="item" v-else>{{idx}}-{{col.value}}</div> </div> </div> <div> <!-- 显示行号 --> <div class="item" style="background: none;color: #000;">#{{index+1}}</div> </div> </div> <!--输出小车--> <div v-for="(car,idx) in currentLevShuttleList" :style="{ left: getCarPosition(car.wcsPoint.x,car.wcsPoint.y)[1] ,top: getCarPosition(car.wcsPoint.x,car.wcsPoint.y)[0] ,color: shuttleColorList[car.shuttleNo] }" class="sxcar" :id="'sxcar-' + car.shuttleNo"> {{car.shuttleNo}} </div> </div> <!--输出楼层--> <div style="height: 100%;"> <div class="floorBtnBox" v-for="(lev,idx) in floorList"> <el-button :style="{background:currentLev === lev ? '#7DCDFF':''}" @click="changFloor(lev)">{{lev}}F</el-button> </div> <div> <el-button @click="testMove()">测试移动车</el-button> <el-button @click="resetMap()">重置地图</el-button> </div> </div> </div> <div class="footer"> <!-- 总开关 --> <div class="line-status"> <div class="body-head">总开关</div> <div class="switch" @click="systemSwitch"> <label id="system-toggle" class="toggle-switch" style="margin-left: 20px;"> <input id="system-toggle-checked" disabled type="checkbox"> <div class="button"> <div class="light"></div> <div class="dots"></div> <div class="characters"></div> <div class="shine"></div> <div class="shadow"></div> </div> </label> <div class="switch_r"> <p>系统状态</p> <p id="system-run-desc">系统运行中</p> </div> </div> </div> <!-- 四向穿梭车状态 --> <div class="line-status"> <div class="body-head">穿梭车状态</div> <div class="shuttle-status-box"> <div v-for="(item,idx) in shuttleList" class="state"> <span :style="{color: shuttleColorList[item.shuttleNo]}">四向穿梭车 {{item.shuttleNo}}</span> <span v-if="item.protocolStatus == 1" class="state-ss shuttle-idle">{{item.protocolStatus$}}</span> <span v-else-if="item.protocolStatus == 2" class="state-ss shuttle-working">{{item.protocolStatus$}}</span> <span v-else-if="item.protocolStatus == 3" class="state-ss shuttle-waiting">{{item.protocolStatus$}}</span> <span v-else-if="item.protocolStatus == 4" class="state-ss shuttle-charging">{{item.protocolStatus$}}</span> <span v-else-if="item.protocolStatus == 5" class="state-ss shuttle-charging-waiting">{{item.protocolStatus$}}</span> <span v-else-if="item.protocolStatus == 6" class="state-ss shuttle-fixing">{{item.protocolStatus$}}</span> <span v-else-if="item.protocolStatus == 7" class="state-ss shuttle-offline">{{item.protocolStatus$}}</span> <span v-else class="state-ss shuttle-offline">{{item.protocolStatus$}}</span> </div> </div> <div class="allStatus"><span>所有状态</span></div> <div class="allStatus item-group"> <span class="shuttle-idle">空闲</span> <span class="shuttle-working">作业中</span> <span class="shuttle-waiting">等待确认</span> <span class="shuttle-charging">充电中</span> <span class="shuttle-charging-waiting">充电任务等待确认</span> <span class="shuttle-fixing">故障修复中</span> <span class="shuttle-offline">离线</span> </div> </div> <!-- 提升机状态 --> <div class="line-status"> <div class="body-head">提升机状态</div> <div class="lift-status-box"> <div v-for="(item,idx) in liftList" class="state states"> <span>提升机 {{item.liftNo}}</span> <span v-if="item.protocolStatus == 1" class="state-ss lift-idle">{{item.protocolStatus$}}</span> <span v-else-if="item.protocolStatus == 2" class="state-ss lift-working">{{item.protocolStatus$}}</span> <span v-else-if="item.protocolStatus == 3" class="state-ss lift-waiting">{{item.protocolStatus$}}</span> <span v-else-if="item.protocolStatus == 4" class="state-ss lift-offline">{{item.protocolStatus$}}</span> <span v-else class="state-ss lift-offline">{{item.protocolStatus$}}</span> </div> </div> <div class="allStatus"><span>所有状态</span></div> <div class="allStatus item-group"> <span class="lift-idle">空闲</span> <span class="lift-working">作业中</span> <span class="lift-waiting">等待确认</span> <span class="lift-offline">离线</span> </div> </div> <!-- 输送线状态 --> <div class="line-status"> <div class="body-head">输送线状态</div> <div class="state states"> <span>运输线总数</span> <span class="line-ss">9</span> </div> <div class="allStatus"><span>所有状态</span></div> <div class="allStatus item-group"> <span class="site-auto-run-id">自动+有物+ID</span> <span class="site-auto-run">自动+有物</span> <span class="site-auto-id">自动+ID</span> <span class="site-auto">自动</span> <span class="site-unauto">非自动/手动</span> </div> </div> <!-- 条码表格 --> <div class="bar-code"> <div class="body-head" id="code">条码扫描器</div> <div class="tablebox"> <div class="table-head"> <li><span>条码名称</span><span class="right">扫码时间</span></li> </div> <div id="barcode1" class="table-body"> <li v-for="(item,index) in codeList1" :key="index"><span>{{item.barcode}}</span><span class="right">{{item.time}}</span></li> </div> </div> <div class="tablebox"> <div class="table-head"> <li><span>条码名称</span><span class="right">扫码时间</span></li> </div> <div id="barcode2" class="table-body"> <li v-for="(item,index) in codeList2" :key="index"><span>{{item.barcode}}</span><span class="right">{{item.time}}</span></li> </div> </div> </div> </div> <!-- 输送设备弹窗 --> <div id="siteWindow" :style="{display:siteWindow?'block':'none'}" class="animate__animated animate__fadeIn"> <!-- 表头 --> <div id="siteWindow-head"> <div class="detailed"></div> <button @click="siteWindow = false"></button> </div> <!-- 表内容 --> <div class="siteWindow-body"> <form> <!-- 设备号 --> <div class="form-item"> <div class="form-item-label"> <span>设备号:</span> </div> <div class="form-item-input"> <input type="text" name="siteId" value=""> </div> </div> <!-- 工作号 --> <div class="form-item"> <div class="form-item-label"> <span>工作号:</span> </div> <div class="form-item-input"> <input type="text" name="workNo" value=""> </div> </div> <!-- 工作状态 --> <div class="form-item"> <div class="form-item-label"> <span>工作状态:</span> </div> <div class="form-item-input"> <input type="text" name="wrkSts" value=""> </div> </div> <div class="form-item"> <!-- 自动 --> <div class="form-item-checkbox"> <div class="form-item-label-checkbox"> <span>自动</span> </div> <div class="form-item-input-checkbox"> <input type="checkbox" name="autoing"> </div> </div> <!-- 有物 --> <div class="form-item-checkbox"> <div class="form-item-label-checkbox"> <span>有物</span> </div> <div class="form-item-input-checkbox"> <input type="checkbox" name="loading"> </div> </div> <!-- 能入 --> <div class="form-item-checkbox"> <div class="form-item-label-checkbox"> <span>能入</span> </div> <div class="form-item-input-checkbox"> <input type="checkbox" name="canining"> </div> </div> <!-- 能出 --> <div class="form-item-checkbox"> <div class="form-item-label-checkbox"> <span>能出</span> </div> <div class="form-item-input-checkbox"> <input type="checkbox" name="canouting"> </div> </div> </div> <!-- 出入类型 --> <div class="form-item"> <div class="form-item-label"> <span>出入类型:</span> </div> <div class="form-item-input"> <input type="text" name="ioType" value=""> </div> </div> <!-- 源站 --> <div class="form-item"> <div class="form-item-label"> <span>源站:</span> </div> <div class="form-item-input"> <input type="text" name="sourceStaNo" value=""> </div> </div> <!-- 目标站 --> <div class="form-item"> <div class="form-item-label"> <span>目标站:</span> </div> <div class="form-item-input"> <input type="text" name="staNo" value=""> </div> </div> <!-- 源库位 --> <div class="form-item"> <div class="form-item-label"> <span>源库位:</span> </div> <div class="form-item-input"> <input type="text" name="sourceLocNo" value=""> </div> </div> <!-- 目标库位 --> <div class="form-item"> <div class="form-item-label"> <span>目标库位:</span> </div> <div class="form-item-input"> <input type="text" name="locNo" value=""> </div> </div> </form> </div> </div> </div> <script> var app = new Vue({ el: '#app', data: { map: [],//地图数据 currentLev: 1,//地图当前楼层 siteWindow: false, //站点弹窗显示默认不显示 floorList: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], //当前项目楼层 shuttleList: [], //四向穿梭车集合 currentLevShuttleList: [],//当前楼层四向穿梭车集合 shuttleColorList: [],//四向穿梭车颜色集合 liftList: [], //提升机集合 systemStatus: true,//系统运行状态 consoleInterval: null,//定时器存储变量 codeList1: [],//条码List codeList2: [],//条码List }, created() { this.init() }, watch: { }, methods: { init() { this.getMap(this.currentLev) this.getSystemRunningStatus() //获取系统运行状态 this.consoleInterval = setInterval(() => { this.getShuttleStateInfo() //获取四向穿梭车信息 this.getLiftStateInfo() //获取提升机信息 this.getSiteInfo() //获取输送站点数据 this.getMap(this.currentLev) //获取实时地图数据 this.getCodeData()//获取条码 }, 1000) }, //获取地图数据 getMap(lev) { $.ajax({ type: "get", url: baseUrl + "/console/map/" + lev + "/auth", headers: { 'token': localStorage.getItem('token') }, success: (res) => { let data = res.data let tmp = [] for (let i = 1; i < data.length - 1; i++) { tmp.push(data[i]) } // console.log(tmp) this.map = tmp } }) }, openSite(id) { this.siteWindow = true; //打开站点信息弹窗 $(".detailed").empty(); $('.detailed').append(id + '站点详细信息'); $.ajax({ url: baseUrl + "/console/site/detail", headers: { 'token': localStorage.getItem('token') }, data: { siteId: id }, method: 'post', success: function(res) { for (var val in res.data) { var find = $("#siteWindow").find(":input[name='" + val + "']"); if (find[0].type === 'text') { find.val(res.data[val]); } else if (find[0].type === 'checkbox') { find.attr("checked", res.data[val] === 'Y'); } } } }) }, getSiteInfo() { //获取输送站点数据 $.ajax({ url: baseUrl+ "/console/latest/data/site", 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].siteId); siteEl.attr("class", "site " + sites[i].siteStatus); if (sites[i].workNo != null && sites[i].workNo>0) { siteEl.html(sites[i].siteId + "[" + sites[i].workNo + "]"); } else { siteEl.html(sites[i].siteId); } } } else if (res.code === 403){ parent.location.href = baseUrl+"/login"; } else { console.log(res.msg); } } }); }, changFloor(lev) { this.currentLev = lev this.currentLevShuttleList = [] this.getMap(lev) }, getShuttleStateInfo() { // 四向穿梭车信息表获取 let that = this $.ajax({ url: baseUrl + "/shuttle/table/shuttle/state", headers: { 'token': localStorage.getItem('token') }, method: 'POST', success: function(res) { if (res.code == 200) { let currentLevShuttle = []//当前楼层小车集合 res.data.forEach((item,idx) => { if (item != null && item.point != undefined && item.point != null) { if (item.point.z == that.currentLev) { currentLevShuttle.push(item); } } }) that.currentLevShuttleList = currentLevShuttle that.shuttleList = res.data if (that.shuttleColorList.length == 0) { let colorList = []//随机小车颜色 res.data.forEach((item,idx) => { colorList[item.shuttleNo] = that.colorRGB() }) that.shuttleColorList = colorList } } } }); }, getLiftStateInfo() { // 提升机信息表获取 let that = this $.ajax({ url: baseUrl + "/lift/table/lift/state", headers: { 'token': localStorage.getItem('token') }, method: 'POST', success: function(res) { if (res.code == 200) { that.liftList = res.data } } }); }, 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' }); } } }); }, getCarPosition(x,y) { //计算四向穿梭车图标位置 let top = (x * 35 - 35) + "px" //需要减去小车自己所占高度 let left = (y * 35) + "px" //需要减去小车自己所占宽度 return [top,left]; }, testMove() { let that = this clearInterval(this.consoleInterval)//清理定时器 let shuttleList = this.currentLevShuttleList $.ajax({ url: baseUrl + "/static/testMoveData.json", headers: { 'token': localStorage.getItem('token') }, method: 'GET', success: function(res) { shuttleList[0].moveAdvancePath = res that.currentLevShuttleList = shuttleList let index = 0 let tmp = null tmp = setInterval(() => { if (index < res.length) { that.currentLevShuttleList[0].wcsPoint.y = res[index].y that.currentLevShuttleList[0].wcsPoint.x = res[index].x index++ }else { clearInterval(tmp) that.init() } },1000) } }); }, 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})`; }, checkAdvancePath(x,y) { //检测路径是否为穿梭车预计路径,如x和y路径是穿梭车预计路径,则返回小车号 this.currentLevShuttleList.forEach((item,idx) => { if (item.moveAdvancePath != null) { item.moveAdvancePath.forEach((path,index) => { if (path.x === x && path.y === y) { return item.shuttleNo; } }) } }) let data = [] let shuttleList = this.currentLevShuttleList; for (var i = 0; i < shuttleList.length; i++) { let shuttle = shuttleList[i] let moveAdvancePath = shuttle.moveAdvancePath if (moveAdvancePath != null) { for (var j = 0; j < moveAdvancePath.length; j++) { let path = moveAdvancePath[j] if (path.x-1 === x && path.y === y) {//路径符合 data.push(shuttle.shuttleNo) continue; } } } } return data;//返回小车号集合 }, resetMap() { //重置地图 let that = this $.ajax({ url:baseUrl+"/console/map/resetMap/auth", headers:{ 'token': localStorage.getItem('token') }, data:{}, method:'get', success:function (res) { that.$message({ message: '重置完成', type: 'success' }); } }) }, getCodeData(){ let that = this $.ajax({ url:baseUrl +'/console/barcode/output/site', method:'GET', success:function (res) { if(res.code === 200){ let data = JSON.parse(res.data) if (data.length <= 5) { that.codeList1 = data; } else { that.codeList1 = data.slice(0, 5); that.codeList2 = data.splice(5, 10); } } } }) } } }) </script> </body> </html> src/main/webapp/views/shuttle2.html
@@ -48,6 +48,7 @@ <th>故障状态</th> <th>故障码</th> <th>管制状态</th> <th>低电量</th> </tr> </thead> <tbody> @@ -229,18 +230,46 @@ var shuttleMsgTableFullRows = 0; // 初始化 var shuttleOutputDom = document.getElementById("shuttle-output"); var ws = new WebSocket("ws://" + window.location.host + baseUrl + "/shuttle/websocket"); //当WebSocket创建成功时,触发onopen事件 ws.onopen = function(){ console.log("open"); } //当客户端收到服务端发来的消息时,触发onmessage事件 ws.onmessage = function(e){ const result = JSON.parse(e.data); if (result.url == "/shuttle/table/shuttle/state") { setShuttleStateInfo(JSON.parse(result.data)) setShuttleMsgInfo(JSON.parse(result.data)) }else if (result.url == "/shuttle/output/shuttle") { setShuttleOutput(JSON.parse(result.data)) } // console.log(e.data,result); } //当客户端收到服务端发送的关闭连接请求时,触发onclose事件 ws.onclose = function(e){ console.log("close"); } //如果出现连接、处理、接收、发送数据失败的时候触发onerror事件 ws.onerror = function(e) { console.log(error); } $(document).ready(function() { initShuttleStateTable(); getShuttleStateInfo(); initShuttleMsgTable(); getShuttleMsgInfo(); operatorBlockShow(); setShuttleRadio(); }); setInterval(function () { getShuttleStateInfo() getShuttleMsgInfo(); getShuttleStateInfo(); },1000) setInterval(function () { getShuttleOutput(); @@ -318,107 +347,96 @@ // 四向穿梭车信息表获取 ---- 表一 function getShuttleStateInfo() { sendWs("{\"url\":\"/shuttle/table/shuttle/state\",\"data\":{}}") } // 四向穿梭车信息表设置 ---- 表一 function setShuttleStateInfo(res) { let tableEl = $('#shuttle-state-table'); $.ajax({ url: baseUrl+ "/shuttle/table/shuttle/state", headers: {'token': localStorage.getItem('token')}, method: 'POST', success: function (res) { if (res.code === 200){ let table = res.data; if (table.length > shuttleStateTableBlankRows && table.length !== shuttleStateTableFullRows) { initShuttleStateTable(table.length-shuttleStateTableBlankRows); shuttleStateTableFullRows = table.length; } for (let i=1;i<=table.length;i++){ // $("#mode-"+table[i-1].shuttleNo).html(table[i-1].statusVal===0?'联机':'脱机'); let tr = tableEl.find("tr").eq(i); setVal(tr.children("td").eq(0), table[i-1].shuttleNo); setVal(tr.children("td").eq(1), table[i-1].protocolStatus$); setVal(tr.children("td").eq(2), table[i-1].free$); setVal(tr.children("td").eq(3), table[i-1].workingMode$); setVal(tr.children("td").eq(4), table[i-1].point$); setVal(tr.children("td").eq(5), table[i-1].point$$); setVal(tr.children("td").eq(6), table[i-1].powerPercent$); setVal(tr.children("td").eq(7), table[i-1].speed); setVal(tr.children("td").eq(8), table[i-1].loadState$); setVal(tr.children("td").eq(9), table[i-1].liftPosition$); setVal(tr.children("td").eq(10), table[i-1].runDir$); setVal(tr.children("td").eq(11), table[i-1].runDir2$); setVal(tr.children("td").eq(12), table[i-1].chargState$); setVal(tr.children("td").eq(13), table[i-1].errState$); setVal(tr.children("td").eq(14), table[i-1].errCode$); setVal(tr.children("td").eq(15), table[i-1].suspendState$); } } else if (res.code === 403){ window.location.href = baseUrl+"/login"; } else { console.log(res.msg); } if (res.code === 200){ let table = res.data; if (table.length > shuttleStateTableBlankRows && table.length !== shuttleStateTableFullRows) { initShuttleStateTable(table.length-shuttleStateTableBlankRows); shuttleStateTableFullRows = table.length; } }); for (let i=1;i<=table.length;i++){ // $("#mode-"+table[i-1].shuttleNo).html(table[i-1].statusVal===0?'联机':'脱机'); let tr = tableEl.find("tr").eq(i); setVal(tr.children("td").eq(0), table[i-1].shuttleNo); setVal(tr.children("td").eq(1), table[i-1].protocolStatus$); setVal(tr.children("td").eq(2), table[i-1].free$); setVal(tr.children("td").eq(3), table[i-1].workingMode$); setVal(tr.children("td").eq(4), table[i-1].point$); setVal(tr.children("td").eq(5), table[i-1].point$$); setVal(tr.children("td").eq(6), table[i-1].powerPercent$); setVal(tr.children("td").eq(7), table[i-1].speed); setVal(tr.children("td").eq(8), table[i-1].loadState$); setVal(tr.children("td").eq(9), table[i-1].liftPosition$); setVal(tr.children("td").eq(10), table[i-1].runDir$); setVal(tr.children("td").eq(11), table[i-1].runDir2$); setVal(tr.children("td").eq(12), table[i-1].chargState$); setVal(tr.children("td").eq(13), table[i-1].errState$); setVal(tr.children("td").eq(14), table[i-1].errCode$); setVal(tr.children("td").eq(15), table[i-1].suspendState$); setVal(tr.children("td").eq(16), table[i-1].lowerPower); } } else if (res.code === 403){ window.location.href = baseUrl+"/login"; } else { console.log(res.msg); } } // 四向穿梭车数据表获取 ---- 表二 function getShuttleMsgInfo() { function setShuttleMsgInfo(res) { let tableEl = $('#shuttle-msg-table'); $.ajax({ url: baseUrl+ "/shuttle/table/shuttle/state", headers: {'token': localStorage.getItem('token')}, method: 'POST', success: function (res) { if (res.code === 200){ var table = res.data; if (table.length > shuttleMsgTableBlankRows && table.length !== shuttleMsgTableFullRows) { initShuttleMsgTable(table.length-shuttleMsgTableBlankRows); shuttleMsgTableFullRows = table.length; } for (var i=1;i<=table.length;i++){ var tr = tableEl.find("tr").eq(i); setVal(tr.children("td").eq(0), table[i-1].shuttleNo); setVal(tr.children("td").eq(1), table[i-1].taskNo); setVal(tr.children("td").eq(2), table[i-1].sourceLocNo); setVal(tr.children("td").eq(3), table[i-1].locNo); setVal(tr.children("td").eq(4), table[i-1].maxCellVoltage$); setVal(tr.children("td").eq(5), table[i-1].minCellVoltage$); setVal(tr.children("td").eq(6), table[i-1].voltage$); setVal(tr.children("td").eq(7), table[i-1].chargeCycleTimes); setVal(tr.children("td").eq(8), table[i-1].surplusQuantity); setVal(tr.children("td").eq(9), table[i-1].countQuantity); setVal(tr.children("td").eq(10), table[i-1].statusSum ? table[i - 1].statusSum.mileage : ''); setVal(tr.children("td").eq(11), table[i-1].pakMk$); setVal(tr.children("td").eq(12), table[i-1].currentLocNo); setVal(tr.children("td").eq(13), table[i-1].token); if (table[i-1].shuttleNo == parseInt($('input[name="shuttleSelect"]:checked').val())) { $("#runSpeedText").text(table[i-1].runSpeed) $("#chargeLineText").text(table[i-1].chargeLine + "%") } } } else if (res.code === 403){ window.location.href = baseUrl+"/login"; } else { console.log(res.msg); if (res.code === 200){ var table = res.data; if (table.length > shuttleMsgTableBlankRows && table.length !== shuttleMsgTableFullRows) { initShuttleMsgTable(table.length-shuttleMsgTableBlankRows); shuttleMsgTableFullRows = table.length; } for (var i=1;i<=table.length;i++){ var tr = tableEl.find("tr").eq(i); setVal(tr.children("td").eq(0), table[i-1].shuttleNo); setVal(tr.children("td").eq(1), table[i-1].taskNo); setVal(tr.children("td").eq(2), table[i-1].sourceLocNo); setVal(tr.children("td").eq(3), table[i-1].locNo); setVal(tr.children("td").eq(4), table[i-1].maxCellVoltage$); setVal(tr.children("td").eq(5), table[i-1].minCellVoltage$); setVal(tr.children("td").eq(6), table[i-1].voltage$); setVal(tr.children("td").eq(7), table[i-1].chargeCycleTimes); setVal(tr.children("td").eq(8), table[i-1].surplusQuantity); setVal(tr.children("td").eq(9), table[i-1].countQuantity); setVal(tr.children("td").eq(10), table[i-1].statusSum ? table[i - 1].statusSum.mileage : ''); setVal(tr.children("td").eq(11), table[i-1].pakMk$); setVal(tr.children("td").eq(12), table[i-1].currentLocNo); setVal(tr.children("td").eq(13), table[i-1].token); if (table[i-1].shuttleNo == parseInt($('input[name="shuttleSelect"]:checked').val())) { $("#runSpeedText").text(table[i-1].runSpeed) $("#chargeLineText").text(table[i-1].chargeLine + "%") } } }); } else if (res.code === 403){ window.location.href = baseUrl+"/login"; } else { console.log(res.msg); } } // 穿梭车日志输出 ----------------------------------------------------------------------- function getShuttleOutput() { $.ajax({ url: baseUrl + "/shuttle/output/shuttle", headers: {'token': localStorage.getItem('token')}, method: 'POST', success: function (res) { if (res.code === 200) { shuttleOutput(res.data); } else if (res.code === 403) { window.location.href = baseUrl + "/login"; } else { console.log(res.msg); } } }) sendWs("{\"url\":\"/shuttle/output/shuttle\",\"data\":{}}") } function setShuttleOutput(res) { if (res.code === 200) { shuttleOutput(res.data); } else if (res.code === 403) { window.location.href = baseUrl + "/login"; } else { console.log(res.msg); } } // 任务指令下发 @@ -622,5 +640,10 @@ layer.close(layerDetl); }) function sendWs(message) { if (ws.readyState == WebSocket.OPEN) { ws.send(message) } } </script>