src/views/productionManagement/processRoute/processRouteItem/index.vue
@@ -179,18 +179,27 @@
          </el-select>
        </el-form-item>
        <el-form-item label="产品名称" prop="productModelId">
        <el-form-item label="产品名称" prop="selectedProducts">
          <el-button type="primary" @click="showProductSelectDialog = true">
            {{ form.productName && form.model
              ? `${form.productName} - ${form.model}`
              : '选择产品' }}
            {{ form.selectedProducts.length ? '重新选择产品' : '选择产品' }}
          </el-button>
          <div v-if="form.selectedProducts.length" class="selected-product-tags">
            <el-tag
              v-for="product in form.selectedProducts"
              :key="product.id"
              class="selected-product-tag"
              type="info"
              effect="plain"
            >
              {{ product.productName }} - {{ product.model }}
            </el-tag>
          </div>
        </el-form-item>
        <el-form-item label="单位" prop="unit">
          <el-input 
              v-model="form.unit" 
              :placeholder="form.productModelId ? '根据选择的产品自动带出' : '请先选择产品'"
              :placeholder="form.selectedProducts.length === 1 ? '根据选择的产品自动带出' : '多个产品时不展示单个单位'"
              clearable 
              :disabled="true" 
          />
@@ -211,7 +220,6 @@
    <ProductSelectDialog
        v-model="showProductSelectDialog"
        @confirm="handleProductSelect"
        single
    />
  </div>
</template>
@@ -269,6 +277,8 @@
  routeId: routeId.value,
  processId: undefined,
  productModelId: undefined,
  productModelIds: "",
  selectedProducts: [],
  productName: "",
  model: "",
  unit: "",
