huang
2025-12-01 dad0263459b30dbfa75f06dff062a0c85183517b
mes-web/src/views/device/components/DeviceLogicConfig/LoadVehicleConfig.vue
@@ -9,6 +9,7 @@
            :max="10000"
            :step="100"
            style="width: 100%;"
            @change="emitConfigUpdate"
          />
          <span class="form-tip">车辆最大容量</span>
        </el-form-item>
@@ -22,6 +23,7 @@
            :step="0.1"
            :precision="1"
            style="width: 100%;"
            @change="emitConfigUpdate"
          />
          <span class="form-tip">车辆运动速度,默认1格/秒</span>
        </el-form-item>
@@ -50,6 +52,7 @@
            :max="10000"
            :step="100"
            style="width: 100%;"
            @change="emitConfigUpdate"
          />
          <span class="form-tip">当玻璃未提供长度时使用的默认值</span>
        </el-form-item>
@@ -65,6 +68,7 @@
            :max="1000"
            :step="1"
            style="width: 100%;"
            @change="emitConfigUpdate"
          />
          <span class="form-tip">车辆初始位置(格子)</span>
        </el-form-item>
@@ -78,6 +82,7 @@
            :step="1"
            style="width: 40%;"
            placeholder="最小"
            @change="emitConfigUpdate"
          />
          <span style="margin: 0 2%;">~</span>
          <el-input-number
@@ -87,6 +92,7 @@
            :step="1"
            style="width: 40%;"
            placeholder="最大"
            @change="emitConfigUpdate"
          />
          <span class="form-tip">运动距离范围(格子)</span>
        </el-form-item>
@@ -137,7 +143,7 @@
      </el-col>
      <el-col :span="12">
        <el-form-item label="自动上料">
          <el-switch v-model="config.autoFeed" />
          <el-switch v-model="config.autoFeed" @change="emitConfigUpdate" />
          <span class="form-tip">是否自动触发上料请求</span>
        </el-form-item>
      </el-col>
@@ -152,6 +158,7 @@
            :max="10"
            :step="1"
            style="width: 100%;"
            @change="emitConfigUpdate"
          />
        </el-form-item>
      </el-col>
@@ -160,30 +167,31 @@
    <el-form-item label="位置映射">
      <div class="position-mapping">
        <div
          v-for="(value, key, index) in config.positionMapping"
          :key="index"
          v-for="(item, index) in positionList"
          :key="item.id"
          class="mapping-item"
        >
          <el-input
            v-model="mappingKeys[index]"
            v-model="item.key"
            placeholder="位置代码(如900/901)"
            size="small"
            style="width: 150px; margin-right: 10px;"
            @input="updatePositionMapping(index, $event, value)"
            @change="handlePositionKeyChange(index)"
          />
          <el-input-number
            v-model="config.positionMapping[mappingKeys[index] || key]"
            v-model="item.value"
            :min="0"
            :max="1000"
            :step="1"
            size="small"
            style="width: 120px; margin-right: 10px;"
            placeholder="位置值(格)"
            @change="handlePositionValueChange(index)"
          />
          <el-button
            type="danger"
            size="small"
            @click="removePositionMapping(key)"
            @click="removePositionMapping(index)"
          >
            删除
          </el-button>
@@ -226,8 +234,40 @@
  positionMapping: {}
})
// 位置映射的键数组
const mappingKeys = ref([])
// 位置映射编辑列表
const positionList = ref([])
let suppressPositionSync = false
let suppressEmit = false
const emitConfigUpdate = () => {
  if (suppressEmit) return
  emit('update:modelValue', { ...config.value })
}
const syncPositionListFromConfig = () => {
  suppressPositionSync = true
  const entries = Object.entries(config.value.positionMapping || {})
  positionList.value = entries.map(([key, value], idx) => ({
    id: `${key}_${idx}_${Date.now()}`,
    key,
    value: value ?? 1
  }))
  suppressPositionSync = false
}
const applyPositionListToConfig = () => {
  if (suppressPositionSync) return
  const mapping = {}
  positionList.value.forEach((item) => {
    if (item.key && item.key.trim()) {
      mapping[item.key.trim()] = item.value ?? 1
    }
  })
  config.value.positionMapping = mapping
  emitConfigUpdate()
}
syncPositionListFromConfig()
// 时间字段(秒)- 用于前端显示和输入
const glassIntervalSeconds = ref(1.0)
@@ -238,6 +278,7 @@
// 监听props变化
watch(() => props.modelValue, (newVal) => {
  if (newVal && Object.keys(newVal).length > 0) {
    suppressEmit = true
    config.value = {
      vehicleCapacity: newVal.vehicleCapacity ?? 6000,
      vehicleSpeed: newVal.vehicleSpeed ?? 1.0,
@@ -258,67 +299,54 @@
    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)
    syncPositionListFromConfig()
    suppressEmit = false
  }
}, { immediate: true, deep: true })
// 监听秒字段变化,转换为毫秒并更新config
watch(glassIntervalSeconds, (val) => {
  config.value.glassIntervalMs = Math.round(val * 1000)
  emit('update:modelValue', { ...config.value })
  emitConfigUpdate()
})
watch(idleMonitorIntervalSeconds, (val) => {
  config.value.idleMonitorIntervalMs = Math.round(val * 1000)
  emit('update:modelValue', { ...config.value })
  emitConfigUpdate()
})
watch(taskMonitorIntervalSeconds, (val) => {
  config.value.taskMonitorIntervalMs = Math.round(val * 1000)
  emit('update:modelValue', { ...config.value })
  emitConfigUpdate()
})
watch(mesConfirmTimeoutSeconds, (val) => {
  config.value.mesConfirmTimeoutMs = Math.round(val * 1000)
  emit('update:modelValue', { ...config.value })
  emitConfigUpdate()
})
// 监听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 nextIndex = positionList.value.length + 1
  positionList.value.push({
    id: `POS_${Date.now()}_${nextIndex}`,
    key: '',
    value: 1
  })
}
const removePositionMapping = (key) => {
  delete config.value.positionMapping[key]
  mappingKeys.value = mappingKeys.value.filter(k => k !== key)
const removePositionMapping = (idx) => {
  positionList.value.splice(idx, 1)
  applyPositionListToConfig()
}
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
  }
const handlePositionKeyChange = () => {
  applyPositionListToConfig()
}
const handlePositionValueChange = () => {
  applyPositionListToConfig()
}
</script>