Files
lanzhouhailiang_one/acs2/nladmin-ui/src/views/screen/twoFloorAgvScreen.vue

396 lines
10 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div class="two-floor-agv-screen">
<div class="header">
<h1>二楼AGV监控看板</h1>
<div class="time-info">
<span>{{ getTime }}</span>
<span>{{ getDate }}</span>
</div>
</div>
<div class="agv-list">
<div
v-for="agv in agvList"
:key="agv.vehicle_code"
class="agv-item"
:class="{ 'agv-error': agv.is_error }"
@click="showAgvDetail(agv)"
>
<div class="agv-header">
<div class="agv-basic-info">
<h3>{{ agv.vehicle_code }}</h3>
<span class="status" :class="agv.status">{{ agv.status_text }}</span>
</div>
<div class="agv-phase">
<span class="label">当前阶段</span>
<span class="phase-value">{{ agv.phase_name || '无' }}</span>
</div>
</div>
<div class="agv-task-info">
<div class="task-item">
<span class="label">任务代码</span>
<span>{{ agv.task_code || '无' }}</span>
</div>
<div class="task-item">
<span class="label">指令代码</span>
<span>{{ agv.inst_code || '无' }}</span>
</div>
<div class="task-item">
<span class="label">当前位置</span>
<span>{{ agv.address || '未知' }}</span>
</div>
</div>
<div v-if="agv.is_error" class="agv-error-info">
<h4>任务卡住原因</h4>
<div v-if="agv.error_action" class="error-item">
<span class="label">Action不满足</span>
<span>{{ agv.error_action }}</span>
</div>
<div v-if="agv.error_mode" class="error-item">
<span class="label">Mode不满足</span>
<span>{{ agv.error_mode }}</span>
</div>
<div v-if="agv.error_error" class="error-item">
<span class="label">Error不满足</span>
<span>{{ agv.error_error }}</span>
</div>
<div v-if="agv.error_move" class="error-item">
<span class="label">Move不满足</span>
<span>{{ agv.error_move }}</span>
</div>
<div v-if="agv.error_message" class="error-item">
<span class="label">错误信息</span>
<span>{{ agv.error_message }}</span>
</div>
</div>
<div v-else-if="agv.phase_name" class="agv-normal-info">
<h4>当前任务进度</h4>
<div v-for="(step, index) in agv.phase_steps" :key="index" class="progress-item">
<span class="step-name">{{ step.name }}</span>
<el-progress
:percentage="step.completed ? 100 : 0"
:color="step.completed ? '#67C23A' : '#E6A23C'"
:stroke-width="6"
/>
</div>
</div>
</div>
</div>
<!-- AGV详情弹窗 -->
<el-dialog
title="AGV详情"
:visible.sync="dialogVisible"
width="50%"
>
<div v-if="currentAgv" class="agv-detail">
<el-descriptions :column="1" border>
<el-descriptions-item label="AGV编号">{{ currentAgv.vehicle_code }}</el-descriptions-item>
<el-descriptions-item label="当前状态">{{ currentAgv.status_text }}</el-descriptions-item>
<el-descriptions-item label="当前阶段">{{ currentAgv.phase_name || '无' }}</el-descriptions-item>
<el-descriptions-item label="任务代码">{{ currentAgv.task_code || '无' }}</el-descriptions-item>
<el-descriptions-item label="指令代码">{{ currentAgv.inst_code || '无' }}</el-descriptions-item>
<el-descriptions-item label="当前位置">{{ currentAgv.address || '未知' }}</el-descriptions-item>
<el-descriptions-item v-if="currentAgv.is_error" label="错误信息">
<div v-if="currentAgv.error_action">Action不满足{{ currentAgv.error_action }}</div>
<div v-if="currentAgv.error_mode">Mode不满足{{ currentAgv.error_mode }}</div>
<div v-if="currentAgv.error_action">Move不满足{{ currentAgv.error_move }}</div>
<div v-if="currentAgv.error_error">Error不满足{{ currentAgv.error_error }}</div>
<div v-if="currentAgv.error_message">{{ currentAgv.error_message }}</div>
</el-descriptions-item>
</el-descriptions>
</div>
</el-dialog>
</div>
</template>
<script>
import Background from '@/assets/images/bigScreen.png'
export default {
data() {
return {
Background: Background,
agvList: [
{ vehicle_code: 'AGV01', status: 'running', status_text: '运行中', is_error: false },
{ vehicle_code: 'AGV02', status: 'idle', status_text: '空闲', is_error: false },
{ vehicle_code: 'AGV03', status: 'error', status_text: '异常', is_error: true },
{ vehicle_code: 'AGV04', status: 'charging', status_text: '充电中', is_error: false }
],
getTime: '',
getDate: '',
dialogVisible: false,
currentAgv: null
}
},
mounted() {
this.init()
// 定时器,每秒更新一次数据
const timer = setInterval(() => {
this.settime()
this.getMessage()
}, 1000)
// 销毁定时器
this.$once('hook:beforeDestroy', () => {
clearInterval(timer)
})
},
methods: {
init() {
// 初始化数据
this.settime()
// 获取AGV状态数据
this.getMessage()
},
settime() {
const yy = new Date().getFullYear()
const mm = new Date().getMonth() + 1
const dd = new Date().getDate()
const hh = new Date().getHours()
const mf = new Date().getMinutes() < 10 ? '0' + new Date().getMinutes() : new Date().getMinutes()
const ss = new Date().getSeconds() < 10 ? '0' + new Date().getSeconds() : new Date().getSeconds()
this.getDate = yy + '年' + mm + '月' + dd + '日 ' + '星期' + '日一二三四五六'.charAt(new Date().getDay())
this.getTime = hh + ':' + mf + ':' + ss
},
getMessage() {
// 通过HTTP接口获取AGV状态数据
this.$axios.get('/api/agv/two-floor/status')
.then(response => {
if (response) {
this.updateAgvData(response)
}
})
.catch(error => {
console.error('获取AGV状态数据失败:', error)
})
},
updateAgvData(agvDataList) {
// 更新AGV数据
agvDataList.forEach(data => {
const agvIndex = this.agvList.findIndex(agv => agv.vehicle_code === data.vehicle_code)
if (agvIndex !== -1) {
// 处理AGV状态
const statusMap = {
'running': { text: '运行中', class: 'running' },
'idle': { text: '空闲', class: 'idle' },
'error': { text: '异常', class: 'error' },
'charging': { text: '充电中', class: 'charging' }
}
// 根据数据状态判断AGV是否处于错误状态
const isError = !!(data.is_error || (data.error_action || data.error_mode || data.error_error || data.error_move || data.error_message))
// 设置状态信息
const statusInfo = statusMap[data.status] || { text: '未知', class: 'unknown' }
if (isError) {
statusInfo.text = '异常'
statusInfo.class = 'error'
}
// 更新AGV数据
this.agvList[agvIndex] = {
...this.agvList[agvIndex],
...data,
status_text: statusInfo.text,
status: statusInfo.class,
is_error: isError,
phase_name: data.phase_name,
error_action: data.error_action,
error_mode: data.error_mode,
error_move: data.error_move,
error_error: data.error_error,
error_message: data.error_message
}
}
})
},
showAgvDetail(agv) {
this.currentAgv = agv
this.dialogVisible = true
}
}
}
</script>
<style scoped>
.two-floor-agv-screen {
width: 100%;
height: 100vh;
background-color: #f0f2f5;
font-family: Arial, sans-serif;
overflow: auto;
}
.header {
background-color: #2c3e50;
color: white;
padding: 20px;
display: flex;
justify-content: space-between;
align-items: center;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
}
.header h1 {
margin: 0;
font-size: 28px;
}
.time-info {
text-align: right;
}
.time-info span {
display: block;
margin: 5px 0;
}
.agv-list {
padding: 20px;
display: grid;
grid-template-columns: repeat(auto-fit, minmax(400px, 1fr));
gap: 20px;
}
.agv-item {
background-color: white;
border-radius: 8px;
padding: 20px;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
cursor: pointer;
transition: all 0.3s ease;
border-left: 5px solid #409eff;
}
.agv-item:hover {
transform: translateY(-5px);
box-shadow: 0 5px 20px rgba(0, 0, 0, 0.15);
}
.agv-item.agv-error {
border-left-color: #f56c6c;
}
.agv-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 15px;
padding-bottom: 10px;
border-bottom: 1px solid #eee;
}
.agv-basic-info h3 {
margin: 0;
font-size: 20px;
color: #333;
}
.status {
display: inline-block;
padding: 4px 12px;
border-radius: 12px;
font-size: 12px;
font-weight: bold;
margin-left: 10px;
}
.status.running {
background-color: #67c23a;
color: white;
}
.status.idle {
background-color: #909399;
color: white;
}
.status.error {
background-color: #f56c6c;
color: white;
}
.status.charging {
background-color: #e6a23c;
color: white;
}
.status.unknown {
background-color: #909399;
color: white;
}
.agv-phase {
text-align: right;
}
.label {
font-weight: bold;
color: #666;
margin-right: 5px;
}
.phase-value {
font-size: 16px;
color: #409eff;
font-weight: bold;
}
.agv-task-info {
margin-bottom: 15px;
}
.task-item {
margin: 8px 0;
font-size: 14px;
}
.agv-error-info {
background-color: #fef0f0;
border: 1px solid #fbc4ab;
border-radius: 4px;
padding: 15px;
margin-top: 15px;
}
.agv-error-info h4 {
margin-top: 0;
color: #f56c6c;
font-size: 16px;
}
.error-item {
margin: 8px 0;
font-size: 14px;
}
.agv-normal-info {
margin-top: 15px;
}
.agv-normal-info h4 {
margin-top: 0;
color: #67c23a;
font-size: 16px;
}
.progress-item {
margin: 10px 0;
}
.step-name {
display: block;
margin-bottom: 5px;
font-size: 14px;
color: #666;
}
.agv-detail {
padding: 10px 0;
}
</style>