@@ -277,94 +287,118 @@
const rules = {
  processId: [{ required: true, message: '请选择工序', trigger: 'change' }],
  productModelId: [{ required: true, message: '请选择产品', trigger: 'change' }],
  selectedProducts: [{
    required: true,
    validator: (_, value, callback) => {
      if (Array.isArray(value) && value.length > 0) {
        callback();
        return;
      }
      callback(new Error('请选择产品'));
    },
    trigger: 'change',
  }],
};
// 根据工序ID获取工序名称
const getProcessName = (processId) => {
  if (!processId) return '';
  const process = processOptions.value.find(p => p.id === processId);
  const process = processOptions.value.find((p) => p.id === processId);
  return process ? process.name : '';
};
// 获取列表
const getList = () => {
  tableLoading.value = true;
  const listPromise =
    pageType.value === "order"
    pageType.value === 'order'
      ? findProductProcessRouteItemList({ orderId: orderId.value })
      : findProcessRouteItemList({ routeId: routeId.value });
  listPromise
    .then(res => {
    .then((res) => {
      tableData.value = res.data || [];
      tableLoading.value = false;
      // 列表加载完成后初始化拖拽排序
      nextTick(() => {
        initSortable();
      });
    })
    .catch(err => {
    .catch((err) => {
      tableLoading.value = false;
      console.error("获取列表失败:", err);
      proxy?.$modal?.msgError("获取列表失败");
      console.error('获取列表失败:', err);
      proxy?.$modal?.msgError('获取列表失败');
    });
};
// 获取工序列表
const getProcessList = () => {
  processList({})
    .then(res => {
    .then((res) => {
      processOptions.value = res.data || [];
    })
    .catch(err => {
      console.error("获取工序失败:", err);
    .catch((err) => {
      console.error('获取工序失败:', err);
    });
};
// 获取工艺路线详情(从路由参数获取)
const getRouteInfo = () => {
  routeInfo.value = {
    processRouteCode: route.query.processRouteCode || '',
    productName: route.query.productName || '',
    model: route.query.model || '',
    bomNo: route.query.bomNo || '',
    description: route.query.description || ''
    description: route.query.description || '',
  };
};
// 新增
const getEditSelectedProducts = (row) => {
  const idList = String(row.productModelIds || row.productModelId || '')
    .split(',')
    .map((item) => item.trim())
    .filter(Boolean);
  const nameList = String(row.productName || '')
    .split(',')
    .map((item) => item.trim());
  const modelList = String(row.model || '')
    .split(',')
    .map((item) => item.trim());
  return idList.map((id, index) => ({
    id: Number(id) || id,
    productName: nameList[index] || row.productName || '',
    model: modelList[index] || row.model || '',
    unit: row.unit || '',
  }));
};
const handleAdd = () => {
  operationType.value = 'add';
  resetForm();
  dialogVisible.value = true;
};
// 编辑
const handleEdit = (row) => {
  operationType.value = 'edit';
  const selectedProducts = getEditSelectedProducts(row);
  form.value = {
    id: row.id,
    routeId: routeId.value,
    processId: row.processId,
    productModelId: row.productModelId,
    productName: row.productName || "",
    model: row.model || "",
    unit: row.unit || "",
    productModelIds: row.productModelIds || (row.productModelId ? String(row.productModelId) : ''),
    selectedProducts,
    productName: row.productName || '',
    model: row.model || '',
    unit: row.unit || '',
    isQuality: row.isQuality,
  };
  dialogVisible.value = true;
};
// 删除
const handleDelete = (row) => {
  ElMessageBox.confirm('确认删除该工艺路线项目?', '提示', {
    confirmButtonText: '确认',
    cancelButtonText: '取消',
    type: 'warning'
    type: 'warning',
  })
    .then(() => {
      // 生产订单下使用 productProcessRoute 的删除接口(路由后拼接 id),其它情况使用工艺路线项目批量删除接口
      const deletePromise =
        pageType.value === 'order'
          ? deleteRouteItem(row.id)
@@ -382,112 +416,115 @@
    .catch(() => {});
};
// 产品选择
const handleProductSelect = (products) => {
  if (products && products.length > 0) {
    const product = products[0];
    form.value.productModelId = product.id;
    form.value.productName = product.productName;
    form.value.model = product.model;
    form.value.unit = product.unit || "";
    const firstProduct = products[0];
    form.value.selectedProducts = products;
    form.value.productModelIds = products.map((item) => item.id).join(',');
    form.value.productModelId = products.length === 1 ? firstProduct.id : undefined;
    form.value.productName = products.length === 1 ? firstProduct.productName : '';
    form.value.model = products.length === 1 ? firstProduct.model : '';
    form.value.unit = products.length === 1 ? (firstProduct.unit || '') : '';
    showProductSelectDialog.value = false;
    // 触发表单验证
    formRef.value?.validateField('productModelId');
    formRef.value?.validateField('selectedProducts');
  }
};
// 提交
const handleSubmit = () => {
  formRef.value.validate((valid) => {
    if (valid) {
      submitLoading.value = true;
      if (operationType.value === 'add') {
        // 新增:传单个对象,包含dragSort字段
        // dragSort = 当前列表长度 + 1,表示新增记录排在最后
        const dragSort = tableData.value.length + 1;
        const isOrderPage = pageType.value === 'order';
        const addPromise = isOrderPage
          ? addRouteItem({
              productOrderId: orderId.value,
              productRouteId: routeId.value,
              processId: form.value.processId,
              productModelId: form.value.productModelId,
              isQuality: form.value.isQuality,
              dragSort,
            })
          : addOrUpdateProcessRouteItem({
              routeId: routeId.value,
              processId: form.value.processId,
              productModelId: form.value.productModelId,
              isQuality: form.value.isQuality,
              dragSort,
            });
        addPromise
          .then(() => {
            proxy?.$modal?.msgSuccess('新增成功');
            closeDialog();
            getList();
          })
          .catch(() => {
            proxy?.$modal?.msgError('新增失败');
          })
          .finally(() => {
            submitLoading.value = false;
          });
      } else {
        // 编辑:生产订单下使用 productProcessRoute/updateRouteItem,其它情况使用工艺路线项目更新接口
        const isOrderPage = pageType.value === 'order';
        const updatePromise = isOrderPage
          ? addOrUpdateProductProcessRouteItem({
              id: form.value.id,
              processId: form.value.processId,
              productModelId: form.value.productModelId,
              isQuality: form.value.isQuality,
            })
          : addOrUpdateProcessRouteItem({
              routeId: routeId.value,
              processId: form.value.processId,
              productModelId: form.value.productModelId,
              id: form.value.id,
              isQuality: form.value.isQuality,
            });
        updatePromise
          .then(() => {
            proxy?.$modal?.msgSuccess('修改成功');
            closeDialog();
            getList();
          })
          .catch(() => {
            proxy?.$modal?.msgError('修改失败');
          })
          .finally(() => {
            submitLoading.value = false;
          });
      }
    if (!valid) {
      return;
    }
    submitLoading.value = true;
    if (operationType.value === 'add') {
      const dragSort = tableData.value.length + 1;
      const isOrderPage = pageType.value === 'order';
      const addPromise = isOrderPage
        ? addRouteItem({
            productOrderId: orderId.value,
            productRouteId: routeId.value,
            processId: form.value.processId,
            productModelId: form.value.productModelId,
            productModelIds: form.value.productModelIds,
            isQuality: form.value.isQuality,
            dragSort,
          })
        : addOrUpdateProcessRouteItem({
            routeId: routeId.value,
            processId: form.value.processId,
            productModelId: form.value.productModelId,
            productModelIds: form.value.productModelIds,
            isQuality: form.value.isQuality,
            dragSort,
          });
      addPromise
        .then(() => {
          proxy?.$modal?.msgSuccess('新增成功');
          closeDialog();
          getList();
        })
        .catch(() => {
          proxy?.$modal?.msgError('新增失败');
        })
        .finally(() => {
          submitLoading.value = false;
        });
      return;
    }
    const isOrderPage = pageType.value === 'order';
    const updatePromise = isOrderPage
      ? addOrUpdateProductProcessRouteItem({
          id: form.value.id,
          processId: form.value.processId,
          productModelId: form.value.productModelId,
          productModelIds: form.value.productModelIds,
          isQuality: form.value.isQuality,
        })
      : addOrUpdateProcessRouteItem({
          routeId: routeId.value,
          processId: form.value.processId,
          productModelId: form.value.productModelId,
          productModelIds: form.value.productModelIds,
          id: form.value.id,
          isQuality: form.value.isQuality,
        });
    updatePromise
      .then(() => {
        proxy?.$modal?.msgSuccess('修改成功');
        closeDialog();
        getList();
      })
      .catch(() => {
        proxy?.$modal?.msgError('修改失败');
      })
      .finally(() => {
        submitLoading.value = false;
      });
  });
};
// 重置表单
const resetForm = () => {
  form.value = {
    id: undefined,
    routeId: routeId.value,
    processId: undefined,
    productModelId: undefined,
    productName: "",
    model: "",
    unit: "",
    productModelIds: '',
    selectedProducts: [],
    productName: '',
    model: '',
    unit: '',
    isQuality: false,
  };
  formRef.value?.resetFields();
};
// 关闭弹窗
const closeDialog = () => {
  dialogVisible.value = false;
  resetForm();
@@ -753,6 +790,18 @@
  margin: 10px 0;
}
.selected-product-tags {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-top: 10px;
}
.selected-product-tag {
  max-width: 100%;
}
.card-footer {
  display: flex;
  justify-content: space-around;