<template>
|
<div class="load-vehicle-config">
|
<el-row :gutter="20">
|
<el-col :span="12">
|
<el-form-item label="车辆容量(mm)">
|
<el-input-number
|
v-model="config.vehicleCapacity"
|
:min="1"
|
:max="10000"
|
:step="100"
|
style="width: 100%;"
|
/>
|
<span class="form-tip">车辆最大容量</span>
|
</el-form-item>
|
</el-col>
|
<el-col :span="12">
|
<el-form-item label="车辆速度(格/秒)">
|
<el-input-number
|
v-model="config.vehicleSpeed"
|
:min="0.1"
|
:max="10"
|
:step="0.1"
|
:precision="1"
|
style="width: 100%;"
|
/>
|
<span class="form-tip">车辆运动速度,默认1格/秒</span>
|
</el-form-item>
|
</el-col>
|
</el-row>
|
|
<el-row :gutter="20">
|
<el-col :span="12">
|
<el-form-item label="玻璃间隔(秒)">
|
<el-input-number
|
v-model="glassIntervalSeconds"
|
:min="0.1"
|
:max="10"
|
:step="0.1"
|
:precision="1"
|
style="width: 100%;"
|
/>
|
<span class="form-tip">玻璃上料间隔时间(秒)</span>
|
</el-form-item>
|
</el-col>
|
<el-col :span="12">
|
<el-form-item label="默认玻璃长度(mm)">
|
<el-input-number
|
v-model="config.defaultGlassLength"
|
:min="100"
|
:max="10000"
|
:step="100"
|
style="width: 100%;"
|
/>
|
<span class="form-tip">当玻璃未提供长度时使用的默认值</span>
|
</el-form-item>
|
</el-col>
|
</el-row>
|
|
<el-row :gutter="20">
|
<el-col :span="12">
|
<el-form-item label="初始位置(格)">
|
<el-input-number
|
v-model="config.homePosition"
|
:min="0"
|
:max="1000"
|
:step="1"
|
style="width: 100%;"
|
/>
|
<span class="form-tip">车辆初始位置(格子)</span>
|
</el-form-item>
|
</el-col>
|
<el-col :span="12">
|
<el-form-item label="运动距离范围">
|
<el-input-number
|
v-model="config.minRange"
|
:min="1"
|
:max="1000"
|
:step="1"
|
style="width: 40%;"
|
placeholder="最小"
|
/>
|
<span style="margin: 0 2%;">~</span>
|
<el-input-number
|
v-model="config.maxRange"
|
:min="1"
|
:max="1000"
|
:step="1"
|
style="width: 40%;"
|
placeholder="最大"
|
/>
|
<span class="form-tip">运动距离范围(格子)</span>
|
</el-form-item>
|
</el-col>
|
</el-row>
|
|
<el-row :gutter="20">
|
<el-col :span="12">
|
<el-form-item label="空闲监控间隔(秒)">
|
<el-input-number
|
v-model="idleMonitorIntervalSeconds"
|
:min="0.5"
|
:max="10"
|
:step="0.1"
|
:precision="1"
|
style="width: 100%;"
|
/>
|
<span class="form-tip">空闲状态监控间隔,默认2秒</span>
|
</el-form-item>
|
</el-col>
|
<el-col :span="12">
|
<el-form-item label="任务监控间隔(秒)">
|
<el-input-number
|
v-model="taskMonitorIntervalSeconds"
|
:min="0.5"
|
:max="10"
|
:step="0.1"
|
:precision="1"
|
style="width: 100%;"
|
/>
|
<span class="form-tip">任务执行监控间隔,默认1秒</span>
|
</el-form-item>
|
</el-col>
|
</el-row>
|
|
<el-row :gutter="20">
|
<el-col :span="12">
|
<el-form-item label="MES确认超时(秒)">
|
<el-input-number
|
v-model="mesConfirmTimeoutSeconds"
|
:min="5"
|
:max="300"
|
:step="1"
|
style="width: 100%;"
|
/>
|
<span class="form-tip">等待MES确认的超时时间,默认30秒</span>
|
</el-form-item>
|
</el-col>
|
<el-col :span="12">
|
<el-form-item label="自动上料">
|
<el-switch v-model="config.autoFeed" />
|
<span class="form-tip">是否自动触发上料请求</span>
|
</el-form-item>
|
</el-col>
|
</el-row>
|
|
<el-row :gutter="20">
|
<el-col :span="12">
|
<el-form-item label="最大重试次数">
|
<el-input-number
|
v-model="config.maxRetryCount"
|
:min="0"
|
:max="10"
|
:step="1"
|
style="width: 100%;"
|
/>
|
</el-form-item>
|
</el-col>
|
</el-row>
|
|
<el-form-item label="位置映射">
|
<div class="position-mapping">
|
<div
|
v-for="(value, key, index) in config.positionMapping"
|
:key="index"
|
class="mapping-item"
|
>
|
<el-input
|
v-model="mappingKeys[index]"
|
placeholder="位置代码(如900/901)"
|
size="small"
|
style="width: 150px; margin-right: 10px;"
|
@input="updatePositionMapping(index, $event, value)"
|
/>
|
<el-input-number
|
v-model="config.positionMapping[mappingKeys[index] || key]"
|
:min="0"
|
:max="1000"
|
:step="1"
|
size="small"
|
style="width: 120px; margin-right: 10px;"
|
placeholder="位置值(格)"
|
/>
|
<el-button
|
type="danger"
|
size="small"
|
@click="removePositionMapping(key)"
|
>
|
删除
|
</el-button>
|
</div>
|
<el-button type="primary" size="small" @click="addPositionMapping">
|
添加位置映射
|
</el-button>
|
</div>
|
<span class="form-tip">将MES编号(如900/901)映射为实际位置值(格子)</span>
|
</el-form-item>
|
</div>
|
</template>
|
|
<script setup>
|
import { ref, watch } from 'vue'
|
|
const props = defineProps({
|
modelValue: {
|
type: Object,
|
default: () => ({})
|
}
|
})
|
|
const emit = defineEmits(['update:modelValue'])
|
|
// 配置数据
|
const config = ref({
|
vehicleCapacity: 6000,
|
vehicleSpeed: 1.0,
|
glassIntervalMs: 1000,
|
defaultGlassLength: 2000,
|
homePosition: 0,
|
minRange: 1,
|
maxRange: 100,
|
idleMonitorIntervalMs: 2000,
|
taskMonitorIntervalMs: 1000,
|
mesConfirmTimeoutMs: 30000,
|
autoFeed: true,
|
maxRetryCount: 5,
|
positionMapping: {}
|
})
|
|
// 位置映射的键数组
|
const mappingKeys = ref([])
|
|
// 时间字段(秒)- 用于前端显示和输入
|
const glassIntervalSeconds = ref(1.0)
|
const idleMonitorIntervalSeconds = ref(2.0)
|
const taskMonitorIntervalSeconds = ref(1.0)
|
const mesConfirmTimeoutSeconds = ref(30)
|
|
// 监听props变化
|
watch(() => props.modelValue, (newVal) => {
|
if (newVal && Object.keys(newVal).length > 0) {
|
config.value = {
|
vehicleCapacity: newVal.vehicleCapacity ?? 6000,
|
vehicleSpeed: newVal.vehicleSpeed ?? 1.0,
|
glassIntervalMs: newVal.glassIntervalMs ?? 1000,
|
defaultGlassLength: newVal.defaultGlassLength ?? 2000,
|
homePosition: newVal.homePosition ?? 0,
|
minRange: newVal.minRange ?? 1,
|
maxRange: newVal.maxRange ?? 100,
|
idleMonitorIntervalMs: newVal.idleMonitorIntervalMs ?? 2000,
|
taskMonitorIntervalMs: newVal.taskMonitorIntervalMs ?? 1000,
|
mesConfirmTimeoutMs: newVal.mesConfirmTimeoutMs ?? 30000,
|
autoFeed: newVal.autoFeed ?? true,
|
maxRetryCount: newVal.maxRetryCount ?? 5,
|
positionMapping: newVal.positionMapping || {}
|
}
|
// 将毫秒转换为秒用于显示
|
glassIntervalSeconds.value = (config.value.glassIntervalMs ?? 1000) / 1000
|
idleMonitorIntervalSeconds.value = (config.value.idleMonitorIntervalMs ?? 2000) / 1000
|
taskMonitorIntervalSeconds.value = (config.value.taskMonitorIntervalMs ?? 1000) / 1000
|
mesConfirmTimeoutSeconds.value = (config.value.mesConfirmTimeoutMs ?? 30000) / 1000
|
mappingKeys.value = Object.keys(config.value.positionMapping)
|
}
|
}, { immediate: true, deep: true })
|
|
// 监听秒字段变化,转换为毫秒并更新config
|
watch(glassIntervalSeconds, (val) => {
|
config.value.glassIntervalMs = Math.round(val * 1000)
|
emit('update:modelValue', { ...config.value })
|
})
|
|
watch(idleMonitorIntervalSeconds, (val) => {
|
config.value.idleMonitorIntervalMs = Math.round(val * 1000)
|
emit('update:modelValue', { ...config.value })
|
})
|
|
watch(taskMonitorIntervalSeconds, (val) => {
|
config.value.taskMonitorIntervalMs = Math.round(val * 1000)
|
emit('update:modelValue', { ...config.value })
|
})
|
|
watch(mesConfirmTimeoutSeconds, (val) => {
|
config.value.mesConfirmTimeoutMs = Math.round(val * 1000)
|
emit('update:modelValue', { ...config.value })
|
})
|
|
// 监听config其他字段变化,同步到父组件
|
watch(() => [
|
config.value.vehicleCapacity,
|
config.value.vehicleSpeed,
|
config.value.defaultGlassLength,
|
config.value.homePosition,
|
config.value.minRange,
|
config.value.maxRange,
|
config.value.autoFeed,
|
config.value.maxRetryCount,
|
config.value.positionMapping
|
], () => {
|
emit('update:modelValue', { ...config.value })
|
}, { deep: true })
|
|
// 位置映射相关方法
|
const addPositionMapping = () => {
|
const newKey = `POS${Object.keys(config.value.positionMapping).length + 1}`
|
config.value.positionMapping[newKey] = 1
|
mappingKeys.value.push(newKey)
|
}
|
|
const removePositionMapping = (key) => {
|
delete config.value.positionMapping[key]
|
mappingKeys.value = mappingKeys.value.filter(k => k !== key)
|
}
|
|
const updatePositionMapping = (index, newKey, oldValue) => {
|
const oldKey = mappingKeys.value[index]
|
if (oldKey && oldKey !== newKey) {
|
delete config.value.positionMapping[oldKey]
|
}
|
mappingKeys.value[index] = newKey
|
if (newKey) {
|
config.value.positionMapping[newKey] = oldValue || 1
|
}
|
}
|
</script>
|
|
<style scoped>
|
.form-tip {
|
margin-left: 10px;
|
font-size: 12px;
|
color: #909399;
|
}
|
|
.position-mapping {
|
width: 100%;
|
}
|
|
.mapping-item {
|
display: flex;
|
align-items: center;
|
margin-bottom: 12px;
|
padding: 12px;
|
border: 1px solid #ebeef5;
|
border-radius: 6px;
|
background-color: #fafafa;
|
}
|
</style>
|