src/views/productionManagement/processRoute/ItemsForm.vue
@@ -7,15 +7,7 @@
        @close="closeModal"
    >
      <div class="operate-button">
        <el-button
            type="primary"
            @click="isShowProductSelectDialog = true"
            class="mb5"
            style="margin-bottom: 10px;"
        >
          选择产品
        </el-button>
        <span class="route-tip">后端根据BOM生成工艺路线,可在此调整工序和顺序</span>
        <el-switch
            v-model="isTable"
            inline-prompt
@@ -68,6 +60,7 @@
              <el-select
                  v-model="scope.row[item.prop]"
                  style="width: 100%;"
                  @change="value => handleProcessChange(scope.row, value)"
                  @mousedown.stop
              >
                <el-option
@@ -102,16 +95,17 @@
          <div class="step-content">
            <div class="step-number">{{ index + 1 }}</div>
            <el-card
                :header="item.productName"
                :header="getProcessName(item)"
                class="step-card"
                style="cursor: move;"
            >
              <div class="step-card-content">
                <p>{{ item.model }}</p>
                <p>{{ item.unit }}</p>
                <p>{{ item.productName || '-' }}</p>
                <p>{{ item.model || '-' }}</p>
                <el-select
                    v-model="item.processId"
                    style="width: 100%;"
                    @change="value => handleProcessChange(item, value)"
                    @mousedown.stop
                >
                  <el-option
@@ -139,18 +133,12 @@
        </div>
      </template>
    </el-dialog>
    <ProductSelectDialog
        v-model="isShowProductSelectDialog"
        @confirm="handelSelectProducts"
    />
  </div>
</template>
<script setup>
import { ref, computed, getCurrentInstance, onMounted, onUnmounted, nextTick } from "vue";
import ProductSelectDialog from "@/views/basicData/product/ProductSelectDialog.vue";
import { findProcessRouteItemList, addOrUpdateProcessRouteItem } from "@/api/productionManagement/processRouteItem.js";
import { findProcessRouteItemList, saveProcessRouteItems } from "@/api/productionManagement/processRouteItem.js";
import { processList } from "@/api/productionManagement/productionProcess.js";
import Sortable from 'sortablejs';
@@ -171,7 +159,6 @@
const processOptions = ref([]);
const tableLoading = ref(false);
const isShowProductSelectDialog = ref(false);
const routeItems = ref([]);
let tableSortable = null;
let stepsSortable = null;
@@ -191,8 +178,7 @@
const tableColumn = ref([
  { label: "产品名称", prop: "productName", width: 180 },
  { label: "规格名称", prop: "model", width: 150 },
  { label: "单位", prop: "unit", width: 80 },
  { label: "工序名称", prop: "processId", width: 180 },
  { label: "工序名称", prop: "processId", width: 220 },
  {
    dataType: "action",
    label: "操作",
@@ -215,6 +201,21 @@
  }
]);
const getProcessName = item => {
  if (item.processName || item.operationName) {
    return item.processName || item.operationName;
  }
  const process = processOptions.value.find(process => process.id === item.processId);
  return process?.name || "请选择工序";
};
const handleProcessChange = (row, value) => {
  const process = processOptions.value.find(process => process.id === value);
  row.processName = process?.name || "";
  row.operationName = row.processName;
  row.operationId = value;
};
const removeItem = (index) => {
  routeItems.value.splice(index, 1);
  nextTick(() => initSortable());
@@ -232,46 +233,18 @@
  isShow.value = false;
};
const handelSelectProducts = (products) => {
  destroySortable();
  const newData = products.map(({ id, ...product }) => ({
    ...product,
    productModelId: id,
    routeId: props.record.id,
    id: `${Date.now()}-${Math.random().toString(36).slice(2)}`,
    processId: undefined
  }));
  console.log('选择产品前数组:', routeItems.value);
  routeItems.value.push(...newData);
  routeItems.value = [...routeItems.value];
  console.log('选择产品后数组:', routeItems.value);
  // 延迟初始化,确保DOM完全渲染
  nextTick(() => {
    // 强制重新渲染组件
    if (proxy?.$forceUpdate) {
      proxy.$forceUpdate();
    }
    const temp = [...routeItems.value];
    routeItems.value = [];
    nextTick(() => {
      routeItems.value = temp;
      initSortable();
    });
  });
};
const findProcessRouteItems = () => {
  tableLoading.value = true;
  findProcessRouteItemList({ routeId: props.record.id })
      .then(res => {
        tableLoading.value = false;
        routeItems.value = res.data.map(item => ({
        // 后端返回 technologyOperationId / technologyOperationName,页面统一用 processId / processName
        routeItems.value = (res.data || []).map(item => ({
          ...item,
          processId: item.processId === 0 ? undefined : item.processId
          productName: item.productName || "",
          model: item.model || "",
          processName: item.technologyOperationName || item.processName || "",
          processId: item.technologyOperationId || (item.processId === 0 ? undefined : item.processId)
        }));
        // 延迟初始化,确保DOM完全渲染
        nextTick(() => {
@@ -302,10 +275,20 @@
    proxy?.$modal?.msgError("请为所有项目选择工序");
    return;
  }
  const processIds = routeItems.value.map(item => item.processId);
  if (new Set(processIds).size !== processIds.length) {
    proxy?.$modal?.msgError("同一道工序不能重复出现在工艺路线中");
    return;
  }
  addOrUpdateProcessRouteItem({
    routeId: props.record.id,
    processRouteItem: routeItems.value.map(({ id, ...item }) => item)
  // 全量提交:工序顺序即当前列表顺序,未回传的工序会被后端删除
  saveProcessRouteItems({
    technologyRoutingId: props.record.id,
    operationList: routeItems.value.map((item, index) => ({
      id: item.id,
      technologyOperationId: item.processId,
      dragSort: index + 1
    }))
  })
      .then(res => {
        isShow.value = false;
@@ -349,7 +332,6 @@
        const moveItem = routeItems.value.splice(evt.oldIndex, 1)[0];
        routeItems.value.splice(evt.newIndex, 0, moveItem);
        routeItems.value = [...routeItems.value];
        console.log('排序后数组:', routeItems.value);
      }
    });
  } else {
@@ -385,10 +367,6 @@
        routeItems.value = [...routeItems.value];
      }
    });
    // 调试:打印容器和实例,确认绑定成功
    console.log('步骤条拖拽容器:', stepsList);
    console.log('Sortable实例:', stepsSortable);
  }
};
@@ -438,6 +416,12 @@
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 10px;
}
.route-tip {
  color: #606266;
  font-size: 13px;
}
/* 修改:自定义步骤条容器样式 */