feat: 增加AGV任务管理并完善磨合管理

This commit is contained in:
XingCheng3
2026-07-16 16:45:57 +08:00
parent f477d03f58
commit 8f1d585592
5 changed files with 1961 additions and 25 deletions

BIN
dist.zip

Binary file not shown.

View File

@@ -1,18 +0,0 @@
模块介绍
用于 处理各工位生产过程中 出现的异常情况(如 进站失败重试 出站失败重试) 开放功能重试按钮、查看工位产品信息、加工状态、可以看工位当前产品 过站情况 等
功能需求
1.首先进入页面仍然需要刷卡弹窗进行登陆 登陆后 首先拉出工位当前在位产品信息 然后是 显示三个重试按钮
2.三个重试按钮 分别是 (进站重试、出站重试、申请条码) 分别对应后端三个接口 (接口地址 仍然是 window.g.API_MES_Controller_URL + /url
4.显示一块区域 或者 点按钮显示一个弹窗看情况和UI自由发挥 就可以拉出 该产品 各工位接口执行情况Moby数据 用户可以查看前面各工位接口执行情况
5.存储过程相关你需要先调用 SqlServerMCP 去查看存储过程定义以及参数 还有返回结果后再进行开发
6.界面要适配 竖屏PAD 因为会在竖屏Pad上进行使用 要界面友好
7.我发现 刷卡登陆弹窗在竖屏Pad上会出现 弹窗宽度不宽 但是 输入框超出了弹窗范围
资源位置
1.这个页面文件是 (D:\项目文件\52.智柔PDC线\前端\MES_ApiFailRetry\src\views\OpStatus.vue)
2.重试接口程序位置 可查看重试接口参数 (D:\项目文件\52.智柔PDC线\程序\MesProject_2025.09.161105\MisDataFun\MisDataFun\webApi\WebSendServer.cs 的 ApiFailRetry 方法)
3.刷卡登陆功能参考 和 工位列表获取参考 (D:\项目文件\52.智柔PDC线\前端\MES_ApiFailRetry\src\views\index.vue)
4.工位状态存储过程 PAD_工位状态_查询 切换选择工位时调用 进入页面默认选择第一个工位 其中 状态 1 已进站 2 已完成 其他都是未进站
5.工位产品 接口调用情况查询存储过程 PAD_工位状态_产品接口Moby_查询 其中请求内容列是个多行文本 这个如果要看可以是单独弹窗或者单独区域显示(你看怎么合适怎么来)

File diff suppressed because it is too large Load Diff

View File

@@ -4,7 +4,7 @@ import {ElMessage} from 'element-plus' // 引入Element Plus的消息提示组
const name_config = `OP8888` const name_config = `OP8888`
// import.meta.env.VITE_BASE_URL // import.meta.env.VITE_BASE_URL
console.log(window.g) console.log(window.g)
const request_config = window.g.API_WEB_URL + `/submit/MESCommonBase.ashx` const request_config = window.g.API_WEB_URL
export const name = name_config export const name = name_config
const service = axios.create({ const service = axios.create({
baseURL: request_config, baseURL: request_config,

View File

@@ -1,4 +1,10 @@
<template> <template>
<div class="management-page">
<el-tabs v-model="activeTab" class="management-tabs">
<el-tab-pane label="AGV任务" name="agv">
<AgvTaskManagement v-if="activeTab === 'agv'" />
</el-tab-pane>
<el-tab-pane label="库位监控" name="slots">
<div class="running-in-page"> <div class="running-in-page">
<!-- 顶部标题栏 --> <!-- 顶部标题栏 -->
<div class="page-header"> <div class="page-header">
@@ -151,6 +157,22 @@
> >
AGV离开 AGV离开
</el-button> </el-button>
<el-button
type="info"
size="large"
:loading="toggleCallLoading"
@click="handleToggleCall"
>
{{ selectedSlot?.是否呼叫 ? '取消呼叫' : '设为呼叫' }}
</el-button>
<el-button
type="danger"
size="large"
:loading="clearSlotLoading"
@click="handleClearSlot"
>
清空库位数据
</el-button>
</div> </div>
</div> </div>
</el-dialog> </el-dialog>
@@ -222,15 +244,20 @@
</template> </template>
</el-dialog> </el-dialog>
</div> </div>
</el-tab-pane>
</el-tabs>
</div>
</template> </template>
<script setup> <script setup>
import { ref, computed, onMounted, onUnmounted, getCurrentInstance, inject } from 'vue' import { ref, computed, onMounted, onUnmounted, getCurrentInstance, inject, watch } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus' import { ElMessage, ElMessageBox } from 'element-plus'
import { Refresh, Right } from '@element-plus/icons-vue' import { Refresh, Right } from '@element-plus/icons-vue'
import AgvTaskManagement from '@/components/AgvTaskManagement.vue'
const { proxy } = getCurrentInstance() const { proxy } = getCurrentInstance()
const ExecHttpRequest = inject('ExecHttpRequest') const ExecHttpRequest = inject('ExecHttpRequest')
const activeTab = ref('agv')
// 数据 // 数据
const loading = ref(false) const loading = ref(false)
@@ -249,6 +276,11 @@ const confirmTransferLoading = ref(false)
const agvArriveLoading = ref(false) const agvArriveLoading = ref(false)
const agvLeaveLoading = ref(false) const agvLeaveLoading = ref(false)
// 库位运维操作
const toggleCallLoading = ref(false)
const clearSlotLoading = ref(false)
const OPERATOR = '磨合系统'
// PLC相关 // PLC相关
const plcConfigList = window.g.showPosList || [] const plcConfigList = window.g.showPosList || []
const plcValues = ref({}) // 存储点位值 Key=TagCode, Value=0/1 const plcValues = ref({}) // 存储点位值 Key=TagCode, Value=0/1
@@ -326,7 +358,6 @@ const handleSlotClick = (slot) => {
} }
// 监听弹窗打开关闭控制PLC轮询 // 监听弹窗打开关闭控制PLC轮询
import { watch } from 'vue'
watch(dialogVisible, (val) => { watch(dialogVisible, (val) => {
if (val) { if (val) {
fetchPLCValues() fetchPLCValues()
@@ -621,9 +652,100 @@ const handleAGVLeave = async () => {
} }
} }
// 切换是否呼叫
const handleToggleCall = async () => {
if (!selectedSlot.value) return
const targetText = selectedSlot.value.是否呼叫 ? '取消呼叫' : '设为呼叫'
try {
await ElMessageBox.confirm(
`确认将库位 ${selectedSlot.value.库位号} ${targetText}?此操作会写入系统日志。`,
'确认',
{ confirmButtonText: '确认', cancelButtonText: '取消', type: 'warning' }
)
} catch {
return
}
toggleCallLoading.value = true
try {
const param = [
['库位号', selectedSlot.value.库位号],
['操作人', OPERATOR]
]
const data = proxy.CreateData('11', 'XD_磨合_状态_是否呼叫_切换', param)
const res = await proxy.ExecDatabase(data)
const row = res.data && res.data[0] ? res.data[0] : {}
if (row.result === 1) {
ElMessage.success(`${targetText}成功`)
selectedSlot.value.是否呼叫 = Number(row.是否呼叫) || 0
loadData(false)
} else {
ElMessage.error(row.msg || `${targetText}失败`)
}
} catch (err) {
console.error('切换呼叫状态失败:', err)
ElMessage.error('切换呼叫状态异常')
} finally {
toggleCallLoading.value = false
}
}
// 清空库位数据
const handleClearSlot = async () => {
if (!selectedSlot.value) return
try {
await ElMessageBox.confirm(
`确认清空库位 ${selectedSlot.value.库位号} 的产品/工序/状态数据?此操作会写入系统日志,且不可撤销。`,
'危险操作',
{ confirmButtonText: '确认清空', cancelButtonText: '取消', type: 'error' }
)
} catch {
return
}
clearSlotLoading.value = true
try {
const param = [
['库位号', selectedSlot.value.库位号],
['操作人', OPERATOR]
]
const data = proxy.CreateData('11', 'XD_磨合_状态_清空', param)
const res = await proxy.ExecDatabase(data)
const row = res.data && res.data[0] ? res.data[0] : {}
if (row.result === 1) {
ElMessage.success('库位数据已清空')
dialogVisible.value = false
loadData()
} else {
ElMessage.error(row.msg || '清空库位数据失败')
}
} catch (err) {
console.error('清空库位数据失败:', err)
ElMessage.error('清空库位数据异常')
} finally {
clearSlotLoading.value = false
}
}
onMounted(() => { onMounted(() => {
if (activeTab.value === 'slots') {
loadData() loadData()
startAutoRefresh() startAutoRefresh()
}
})
watch(activeTab, value => {
if (value === 'slots') {
loadData()
startAutoRefresh()
} else {
dialogVisible.value = false
stopAutoRefresh()
}
}) })
onUnmounted(() => { onUnmounted(() => {
@@ -632,9 +754,33 @@ onUnmounted(() => {
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.running-in-page { .management-page {
min-height: 100vh; min-height: 100vh;
background: #e8eaed; background: #e8eaed;
}
.management-tabs {
:deep(.el-tabs__header) {
padding: 0 18px;
margin: 0;
background: #fff;
border-bottom: 1px solid #dcdfe6;
}
:deep(.el-tabs__item) {
height: 52px;
font-size: 15px;
letter-spacing: 0;
}
:deep(.el-tabs__content) {
overflow: visible;
}
}
.running-in-page {
min-height: calc(100vh - 52px);
background: #e8eaed;
color: #1a1a1a; color: #1a1a1a;
padding: 16px; padding: 16px;
box-sizing: border-box; box-sizing: border-box;