<!DOCTYPE html>
|
<html lang="en">
|
<head>
|
<meta charset="utf-8">
|
<title>智能系统</title>
|
<link rel="icon" href="../../static/images/favicon.ico" type="image/x-icon">
|
|
<link rel="stylesheet" href="../../static/wcs/css/element.css">
|
<link rel="stylesheet" href="../../static/wcs/css/indexHCDD.css">
|
<link rel="stylesheet" href="../../static/wcs/css/element-ui.css">
|
<script type="text/javascript" src="../../static/js/jquery/jquery-3.3.1.min.js"></script>
|
<script type="text/javascript" src="../../static/js/common.js"></script>
|
<script type="text/javascript" src="../../static/wcs/js/vue.min.js"></script>
|
<script type="text/javascript" src="../../static/wcs/js/element.js"></script>
|
<script type="text/javascript" src="../../static/wcs/js/testPosition.js"></script>
|
<style>
|
|
.site-logo {
|
position: absolute; /* 使用绝对定位,将Logo脱离正常文档流 */
|
top: 10px; /* 距离顶部10像素,可根据需要调整 */
|
left: 10px; /* 距离左侧10像素,可根据需要调整 */
|
padding: 0; /* 移除原有的内边距 */
|
text-align: left; /* 将图片对齐方式改为左对齐 */
|
z-index: 1000; /* 确保Logo显示在最上层,避免被其他元素遮挡 */
|
}
|
|
.site-logo img {
|
max-width: 80%; /* Logo最大宽度为容器宽度的80% */
|
height: auto; /* 高度自动,保持比例 */
|
max-height: 60px; /* 设置Logo最大高度 */
|
}
|
</style>
|
</head>
|
<body >
|
<div class="tech-background">
|
<div class="grid-overlay"></div>
|
<div class="glow-effect"></div>
|
<div class="particles-container" id="particles-container"></div>
|
</div>
|
<div id="app">
|
<!-- 添加Logo -->
|
<div class="site-logo">
|
<img src="../../static/images/zy_logo_dark_color.png" alt="自动仓库WCS系统 Logo">
|
</div>
|
<div class="map">
|
<div class="system-control-panel">
|
<div class="system-status">
|
<div class="status-indicator" :class="valueSystem ? 'status-running' : 'status-stopped'"></div>
|
<span class="status-text">{{ valueSystem ? '系统运行中' : '系统已停止' }}</span>
|
</div>
|
<div class="custom-switch">
|
<el-switch
|
v-model="valueSystem"
|
active-color="#13ce66"
|
inactive-color="#A64036"
|
@change='upDateValueSystem'>
|
</el-switch>
|
</div>
|
</div>
|
|
<div class="license-info" :class="getLicenseClass()" v-if="licenseDayI <=30">
|
<span class="license-icon">📄</span>
|
{{ licenseDay }}
|
</div>
|
<!-- <div class="inner-ring"></div>-->
|
<!-- <div class="outer-ring"></div>-->
|
<!-- <div v-for="track in energyGatheringRing" class="inner-ring" :style="{ borderColor: track.trackColor , boxShadow : 'inset 0 0 30px '+track.radiationColor+', 0 0 20px '+track.radiationColor}"></div>-->
|
<!-- <div v-for="track in energyGatheringRing" class="outer-ring" :style="{ borderColor: track.trackColor , boxShadow : 'inset 0 0 30px '+track.radiationColor+', 0 0 20px '+track.radiationColor}"></div>-->
|
<svg class="container"
|
viewBox="0 0 1200 850"
|
preserveAspectRatio="xMidYMid meet">
|
<path d="M 100,225 L 1100,225"
|
style="fill:none; stroke:blue; stroke-width:3; stroke-dasharray:10,1;"/>
|
<path d="M 100,625 L 1100,625"
|
style="fill:none; stroke:blue; stroke-width:3; stroke-dasharray:10,1;"/>
|
</svg>
|
|
<div v-for="station in tableDataDev" class="station" :style="{
|
top: convertToCSSPosition2(station.index,station.valueX, station.valueY).y + 'px',
|
left: convertToCSSPosition2(station.index,station.valueX, station.valueY).x + 'px',
|
backgroundColor: station.modeColor}">
|
<div class="corner corner-tl"></div>
|
<div class="corner corner-tr"></div>
|
<div class="corner corner-bl"></div>
|
<div class="corner corner-br"></div>
|
{{ station.index }}
|
</div>
|
|
<!-- Buses -->
|
<div v-for="bus in tableDataRgv" class="bus" :style="{
|
top: convertToCSSPositionWithOffset(bus.valueX, bus.valueY).y + 'px',
|
left: convertToCSSPositionWithOffset(bus.valueX, bus.valueY).x + 'px',
|
animation: 'pulse ' + bus.animation + 's infinite',
|
borderColor: bus.modeColor, backgroundColor: bus.statusColor}">{{ bus.index }}
|
</div>
|
|
</div>
|
</div>
|
|
<script>
|
// 在Vue实例外添加粒子生成函数
|
function createParticles() {
|
const container = document.getElementById('particles-container');
|
const particleCount = 30;
|
|
for (let i = 0; i < particleCount; i++) {
|
const particle = document.createElement('div');
|
particle.classList.add('particle');
|
|
// 随机大小和位置
|
const size = Math.random() * 3 + 1;
|
const posX = Math.random() * 100;
|
const posY = Math.random() * 100;
|
const delay = Math.random() * 15;
|
|
particle.style.width = `${size}px`;
|
particle.style.height = `${size}px`;
|
particle.style.left = `${posX}vw`;
|
particle.style.top = `${posY}vh`;
|
particle.style.animationDelay = `${delay}s`;
|
|
container.appendChild(particle);
|
}
|
}
|
|
// 页面加载完成后创建粒子
|
document.addEventListener('DOMContentLoaded', createParticles);
|
// 在Vue实例外获取body尺寸
|
function getBodySize() {
|
return {
|
width: document.body.clientWidth,
|
height: document.body.clientHeight
|
};
|
}
|
var app = new Vue({
|
el: '#app',
|
data: {
|
containerSize: { width: 0, height: 0},
|
bodySize: { width: 0, height: 0 },
|
activeNames: ['1'],
|
valueLeft: '0',
|
valueLeft1: '0',
|
valueRight: '0',
|
valueRight1: '0',
|
licenseDay: '已过期',
|
licenseDayI: 100,
|
valueSystem: false,
|
tableDataRgv: [],
|
tableDataDev: [],
|
energyGatheringRing: [],
|
tableDataLeft: [],
|
tableDataLeft1: [],
|
tableDataRight: [],
|
tableDataRight1: []
|
},
|
created(){
|
this.init();
|
},
|
watch: {
|
|
},
|
|
// 在 mounted 中初始化尺寸和监听
|
mounted() {
|
this.updateContainerSize();
|
this.updateBodySize();
|
window.addEventListener('resize', this.handleResize);
|
},
|
beforeDestroy() {
|
window.removeEventListener('resize', this.handleResize);
|
},
|
computed: {
|
mappedStations() {
|
return this.tableDataDev.map(station => ({
|
...station,
|
position: this.convertToCSSPosition2(station.index,station.valueX, station.valueY)
|
}));
|
}
|
},
|
methods: {
|
init(){
|
this.getTableDataRgv()
|
this.getTableDataDev()
|
this.getTableDataTrack()
|
this.getTableDataLeft()
|
this.getTableDataLeft1()
|
this.getTableDataRight()
|
this.getTableDataRight1()
|
this.getValueSystem()
|
this.getLicenseDays()
|
|
// 高频更新:小车和设备位置(1.5秒)
|
setInterval(() => {
|
this.getTableDataRgv()
|
}, 1000)
|
|
// 高频更新:实时任务列表等(2秒)
|
setInterval(() => {
|
this.getTableDataLeft()
|
this.getTableDataRight()
|
}, 2000)
|
|
// 高频更新:实时站点信息等(3秒)
|
setInterval(() => {
|
this.getTableDataDev()
|
}, 3000)
|
|
// 低频更新:任务列表等(10秒)
|
setInterval(() => {
|
this.getTableDataLeft1()
|
this.getTableDataRight1()
|
this.getValueSystem()
|
}, 10*1000)
|
|
// 低频更新:许可证信息(30秒)
|
setInterval(() => {
|
this.getLicenseDays()
|
}, 30000)
|
|
// 静态低频更新:PLC(1小时)
|
setInterval(() => {
|
this.getTableDataTrack()
|
}, 60*60*1000)
|
},
|
// 获取容器实际尺寸
|
updateContainerSize() {
|
const mapEl = this.$el.querySelector('.map');
|
this.containerSize = {
|
width: mapEl.clientWidth,
|
height: mapEl.clientHeight
|
};
|
},
|
convertToCSSPositionWithOffset(svgX, svgY, radius) {
|
const basePos = this.convertToCSSPosition(svgX, svgY);
|
return {
|
x: basePos.x-16.5,
|
y: basePos.y-16.5
|
};
|
},
|
// 更新body尺寸
|
updateBodySize() {
|
this.bodySize = getBodySize();
|
},
|
|
// 坐标转换函数
|
convertToCSSPosition(svgX, svgY) {
|
const svgWidth = 1200; // SVG 原始宽度
|
let svgWidthR = 0; //
|
const svgHeight = 850; // SVG 原始高度
|
let svgHeightR = 0; //
|
if (svgX>svgWidth/2){
|
svgWidthR = (((svgX-svgWidth/2)/svgWidth) * this.containerSize.width) + this.bodySize.width/2 - this.bodySize.width*((1-0.52)/2);
|
} else {
|
svgWidthR = this.bodySize.width/2 - (((svgWidth/2 - svgX)/svgWidth) * this.containerSize.width) - this.bodySize.width*((1-0.52)/2);
|
}
|
if (svgY>svgHeight/2){
|
svgHeightR = (((svgY-svgHeight/2)/svgHeight) * this.containerSize.height) + this.bodySize.height/2 - this.bodySize.height*((1-0.72)/2);
|
} else {
|
svgHeightR = this.bodySize.height/2 - (((svgHeight/2 - svgY)/svgHeight) * this.containerSize.height) - this.bodySize.height*((1-0.72)/2);
|
}
|
return {
|
x: svgWidthR,
|
y: svgHeightR
|
};
|
},
|
|
// 坐标转换函数
|
convertToCSSPosition2(devNo,svgX, svgY) {
|
const svgWidth = 1200; // SVG 原始宽度
|
let svgWidthR = 0; //
|
const svgHeight = 850; // SVG 原始高度
|
let svgHeightR = 0; //
|
if (svgX>svgWidth/2){
|
svgWidthR = (((svgX-svgWidth/2)/svgWidth) * this.containerSize.width) + this.bodySize.width/2 - this.bodySize.width*((1-0.52)/2);
|
} else {
|
svgWidthR = this.bodySize.width/2 - (((svgWidth/2 - svgX)/svgWidth) * this.containerSize.width) - this.bodySize.width*((1-0.52)/2);
|
}
|
if (svgY>svgHeight/2){
|
svgHeightR = (((svgY-svgHeight/2)/svgHeight) * this.containerSize.height) + this.bodySize.height/2 - this.bodySize.height*((1-0.72)/2);
|
} else {
|
svgHeightR = this.bodySize.height/2 - (((svgHeight/2 - svgY)/svgHeight) * this.containerSize.height) - this.bodySize.height*((1-0.72)/2);
|
}
|
svgHeightR = svgHeightR-60;
|
if(devNo>200){
|
if (devNo>216){
|
svgHeightR = svgHeightR+80;
|
}
|
} else {
|
if (devNo>116){
|
svgHeightR = svgHeightR+80;
|
} else {
|
if(devNo === 114 || devNo === 112 ){
|
svgWidthR = svgWidthR-20;
|
} else {
|
svgWidthR = svgWidthR+40;
|
}
|
|
}
|
}
|
if(devNo === 116){
|
svgHeightR = svgHeightR-35;
|
}
|
return {
|
x: svgWidthR,
|
y: svgHeightR
|
};
|
},
|
|
handleZoom(e) {
|
const scaleDelta = e.deltaY > 0 ? 0.9 : 1.1;
|
const currentScale = this.scale || 1;
|
const newScale = Math.max(0.5, Math.min(2, currentScale * scaleDelta));
|
|
// 应用缩放
|
const svgEl = this.$el.querySelector('.container');
|
svgEl.style.transform = `scale(${newScale})`;
|
this.scale = newScale;
|
},
|
verifyPassword(callback) {
|
this.$prompt('请输入管理员密码: root', '验证', {
|
confirmButtonText: '确定',
|
cancelButtonText: '取消',
|
inputType: 'password',
|
inputPattern: /^root$/,
|
inputErrorMessage: '密码错误'
|
}).then(({ value }) => {
|
if (value === 'root') {
|
callback();
|
}
|
}).catch(() => {
|
this.$message.info('已取消操作');
|
});
|
},
|
handleChange(val) {
|
if (val.length === 0){
|
valueRight = '0';
|
} else {
|
|
if (val.length >= 1){
|
this.handleChangeValueRight(1)
|
}
|
}
|
},
|
handleChange1(val) {
|
if (val.length === 0){
|
valueRight1 = '0';
|
} else {
|
if (val.length >= 1){
|
this.handleChangeValueRight1(1)
|
}
|
}
|
},
|
taskDelete(row) {
|
let that = this;
|
that.$confirm('确认要删除该设备吗?', '提示', {
|
confirmButtonText: '确定',
|
cancelButtonText: '取消',
|
type: 'warning'
|
}).then(() => {
|
$.ajax({
|
url: baseUrl + "/rgv/disable/task/delete",
|
headers: {'token': localStorage.getItem('token')},
|
method: 'POST',
|
data: {
|
wrkNo: row.wrkNo
|
},
|
success: function (res) {
|
if (res.code === 200) {
|
that.$message.success('删除成功');
|
// 删除当前行
|
that.tableDataRight.splice(that.tableDataRight.indexOf(row), 1);
|
} else {
|
that.$message.error('删除失败');
|
}
|
}
|
});
|
});
|
},
|
taskDelete1(row) {
|
let that = this;
|
that.$confirm('确认要初始化该任务吗?', '提示', {
|
confirmButtonText: '确定',
|
cancelButtonText: '取消',
|
type: 'warning'
|
}).then(() => {
|
$.ajax({
|
url: baseUrl + "/rgv/disable/task/delete1",
|
headers: {'token': localStorage.getItem('token')},
|
method: 'POST',
|
data: {
|
wrkNo: row.wrkNo
|
},
|
success: function (res) {
|
if (res.code === 200) {
|
that.$message.success('初始化成功');
|
// 删除当前行
|
// that.tableDataRight.splice(that.tableDataRight.indexOf(row), 1);
|
} else {
|
that.$message.error('初始化失败');
|
}
|
}
|
});
|
});
|
},
|
toggleStatus(index, row) {
|
let that = this;
|
const currentStatus = row.status;
|
const targetStatus = currentStatus === 0 ? 1 : 0;
|
|
that.$confirm(`确认要${currentStatus === 0 ? '禁用' : '启用'}该设备吗?`, '提示', {
|
confirmButtonText: '确定',
|
cancelButtonText: '取消',
|
type: 'warning'
|
}).then(() => {
|
$.ajax({
|
url: baseUrl + "/rgv/disable/rgv/status",
|
headers: {'token': localStorage.getItem('token')},
|
method: 'POST',
|
data: {
|
rgvNo: row.rgvNo,
|
status: targetStatus
|
},
|
success: function (res) {
|
if (res.code === 200) {
|
that.$message.success(`状态更新成功`);
|
row.status$ = targetStatus; // 更新前端状态
|
} else {
|
that.$message.error('状态更新失败');
|
}
|
}
|
});
|
});
|
},
|
handleChangeValueRight(val) {
|
switch (val){
|
case 1:
|
valueRight = '100';
|
case 2:
|
valueRight = '100';
|
case 3:
|
valueRight = '100';
|
case 4:
|
valueRight = '100';
|
default:
|
valueRight = '0';
|
}
|
},
|
handleChangeValueRight1(val) {
|
switch (val){
|
case 1:
|
valueRight1 = '100';
|
case 2:
|
valueRight1 = '100';
|
case 3:
|
valueRight1 = '100';
|
case 4:
|
valueRight1 = '100';
|
default:
|
valueRight1 = '0';
|
}
|
},
|
tableRowClassName({row, rowIndex}) {
|
if (rowIndex === 1) {
|
return 'warning-row';
|
} else if (rowIndex === 3) {
|
return 'success-row';
|
}
|
return '';
|
},
|
|
// 获取许可证样式类
|
getLicenseClass() {
|
if (this.licenseDayI > 30) {
|
return 'normal';
|
} else if (this.licenseDayI > 0) {
|
return 'warning';
|
} else {
|
return 'expired';
|
}
|
},
|
getLicenseDays(){
|
let that = this;
|
$.ajax({
|
url: baseUrl + "/license/getLicenseDays",
|
headers: {'token': localStorage.getItem('token')},
|
method: 'POST',
|
success: function (res) {
|
if (res.code == 200) {
|
if (res.data.day<0){
|
that.licenseDay = "已过期"+res.data.day+"天";
|
that.licenseDayI = -1;
|
} else {
|
that.licenseDay = "许可证有效期"+res.data.day+"天";
|
that.licenseDayI = res.data.day;
|
}
|
}else {
|
that.licenseDay = "已过期";
|
that.licenseDayI = -1;
|
}
|
}
|
});
|
// setTimeout(function() {
|
//
|
// }, 1000);
|
},
|
getValueSystem() {
|
let that = this;
|
$.ajax({
|
url: baseUrl + "/console/system/running/status",
|
headers: {
|
'token': localStorage.getItem('token')
|
},
|
data: {},
|
dataType: 'json',
|
contentType: 'application/json;charset=UTF-8',
|
method: 'post',
|
success: function (res) {
|
that.valueSystem = res.data.status
|
}
|
});
|
},
|
upDateValueSystem(){
|
let that = this;
|
let operatorTypeI = 0;
|
if (that.valueSystem){
|
operatorTypeI = 1;
|
}
|
this.verifyPassword(() => {
|
$.ajax({
|
url: baseUrl + "/console/system/switch",
|
headers: {'token': localStorage.getItem('token')},
|
data: {operatorType : operatorTypeI},
|
method: 'POST',
|
success: function (res) {
|
if (res.code === 200) {
|
that.$message.success(`状态更新成功`);
|
} else {
|
that.$message.error('状态更新失败');
|
}
|
}
|
});
|
});
|
},
|
getTableDataLeft() {
|
let that = this;
|
$.ajax({
|
url: baseUrl + "/rgv/ring/through/task/wrk/mast/position/data",
|
headers: {
|
'token': localStorage.getItem('token')
|
},
|
data: {},
|
dataType: 'json',
|
contentType: 'application/json;charset=UTF-8',
|
method: 'post',
|
success: function (res) {
|
that.tableDataLeft = res.data
|
}
|
});
|
},
|
getTableDataLeft1() {
|
let that = this;
|
$.ajax({
|
url: baseUrl + "/rgv/ring/through/task/wrk/mast/position/data/v1",
|
headers: {
|
'token': localStorage.getItem('token')
|
},
|
data: {},
|
dataType: 'json',
|
contentType: 'application/json;charset=UTF-8',
|
method: 'post',
|
success: function (res) {
|
that.tableDataLeft1 = res.data
|
}
|
});
|
},
|
getTableDataRight() {
|
let that = this;
|
$.ajax({
|
url: baseUrl + "/rgv/task/rgv/circular/shuttle/mast/position/data",
|
headers: {
|
'token': localStorage.getItem('token')
|
},
|
data: {},
|
dataType: 'json',
|
contentType: 'application/json;charset=UTF-8',
|
method: 'post',
|
success: function (res) {
|
that.tableDataRight = res.data
|
}
|
});
|
},
|
getTableDataRight1() {
|
let that = this;
|
$.ajax({
|
url: baseUrl + "/rgv/task/rgv/circular/shuttle/mast/position/data/v1",
|
headers: {
|
'token': localStorage.getItem('token')
|
},
|
data: {},
|
dataType: 'json',
|
contentType: 'application/json;charset=UTF-8',
|
method: 'post',
|
success: function (res) {
|
that.tableDataRight1 = res.data
|
}
|
});
|
},
|
getTableDataRgv() {
|
let that = this;
|
$.ajax({
|
url: baseUrl + "/rgv/ring/through/rgv/position/data",
|
headers: {
|
'token': localStorage.getItem('token')
|
},
|
data: {},
|
dataType: 'json',
|
contentType: 'application/json;charset=UTF-8',
|
method: 'post',
|
success: function (res) {
|
that.tableDataRgv = res.data
|
}
|
});
|
},
|
getTableDataDev() {
|
let that = this;
|
$.ajax({
|
url: baseUrl + "/rgv/ring/through/dev/position/data",
|
headers: {
|
'token': localStorage.getItem('token')
|
},
|
data: {},
|
dataType: 'json',
|
contentType: 'application/json;charset=UTF-8',
|
method: 'post',
|
success: function (res) {
|
that.tableDataDev = res.data
|
}
|
});
|
},
|
getTableDataTrack() {
|
let that = this;
|
$.ajax({
|
url: baseUrl + "/rgv/ring/through/track/position/data",
|
headers: {
|
'token': localStorage.getItem('token')
|
},
|
data: {},
|
dataType: 'json',
|
contentType: 'application/json;charset=UTF-8',
|
method: 'post',
|
success: function (res) {
|
that.energyGatheringRing = res.data
|
}
|
});
|
},
|
// 处理窗口大小变化
|
handleResize: _.debounce(function() {
|
this.updateContainerSize();
|
this.updateBodySize();
|
}, 100)
|
}
|
})
|
|
</script>
|
</body>
|
|
</html>
|