huang
2025-11-25 19f59c243e8df97c8b9fd9dba4e758be8235d68b
mes-web/src/views/plcTest/components/MultiDeviceTest/TaskOrchestration.vue
@@ -5,7 +5,7 @@
        <h3>多设备测试编排</h3>
        <p v-if="group">当前设备组:{{ group.groupName }}({{ group.deviceCount || '-' }} 台设备)</p>
        <p v-else class="warning">请先在左侧选择一个设备组</p>
        <p v-if="group && loadDeviceName" class="sub-info">上大车设备:{{ loadDeviceName }}</p>
        <p v-if="group && loadDeviceName" class="sub-info">当前设备:{{ loadDeviceName }}</p>
      </div>
      <div class="action-buttons">
        <el-button
@@ -25,23 +25,94 @@
      </div>
    </div>
    <el-form :model="form" label-width="120px">
      <el-form-item label="玻璃ID列表">
    <el-form :model="form" label-width="120px" :rules="rules" ref="formRef">
      <el-form-item label="玻璃ID列表" prop="glassIds" required>
        <el-input
          v-model="glassIdsInput"
          type="textarea"
          :rows="4"
          placeholder="请输入玻璃条码,支持多行或逗号分隔"
          placeholder="请输入玻璃条码,支持多行或逗号分隔,每行一个或逗号分隔"
          show-word-limit
          :maxlength="5000"
        />
        <div class="form-tip">
          已输入 {{ glassIds.length }} 个玻璃ID
        </div>
      </el-form-item>
      <el-divider content-position="left">设备特定配置</el-divider>
      <el-form-item label="位置编码">
        <el-input v-model="form.positionCode" placeholder="例如:POS1" />
        <el-input
          v-model="form.positionCode"
          placeholder="例如:POS1"
          clearable
        />
        <div class="form-tip">上大车设备的位置编码</div>
      </el-form-item>
      <el-form-item label="位置值">
        <el-input-number
          v-model="form.positionValue"
          :min="0"
          :max="9999"
          placeholder="位置数值"
        />
        <div class="form-tip">上大车设备的位置数值</div>
      </el-form-item>
      <el-form-item label="存储位置">
        <el-input-number v-model="form.storagePosition" :min="1" :max="200" />
        <el-input-number
          v-model="form.storagePosition"
          :min="1"
          :max="200"
          placeholder="存储位置编号"
        />
        <div class="form-tip">玻璃存储设备的存储位置</div>
      </el-form-item>
      <el-form-item label="处理类型">
        <el-select v-model="form.processType" placeholder="选择处理类型" clearable>
          <el-option label="标准处理" :value="1" />
          <el-option label="快速处理" :value="2" />
          <el-option label="慢速处理" :value="3" />
        </el-select>
        <div class="form-tip">大理片设备的处理类型</div>
      </el-form-item>
      <el-divider content-position="left">执行配置</el-divider>
      <el-form-item label="执行间隔 (ms)">
        <el-input-number v-model="form.executionInterval" :min="100" :max="10000" />
        <el-input-number
          v-model="form.executionInterval"
          :min="100"
          :max="10000"
          :step="100"
          placeholder="设备操作间隔时间"
        />
        <div class="form-tip">每个设备操作之间的间隔时间(毫秒)</div>
      </el-form-item>
      <el-form-item label="超时时间 (分钟)">
        <el-input-number
          v-model="form.timeoutMinutes"
          :min="1"
          :max="60"
          :step="1"
          placeholder="任务超时时间"
        />
        <div class="form-tip">任务执行的最大超时时间</div>
      </el-form-item>
      <el-form-item label="重试次数">
        <el-input-number
          v-model="form.retryCount"
          :min="0"
          :max="10"
          :step="1"
          placeholder="失败重试次数"
        />
        <div class="form-tip">设备操作失败时的最大重试次数</div>
      </el-form-item>
    </el-form>
  </div>
@@ -65,9 +136,41 @@
const form = reactive({
  positionCode: '',
  positionValue: null,
  storagePosition: null,
  executionInterval: 1000
  processType: null,
  executionInterval: 1000,
  timeoutMinutes: 30,
  retryCount: 3
})
const formRef = ref(null)
const rules = {
  glassIds: [
    {
      validator: (rule, value, callback) => {
        if (glassIds.value.length === 0) {
          callback(new Error('请至少输入一个玻璃ID'))
        } else if (glassIds.value.length > 100) {
          callback(new Error('玻璃ID数量不能超过100个'))
        } else {
          // 验证玻璃ID格式
          const invalidIds = glassIds.value.filter(id => {
            // 简单的格式验证:不能为空,长度在1-50之间
            return !id || id.length === 0 || id.length > 50
          })
          if (invalidIds.length > 0) {
            callback(new Error(`存在无效的玻璃ID格式,请检查`))
          } else {
            callback()
          }
        }
      },
      trigger: 'blur'
    }
  ]
}
const glassIdsInput = ref('')
const loading = ref(false)
@@ -133,23 +236,78 @@
    ElMessage.warning('请先选择设备组')
    return
  }
  // 表单验证
  if (!formRef.value) return
  try {
    await formRef.value.validate()
  } catch (error) {
    ElMessage.warning('请检查表单输入')
    return
  }
  if (glassIds.value.length === 0) {
    ElMessage.warning('请至少输入一个玻璃ID')
    return
  }
  try {
    loading.value = true
    await multiDeviceTaskApi.startTask({
    // 构建任务参数
    const parameters = {
      glassIds: glassIds.value,
      executionInterval: form.executionInterval || 1000
    }
    // 添加可选参数
    if (form.positionCode) {
      parameters.positionCode = form.positionCode
    }
    if (form.positionValue !== null) {
      parameters.positionValue = form.positionValue
    }
    if (form.storagePosition !== null) {
      parameters.storagePosition = form.storagePosition
    }
    if (form.processType !== null) {
      parameters.processType = form.processType
    }
    if (form.timeoutMinutes) {
      parameters.timeoutMinutes = form.timeoutMinutes
    }
    if (form.retryCount !== null) {
      parameters.retryCount = form.retryCount
    }
    // 异步启动任务,立即返回,不阻塞
    const response = await multiDeviceTaskApi.startTask({
      groupId: props.group.id || props.group.groupId,
      parameters: {
        glassIds: glassIds.value,
        positionCode: form.positionCode || null,
        storagePosition: form.storagePosition,
        executionInterval: form.executionInterval
      }
      parameters
    })
    ElMessage.success('任务已启动')
    emit('task-started')
    const task = response?.data
    if (task && task.taskId) {
      ElMessage.success(`任务已启动(异步执行): ${task.taskId}`)
      emit('task-started', task)
      // 立即刷新监控列表,显示新启动的任务
      setTimeout(() => {
        emit('task-started')
      }, 500)
      // 重置表单(保留部分配置),方便继续启动其他设备组
      glassIdsInput.value = ''
      form.positionCode = ''
      form.positionValue = null
      form.storagePosition = null
      form.processType = null
      // 提示用户可以继续启动其他设备组
      ElMessage.info('可以继续选择其他设备组启动测试,多个设备组将并行执行')
    } else {
      ElMessage.warning('任务启动响应异常')
    }
  } catch (error) {
    ElMessage.error(error?.message || '任务启动失败')
  } finally {
@@ -234,5 +392,12 @@
  gap: 12px;
  align-items: center;
}
.form-tip {
  font-size: 12px;
  color: #909399;
  margin-top: 4px;
  line-height: 1.4;
}
</style>