zhangwencui
7 小时以前 4acf9156ee445cb9f2367d77824e1c6e25b397ab
工序和公益路线页面开发
已修改3个文件
已删除6个文件
5099 ■■■■ 文件已修改
src/views/basicData/parameterMaintenance/index.vue 279 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/productionManagement/processRoute/Edit.vue 252 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/productionManagement/processRoute/ItemsForm.vue 531 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/productionManagement/processRoute/New.vue 194 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/productionManagement/processRoute/index.vue 1515 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/productionManagement/processRoute/processRouteItem/index.vue 896 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/productionManagement/productionProcess/Edit.vue 138 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/productionManagement/productionProcess/New.vue 105 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/productionManagement/productionProcess/index.vue 1189 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/basicData/parameterMaintenance/index.vue
@@ -7,11 +7,12 @@
                  style="width: 200px"
                  placeholder="请输入参数名称"
                  clearable />
        <span class="search_title ml10">关联产品类型:</span>
        <!-- å…³è”产品类型搜索 -->
        <!-- <span class="search_title ml10">关联产品类型:</span>
        <el-input v-model="searchForm.productName"
                  style="width: 200px"
                  placeholder="请输入关联产品类型"
                  clearable />
                  clearable /> -->
        <el-button type="primary"
                   @click="handleQuery"
                   style="margin-left: 10px">搜索</el-button>
@@ -19,9 +20,10 @@
        <el-button type="primary"
                   @click="handleAdd"
                   style="margin-left: 10px">新增参数</el-button>
        <el-button type="primary"
        <!-- äº§å“ç±»åž‹ç»´æŠ¤æŒ‰é’® -->
        <!-- <el-button type="primary"
                   @click="handleProductTypeMaintenance"
                   style="margin-left: 10px">产品类型维护</el-button>
                   style="margin-left: 10px">产品类型维护</el-button> -->
      </div>
    </div>
    <div class="table_list">
@@ -106,7 +108,8 @@
          <el-input v-model="formData.parameterFormat"
                    placeholder="请输入参数格式" />
        </el-form-item>
        <el-form-item label="关联产品类型"
        <!-- å…³è”产品类型 -->
        <!-- <el-form-item label="关联产品类型"
                      prop="parameterValue">
          <el-select v-model="formData.parameterValue"
                     placeholder="请选择关联产品类型">
@@ -115,7 +118,7 @@
                       :label="item.label"
                       :value="item.value" />
          </el-select>
        </el-form-item>
        </el-form-item> -->
        <el-form-item label="标准值"
                      v-if="formData.parameterType2 === '1'"
                      prop="standardValue">
@@ -149,7 +152,7 @@
      </template>
    </el-dialog>
    <!-- äº§å“ç±»åž‹ç»´æŠ¤å¯¹è¯æ¡† -->
    <el-dialog v-model="productTypeDialogVisible"
    <!-- <el-dialog v-model="productTypeDialogVisible"
               title="产品类型维护"
               width="600px">
      <div class="product-type-header">
@@ -159,9 +162,9 @@
      <el-table :data="productTypeList"
                border
                style="width: 100%; margin-top: 10px; margin-bottom: 20px">
        <!-- <el-table-column prop="typeCode"
        <el-table-column prop="typeCode"
                         label="类型编码"
                         width="150" /> -->
                         width="150" />
        <el-table-column prop="typeName"
                         label="类型名称" />
        <el-table-column label="操作"
@@ -176,20 +179,20 @@
          </template>
        </el-table-column>
      </el-table>
    </el-dialog>
    </el-dialog> -->
    <!-- æ–°å¢ž/编辑产品类型对话框 -->
    <el-dialog v-model="productTypeFormVisible"
    <!-- <el-dialog v-model="productTypeFormVisible"
               :title="productTypeDialogTitle"
               width="400px">
      <el-form :model="productTypeForm"
               :rules="productTypeRules"
               ref="productTypeFormRef"
               label-width="100px">
        <!-- <el-form-item label="类型编码"
        <el-form-item label="类型编码"
                      prop="typeCode">
          <el-input v-model="productTypeForm.typeCode"
                    placeholder="请输入类型编码" />
        </el-form-item> -->
        </el-form-item>
        <el-form-item label="类型名称"
                      prop="typeName">
          <el-input v-model="productTypeForm.typeName"
@@ -203,7 +206,7 @@
                     @click="handleProductTypeSubmit">确定</el-button>
        </span>
      </template>
    </el-dialog>
    </el-dialog> -->
  </div>
</template>
@@ -214,7 +217,7 @@
    addParameter,
    updateParameter,
    delParameter,
    getProductTypes as getProductTypesApi,
    // getProductTypes as getProductTypesApi,
  } from "@/api/basicData/parameterMaintenance.js";
  import { listType } from "@/api/system/dict/type";
  import PIMTable from "@/components/PIMTable/PIMTable.vue";
@@ -252,10 +255,11 @@
      label: "参数格式",
      prop: "parameterFormat",
    },
    {
      label: "关联产品类型",
      prop: "parameterValue",
    },
    // å…³è”产品类型列
    // {
    //   label: "关联产品类型",
    //   prop: "parameterValue",
    // },
    {
      label: "标准值",
      prop: "standardValue",
@@ -325,7 +329,7 @@
    parameterType2: "1",
    parameterType: "",
    parameterFormat: "",
    parameterValue: "",
    // parameterValue: "",
    standardValue: "",
    unit: "",
  });
@@ -342,31 +346,31 @@
    parameterFormat: [
      { required: true, message: "请选择参数格式", trigger: "change" },
    ],
    parameterValue: [
      { required: true, message: "请选择关联产品类型", trigger: "change" },
    ],
    // parameterValue: [
    //   { required: true, message: "请选择关联产品类型", trigger: "change" },
    // ],
    standardValue: [{ required: true, message: "请输入标准值", trigger: "blur" }],
    unit: [{ required: true, message: "请输入单位", trigger: "blur" }],
  });
  const productTypes = ref([]);
  // const productTypes = ref([]);
  const isEdit = ref(false);
  // äº§å“ç±»åž‹ç»´æŠ¤ç›¸å…³
  const productTypeDialogVisible = ref(false);
  const productTypeFormVisible = ref(false);
  const productTypeDialogTitle = ref("");
  const productTypeFormRef = ref(null);
  const productTypeList = ref([]);
  const productTypeForm = reactive({
    id: null,
    // typeCode: "",
    typeName: "",
  });
  const productTypeRules = reactive({
    // typeCode: [{ required: true, message: "请输入类型编码", trigger: "blur" }],
    typeName: [{ required: true, message: "请输入类型名称", trigger: "blur" }],
  });
  const isProductTypeEdit = ref(false);
  // äº§å“ç±»åž‹ç»´æŠ¤ç›¸å…³ - å·²æ³¨é‡Š
  // const productTypeDialogVisible = ref(false);
  // const productTypeFormVisible = ref(false);
  // const productTypeDialogTitle = ref("");
  // const productTypeFormRef = ref(null);
  // const productTypeList = ref([]);
  // const productTypeForm = reactive({
  //   id: null,
  //   typeCode: "",
  //   typeName: "",
  // });
  // const productTypeRules = reactive({
  //   typeCode: [{ required: true, message: "请输入类型编码", trigger: "blur" }],
  //   typeName: [{ required: true, message: "请输入类型名称", trigger: "blur" }],
  // });
  // const isProductTypeEdit = ref(false);
  const handleParameterTypeChange = () => {
    if (formData.parameterType === "数值格式") {
      formData.parameterFormat = "#.0000";
@@ -376,65 +380,65 @@
      formData.parameterFormat = "";
    }
  };
  // äº§å“ç±»åž‹ç»´æŠ¤æŒ‰é’®ç‚¹å‡»äº‹ä»¶
  const handleProductTypeMaintenance = () => {
    productTypeDialogVisible.value = true;
    getProductTypeList();
  };
  // äº§å“ç±»åž‹ç»´æŠ¤æŒ‰é’®ç‚¹å‡»äº‹ä»¶ - å·²æ³¨é‡Š
  // const handleProductTypeMaintenance = () => {
  //   productTypeDialogVisible.value = true;
  //   getProductTypeList();
  // };
  // èŽ·å–äº§å“ç±»åž‹åˆ—è¡¨
  const getProductTypeList = () => {
    productTypeList.value = [
      { id: 1, typeCode: "TYPE001", typeName: "3.5砌块" },
      { id: 2, typeCode: "TYPE002", typeName: "5.0砌块" },
      { id: 3, typeCode: "TYPE003", typeName: "板材" },
    ];
  };
  // èŽ·å–äº§å“ç±»åž‹åˆ—è¡¨ - å·²æ³¨é‡Š
  // const getProductTypeList = () => {
  //   productTypeList.value = [
  //     { id: 1, typeCode: "TYPE001", typeName: "3.5砌块" },
  //     { id: 2, typeCode: "TYPE002", typeName: "5.0砌块" },
  //     { id: 3, typeCode: "TYPE003", typeName: "板材" },
  //   ];
  // };
  // æ–°å¢žäº§å“ç±»åž‹
  const handleAddProductType = () => {
    isProductTypeEdit.value = false;
    productTypeDialogTitle.value = "新增产品类型";
    productTypeForm.id = null;
    productTypeForm.typeCode = "";
    productTypeForm.typeName = "";
    productTypeFormVisible.value = true;
  };
  // æ–°å¢žäº§å“ç±»åž‹ - å·²æ³¨é‡Š
  // const handleAddProductType = () => {
  //   isProductTypeEdit.value = false;
  //   productTypeDialogTitle.value = "新增产品类型";
  //   productTypeForm.id = null;
  //   productTypeForm.typeCode = "";
  //   productTypeForm.typeName = "";
  //   productTypeFormVisible.value = true;
  // };
  // ç¼–辑产品类型
  const handleEditProductType = row => {
    isProductTypeEdit.value = true;
    productTypeDialogTitle.value = "编辑产品类型";
    productTypeForm.id = row.id;
    productTypeForm.typeCode = row.typeCode;
    productTypeForm.typeName = row.typeName;
    productTypeFormVisible.value = true;
  };
  // ç¼–辑产品类型 - å·²æ³¨é‡Š
  // const handleEditProductType = row => {
  //   isProductTypeEdit.value = true;
  //   productTypeDialogTitle.value = "编辑产品类型";
  //   productTypeForm.id = row.id;
  //   productTypeForm.typeCode = row.typeCode;
  //   productTypeForm.typeName = row.typeName;
  //   productTypeFormVisible.value = true;
  // };
  // åˆ é™¤äº§å“ç±»åž‹
  const handleDeleteProductType = row => {
    ElMessageBox.confirm("确定要删除该产品类型吗?", "提示", {
      confirmButtonText: "确定",
      cancelButtonText: "取消",
      type: "warning",
    })
      .then(() => {
        ElMessage.success("删除成功");
        getProductTypeList();
      })
      .catch(() => {});
  };
  // åˆ é™¤äº§å“ç±»åž‹ - å·²æ³¨é‡Š
  // const handleDeleteProductType = row => {
  //   ElMessageBox.confirm("确定要删除该产品类型吗?", "提示", {
  //     confirmButtonText: "确定",
  //     cancelButtonText: "取消",
  //     type: "warning",
  //   })
  //     .then(() => {
  //       ElMessage.success("删除成功");
  //       getProductTypeList();
  //     })
  //     .catch(() => {});
  // };
  // æäº¤äº§å“ç±»åž‹è¡¨å•
  const handleProductTypeSubmit = () => {
    productTypeFormRef.value.validate(valid => {
      if (valid) {
        ElMessage.success(isProductTypeEdit.value ? "编辑成功" : "新增成功");
        productTypeFormVisible.value = false;
        getProductTypeList();
      }
    });
  };
  // æäº¤äº§å“ç±»åž‹è¡¨å• - å·²æ³¨é‡Š
  // const handleProductTypeSubmit = () => {
  //   productTypeFormRef.value.validate(valid => {
  //     if (valid) {
  //       ElMessage.success(isProductTypeEdit.value ? "编辑成功" : "新增成功");
  //       productTypeFormVisible.value = false;
  //       getProductTypeList();
  //     }
  //   });
  // };
  // æŸ¥è¯¢åˆ—表
  /** æœç´¢æŒ‰é’®æ“ä½œ */
@@ -460,15 +464,15 @@
    tableLoading.value = true;
    // æ³¨é‡ŠæŽ‰API调用,使用假数据
    /*const params = { ...searchForm, ...page };
                                                                    parameterListPage(params)
                                                                      .then(res => {
                                                                        tableLoading.value = false;
                                                                        tableData.value = res.data;
                                                                        page.total = res.total || 0;
                                                                      })
                                                                      .catch(() => {
                                                                        tableLoading.value = false;
                                                                      });*/
                                                                                              parameterListPage(params)
                                                                                                .then(res => {
                                                                                                  tableLoading.value = false;
                                                                                                  tableData.value = res.data;
                                                                                                  page.total = res.total || 0;
                                                                                                })
                                                                                                .catch(() => {
                                                                                                  tableLoading.value = false;
                                                                                                });*/
    // å‡æ•°æ®
    setTimeout(() => {
@@ -534,29 +538,14 @@
    }, 500);
  };
  // èŽ·å–äº§å“ç±»åž‹åˆ—è¡¨
  const getProductTypes = () => {
    // æ³¨é‡ŠæŽ‰API调用,使用假数据
    /*getProductTypesApi()
                                                                      .then(res => {
                                                                        productTypes.value = res.data || [];
                                                                      })
                                                                      .catch(() => {
                                                                        // å¤±è´¥æ—¶ä½¿ç”¨æ¨¡æ‹Ÿæ•°æ®
                                                                        productTypes.value = [
                                                                          { label: "3.5砌块", value: "type1" },
                                                                          { label: "5.0砌块", value: "type2" },
                                                                          { label: "板材", value: "type3" },
                                                                        ];
                                                                      });*/
    // å‡æ•°æ®
    productTypes.value = [
      { label: "3.5砌块", value: "type1" },
      { label: "5.0砌块", value: "type2" },
      { label: "板材", value: "type3" },
    ];
  };
  // èŽ·å–äº§å“ç±»åž‹åˆ—è¡¨ - å·²æ³¨é‡Š
  // const getProductTypes = () => {
  //   productTypes.value = [
  //     { label: "3.5砌块", value: "type1" },
  //     { label: "5.0砌块", value: "type2" },
  //     { label: "板材", value: "type3" },
  //   ];
  // };
  // æ–°å¢žæŒ‰é’®ç‚¹å‡»äº‹ä»¶
  const handleAdd = () => {
@@ -568,7 +557,7 @@
    formData.parameterType2 = "1";
    formData.parameterType = "";
    formData.parameterFormat = "";
    formData.parameterValue = "";
    // formData.parameterValue = "";
    formData.standardValue = "";
    formData.unit = "";
    dialogVisible.value = true;
@@ -584,7 +573,7 @@
    formData.parameterType2 = row.parameterType2 || "1";
    formData.parameterType = row.parameterType;
    formData.parameterFormat = row.parameterFormat;
    formData.parameterValue = row.parameterValue;
    // formData.parameterValue = row.parameterValue;
    formData.standardValue = row.standardValue;
    formData.unit = row.unit;
    dialogVisible.value = true;
@@ -600,13 +589,13 @@
      .then(() => {
        // æ³¨é‡ŠæŽ‰API调用,使用假数据
        /*delParameter(row.id)
                                                                      .then(res => {
                                                                        ElMessage.success("删除成功");
                                                                        getList();
                                                                      })
                                                                      .catch(() => {
                                                                        ElMessage.error("删除失败");
                                                                      });*/
                                                                                                .then(res => {
                                                                                                  ElMessage.success("删除成功");
                                                                                                  getList();
                                                                                                })
                                                                                                .catch(() => {
                                                                                                  ElMessage.error("删除失败");
                                                                                                });*/
        // å‡æ•°æ®æ¨¡æ‹Ÿ
        ElMessage.success("删除成功");
@@ -623,15 +612,15 @@
      if (valid) {
        // æ³¨é‡ŠæŽ‰API调用,使用假数据
        /*const api = isEdit.value ? updateParameter : addParameter;
                                                                      api(formData)
                                                                        .then(res => {
                                                                          ElMessage.success(isEdit.value ? "编辑成功" : "新增成功");
                                                                          dialogVisible.value = false;
                                                                          getList();
                                                                        })
                                                                        .catch(() => {
                                                                          ElMessage.error(isEdit.value ? "编辑失败" : "新增失败");
                                                                        });*/
                                                                                                api(formData)
                                                                                                  .then(res => {
                                                                                                    ElMessage.success(isEdit.value ? "编辑成功" : "新增成功");
                                                                                                    dialogVisible.value = false;
                                                                                                    getList();
                                                                                                  })
                                                                                                  .catch(() => {
                                                                                                    ElMessage.error(isEdit.value ? "编辑失败" : "新增失败");
                                                                                                  });*/
        // å‡æ•°æ®æ¨¡æ‹Ÿ
        ElMessage.success(isEdit.value ? "编辑成功" : "新增成功");
@@ -652,7 +641,7 @@
  onMounted(() => {
    getDictTypes();
    getList();
    getProductTypes();
    // getProductTypes();
  });
</script>
src/views/productionManagement/processRoute/Edit.vue
ÎļþÒÑɾ³ý
src/views/productionManagement/processRoute/ItemsForm.vue
ÎļþÒÑɾ³ý
src/views/productionManagement/processRoute/New.vue
ÎļþÒÑɾ³ý
src/views/productionManagement/processRoute/index.vue
@@ -1,204 +1,1361 @@
<template>
  <div class="app-container">
    <div class="search_form">
      <el-form :model="searchForm" :inline="true">
        <el-form-item label="规格名称:">
          <el-input v-model="searchForm.model" placeholder="请输入" clearable prefix-icon="Search"
                    style="width: 200px;"
                    @change="handleQuery" />
    <div class="route-header">
      <div class="add-route-btn"
           @click="handleAddRoute">
        <el-icon>
          <Plus />
        </el-icon>
        <span>新增工艺路线</span>
      </div>
    </div>
    <div class="route-card-list">
      <div v-for="route in routeList"
           :key="route.id"
           class="route-card">
        <div class="card-header">
          <div class="route-info">
            <span class="route-name"><el-icon style="margin-right: 8px;line-height: 30px;">
                <ScaleToOriginal />
              </el-icon>{{ route.routeName }}<el-tag style="margin-left: 8px"
                      :type="route.status == 1 ? 'warning' : 'success'">{{ route.status == 1 ? '草稿' : '批准' }}</el-tag></span>
            <span class="route-code">{{ route.routeCode }}</span>
          </div>
          <div class="route-actions">
            <el-button v-if="route.status === '1'"
                       link
                       type="success"
                       @click="handleApproveRoute(route)">
              <el-icon>
                <Check />
              </el-icon>
              æ‰¹å‡†
            </el-button>
            <el-button v-if="route.status === '2'"
                       link
                       type="warning"
                       @click="handleRevokeApproveRoute(route)">
              <el-icon>
                <Close />
              </el-icon>
              æ’¤é”€æ‰¹å‡†
            </el-button>
            <el-button link
                       type="primary"
                       @click="handleEditRoute(route)">
              <el-icon>
                <Edit />
              </el-icon>
              ç¼–辑
            </el-button>
            <el-button link
                       type="danger"
                       @click="handleDeleteRoute(route)">
              <el-icon>
                <Delete />
              </el-icon>
              åˆ é™¤
            </el-button>
          </div>
        </div>
        <div class="card-body">
          <div class="route-desc">{{ route.routeDesc || '暂无描述' }}</div>
          <el-button type="primary"
                     link
                     @click="toggleExpand(route)">
            {{ route.expanded ? '收起' : '展开工序路线' }}
            <el-icon class="expand-icon">
              <component :is="route.expanded ? 'ArrowUp' : 'ArrowDown'" />
            </el-icon>
          </el-button>
        </div>
        <div v-if="route.expanded"
             class="process-route">
          <div class="process-flow">
            <div v-for="(process, index) in route.processList"
                 :key="process.id"
                 class="process-flow-item"
                 draggable="true"
                 @dragstart="handleDragStart($event, index, route.id)"
                 @dragover="handleDragOver($event)"
                 @drop="handleDrop($event, index, route.id)"
                 @dragend="handleDragEnd">
              <div class="process-node"
                   :class="{ expanded: process.expanded }">
                <div class="process-node-header">
                  <div class="process-number">{{ index + 1 }}</div>
                  <div class="process-actions">
                    <el-button link
                               type="danger"
                               @click="handleDeleteProcess(route.id, process)">
                      <el-icon>
                        <Delete />
                      </el-icon>
                    </el-button>
                  </div>
                </div>
                <div class="process-node-body">
                  <div class="process-code">{{ process.processCode }}</div>
                  <div class="process-name">{{ process.processName }}</div>
                  <div class="process-desc">{{ process.processDesc || '暂无描述' }}</div>
                </div>
                <div class="process-node-footer">
                  <!-- <el-tag size="small"
                          :type="process.status === '1' ? 'success' : 'info'">
                    {{ process.status === '1' ? '启用' : '停用' }}
                  </el-tag> -->
                  <el-button type="primary"
                             link
                             size="small"
                             @click="toggleProcessParams(process)">
                    {{ process.expanded ? '收起参数' : '展开参数' }}
                    ({{ process.paramList?.length || 0 }})
                  </el-button>
                </div>
                <div v-if="process.expanded"
                     class="process-params-section">
                  <div class="params-header">
                    <span>参数列表</span>
                    <el-button type="primary"
                               link
                               size="small"
                               @click="handleAddParam(route.id, process)">
                      <el-icon>
                        <Plus />
                      </el-icon>新增
                    </el-button>
                  </div>
                  <div class="params-list">
                    <div v-for="param in process.paramList"
                         :key="param.id"
                         class="param-item">
                      <div class="param-info">
                        <span class="param-code">{{ param.parameterCode }}</span>
                        <span class="param-name">{{ param.parameterName }}</span>
                        <!-- <el-tag size="small"
                                style="margin-right: 20px;"
                                :type="getParamTypeTag(param.parameterType)">
                          {{ param.parameterType }}
                        </el-tag> -->
                        <span class="param-value">标准值:{{ param.standardValue }} {{ param.unit }}</span>
                      </div>
                      <div class="param-actions">
                        <el-button link
                                   type="primary"
                                   size="small"
                                   @click="handleEditParam(route.id, process, param)">
                          ç¼–辑
                        </el-button>
                        <el-button link
                                   type="danger"
                                   size="small"
                                   @click="handleDeleteParam(route.id, process, param)">
                          åˆ é™¤
                        </el-button>
                      </div>
                    </div>
                    <el-empty v-if="!process.paramList || process.paramList.length === 0"
                              description="暂无参数"
                              :image-size="50" />
                  </div>
                </div>
              </div>
              <div v-if="index < route.processList.length - 1"
                   class="flow-arrow">
                <el-icon>
                  <Right />
                </el-icon>
              </div>
            </div>
            <div class="add-process-node"
                 @click="handleSelectProcess(route, index)">
              <el-icon>
                <Plus />
              </el-icon>
              <span>新增工序</span>
            </div>
          </div>
          <el-empty v-if="!route.processList || route.processList.length === 0"
                    description="暂无工序"
                    :image-size="80" />
        </div>
      </div>
    </div>
    <!-- å·¥è‰ºè·¯çº¿æ–°å¢ž/编辑对话框 -->
    <el-dialog v-model="routeDialogVisible"
               :title="isRouteEdit ? '编辑工艺路线' : '新增工艺路线'"
               width="500px">
      <el-form :model="routeForm"
               :rules="routeRules"
               ref="routeFormRef"
               label-width="120px">
        <el-form-item label="路线编码"
                      prop="routeCode">
          <el-input v-model="routeForm.routeCode"
                    placeholder="请输入路线编码" />
        </el-form-item>
        <el-form-item>
          <el-button type="primary" @click="handleQuery">搜索</el-button>
        <el-form-item label="路线名称"
                      prop="routeName">
          <el-input v-model="routeForm.routeName"
                    placeholder="请输入路线名称" />
        </el-form-item>
        <el-form-item label="路线描述"
                      prop="routeDesc">
          <el-input v-model="routeForm.routeDesc"
                    type="textarea"
                    :rows="3"
                    placeholder="请输入路线描述" />
        </el-form-item>
        <!-- <el-form-item label="状态"
                      prop="status">
          <el-radio-group v-model="routeForm.status">
            <el-radio label="1">启用</el-radio>
            <el-radio label="0">停用</el-radio>
          </el-radio-group>
        </el-form-item> -->
      </el-form>
      <template #footer>
        <span class="dialog-footer">
          <el-button @click="routeDialogVisible = false">取消</el-button>
          <el-button type="primary"
                     @click="handleRouteSubmit">确定</el-button>
        </span>
      </template>
    </el-dialog>
    <!-- å·¥åºæ–°å¢ž/编辑对话框 -->
    <el-dialog v-model="processDialogVisible"
               :title="isProcessEdit ? '编辑工序' : '新增工序'"
               width="500px">
      <el-form :model="processForm"
               :rules="processRules"
               ref="processFormRef"
               label-width="120px">
        <el-form-item label="工序编码"
                      prop="processCode">
          <el-input v-model="processForm.processCode"
                    placeholder="请输入工序编码" />
        </el-form-item>
        <el-form-item label="工序名称"
                      prop="processName">
          <el-input v-model="processForm.processName"
                    placeholder="请输入工序名称" />
        </el-form-item>
        <el-form-item label="工序描述"
                      prop="processDesc">
          <el-input v-model="processForm.processDesc"
                    type="textarea"
                    :rows="3"
                    placeholder="请输入工序描述" />
        </el-form-item>
        <el-form-item label="状态"
                      prop="status">
          <el-radio-group v-model="processForm.status">
            <el-radio label="1">启用</el-radio>
            <el-radio label="0">停用</el-radio>
          </el-radio-group>
        </el-form-item>
      </el-form>
    </div>
    <div class="table_list">
      <div style="text-align: right" class="mb10">
        <el-button type="primary" @click="showNewModal">新增工艺路线</el-button>
        <el-button type="danger" @click="handleDelete" :disabled="selectedRows.length === 0" plain>删除工艺路线</el-button>
      <template #footer>
        <span class="dialog-footer">
          <el-button @click="processDialogVisible = false">取消</el-button>
          <el-button type="primary"
                     @click="handleProcessSubmit">确定</el-button>
        </span>
      </template>
    </el-dialog>
    <!-- é€‰æ‹©å·¥åºå¯¹è¯æ¡† -->
    <el-dialog v-model="selectProcessDialogVisible"
               title="选择工序"
               width="1000px">
      <div class="process-select-container">
        <!-- å·¦ä¾§å·¥åºåˆ—表 -->
        <div class="process-list-area">
          <div class="area-title">可选工序</div>
          <div class="search-box">
            <el-input v-model="processSearchKeyword"
                      placeholder="请输入工序名称搜索"
                      clearable
                      size="small"
                      @input="handleProcessSearch">
              <template #prefix>
                <el-icon>
                  <Search />
                </el-icon>
              </template>
            </el-input>
          </div>
          <el-table :data="filteredProcessList"
                    height="360"
                    border
                    highlight-current-row
                    @current-change="handleProcessSelect">
            <el-table-column prop="processCode"
                             label="工序编号"
                             width="100" />
            <el-table-column prop="processName"
                             label="工序名称" />
            <el-table-column prop="processDesc"
                             label="工序描述" />
            <el-table-column prop="status"
                             label="状态"
                             width="80">
              <template #default="scope">
                <el-tag size="small"
                        :type="scope.row.status === '1' ? 'success' : 'info'">
                  {{ scope.row.status === '1' ? '启用' : '停用' }}
                </el-tag>
              </template>
            </el-table-column>
          </el-table>
        </div>
        <!-- å³ä¾§å·¥åºè¯¦æƒ… -->
        <div class="process-detail-area">
          <div class="area-title">工序详情</div>
          <el-form v-if="selectedProcessItem"
                   :model="selectedProcessItem"
                   label-width="100px"
                   class="process-detail-form">
            <el-form-item label="工序编号">
              <span class="detail-text">{{ selectedProcessItem.processCode }}</span>
            </el-form-item>
            <el-form-item label="工序名称">
              <span class="detail-text">{{ selectedProcessItem.processName }}</span>
            </el-form-item>
            <el-form-item label="工序描述">
              <span class="detail-text">{{ selectedProcessItem.processDesc || '-' }}</span>
            </el-form-item>
            <el-form-item label="状态">
              <el-tag size="small"
                      :type="selectedProcessItem.status === '1' ? 'success' : 'info'">
                {{ selectedProcessItem.status === '1' ? '启用' : '停用' }}
              </el-tag>
            </el-form-item>
            <el-form-item label="参数数量">
              <span class="detail-text">{{ selectedProcessItem.paramCount || 0 }}个</span>
            </el-form-item>
          </el-form>
          <el-empty v-else
                    description="请从左侧选择工序" />
        </div>
      </div>
      <PIMTable
          rowKey="id"
          :column="tableColumn"
          :tableData="tableData"
          :page="page"
          :isSelection="true"
          @selection-change="handleSelectionChange"
          :tableLoading="tableLoading"
          @pagination="pagination"
          :total="page.total"
      />
    </div>
    <new-process
        v-if="isShowNewModal"
        v-model:visible="isShowNewModal"
        @completed="getList"
    />
    <edit-process
        v-if="isShowEditModal"
        v-model:visible="isShowEditModal"
        :record="record"
        @completed="getList"
    />
    <route-item-form
        v-if="isShowItemModal"
        v-model:visible="isShowItemModal"
        :record="record"
        @completed="getList"
    />
      <template #footer>
        <span class="dialog-footer">
          <el-button @click="selectProcessDialogVisible = false">取消</el-button>
          <el-button type="primary"
                     :disabled="!selectedProcessItem"
                     @click="handleProcessSelectSubmit">确定</el-button>
        </span>
      </template>
    </el-dialog>
    <!-- å‚数新增/编辑对话框 -->
    <el-dialog v-model="paramDialogVisible"
               :title="isParamEdit ? '编辑参数' : '新增参数'"
               width="500px">
      <el-form :model="paramForm"
               :rules="paramRules"
               ref="paramFormRef"
               label-width="120px">
        <el-form-item label="参数编号"
                      prop="parameterCode">
          <el-input v-model="paramForm.parameterCode"
                    placeholder="请输入参数编号" />
        </el-form-item>
        <el-form-item label="参数名称"
                      prop="parameterName">
          <el-input v-model="paramForm.parameterName"
                    placeholder="请输入参数名称" />
        </el-form-item>
        <el-form-item label="参数模式"
                      prop="parameterType2">
          <el-select v-model="paramForm.parameterType2"
                     placeholder="请选择参数模式">
            <el-option label="单值"
                       value="1" />
            <el-option label="区间"
                       value="2" />
          </el-select>
        </el-form-item>
        <el-form-item label="参数类型"
                      prop="parameterType">
          <el-select v-model="paramForm.parameterType"
                     @change="handleParamTypeChange"
                     placeholder="请选择参数类型">
            <el-option label="数值格式"
                       value="数值格式" />
            <el-option label="文本格式"
                       value="文本格式" />
            <el-option label="下拉选项"
                       value="下拉选项" />
            <el-option label="时间格式"
                       value="时间格式" />
          </el-select>
        </el-form-item>
        <el-form-item v-if="paramForm.parameterType === '下拉选项'"
                      label="数据字典"
                      prop="parameterFormat">
          <el-select v-model="paramForm.parameterFormat"
                     placeholder="请选择数据字典">
            <el-option v-for="item in dictTypes"
                       :key="item.dictType"
                       :label="item.dictName"
                       :value="item.dictType" />
          </el-select>
        </el-form-item>
        <el-form-item v-else-if="paramForm.parameterType === '时间格式'"
                      label="时间格式"
                      prop="parameterFormat">
          <el-select v-model="paramForm.parameterFormat"
                     placeholder="请选择时间格式">
            <el-option label="YYYY-MM-DD HH:mm:ss"
                       value="YYYY-MM-DD HH:mm:ss" />
            <el-option label="YYYY-MM-DD"
                       value="YYYY-MM-DD" />
          </el-select>
        </el-form-item>
        <el-form-item v-else
                      label="参数格式"
                      prop="parameterFormat">
          <el-input v-model="paramForm.parameterFormat"
                    placeholder="请输入参数格式" />
        </el-form-item>
        <el-form-item label="标准值"
                      prop="standardValue">
          <el-input v-model="paramForm.standardValue"
                    placeholder="请输入标准值" />
        </el-form-item>
        <el-form-item label="单位"
                      prop="unit">
          <el-input v-model="paramForm.unit"
                    placeholder="请输入单位" />
        </el-form-item>
      </el-form>
      <template #footer>
        <span class="dialog-footer">
          <el-button @click="paramDialogVisible = false">取消</el-button>
          <el-button type="primary"
                     @click="handleParamSubmit">确定</el-button>
        </span>
      </template>
    </el-dialog>
  </div>
</template>
<script setup>
import {onMounted, ref} from "vue";
import NewProcess from "@/views/productionManagement/processRoute/New.vue";
import EditProcess from "@/views/productionManagement/processRoute/Edit.vue";
import RouteItemForm from "@/views/productionManagement/processRoute/ItemsForm.vue";
import {listPage, del} from "@/api/productionManagement/processRoute.js";
import { useRouter } from 'vue-router'
  import { ref, reactive } from "vue";
  import { ElMessage, ElMessageBox } from "element-plus";
  import {
    Plus,
    Edit,
    Delete,
    ArrowUp,
    ArrowDown,
    Right,
    Search,
    Check,
    Close,
  } from "@element-plus/icons-vue";
  import { listType } from "@/api/system/dict/type";
const router = useRouter()
const data = reactive({
  searchForm: {
    model: "",
  },
});
const { searchForm } = toRefs(data);
const tableColumn = ref([
  {
    label: "工艺路线编号",
    prop: "processRouteCode",
  },
  {
    label: "产品名称",
    prop: "productName",
  },
  {
    label: "规格名称",
    prop: "model",
  },
  {
    label: "BOM编号",
    prop: "bomNo",
  },
  {
    label: "描述",
    prop: "description",
  },
  {
    dataType: "action",
    label: "操作",
    align: "center",
    fixed: "right",
    width: 280,
    operation: [
  // å·¥è‰ºè·¯çº¿åˆ—表
  const routeList = ref([]);
  const dictTypes = ref([]);
  // å·¥è‰ºè·¯çº¿å¯¹è¯æ¡†
  const routeDialogVisible = ref(false);
  const isRouteEdit = ref(false);
  const routeFormRef = ref(null);
  const routeForm = reactive({
    id: null,
    routeCode: "",
    routeName: "",
    routeDesc: "",
    status: "1",
  });
  const routeRules = {
    routeCode: [{ required: true, message: "请输入路线编码", trigger: "blur" }],
    routeName: [{ required: true, message: "请输入路线名称", trigger: "blur" }],
  };
  // å·¥åºå¯¹è¯æ¡†
  const processDialogVisible = ref(false);
  const isProcessEdit = ref(false);
  const processFormRef = ref(null);
  const currentRouteId = ref(null);
  const processForm = reactive({
    id: null,
    processCode: "",
    processName: "",
    processDesc: "",
    status: "1",
  });
  const processRules = {
    processCode: [{ required: true, message: "请输入工序编码", trigger: "blur" }],
    processName: [{ required: true, message: "请输入工序名称", trigger: "blur" }],
  };
  // é€‰æ‹©å·¥åºå¯¹è¯æ¡†
  const selectProcessDialogVisible = ref(false);
  const availableProcessList = ref([]);
  const filteredProcessList = ref([]);
  const selectedProcessItem = ref(null);
  const processSearchKeyword = ref("");
  const currentRouteIndex = ref(null);
  // å‚数对话框
  const paramDialogVisible = ref(false);
  const isParamEdit = ref(false);
  const paramFormRef = ref(null);
  const currentProcessId = ref(null);
  const paramForm = reactive({
    id: null,
    parameterCode: "",
    parameterName: "",
    parameterType2: "1",
    parameterType: "",
    parameterFormat: "",
    standardValue: "",
    unit: "",
  });
  const paramRules = {
    parameterCode: [
      { required: true, message: "请输入参数编号", trigger: "blur" },
    ],
    parameterName: [
      { required: true, message: "请输入参数名称", trigger: "blur" },
    ],
    parameterType: [
      { required: true, message: "请选择参数类型", trigger: "change" },
    ],
  };
  // æ‹–拽相关
  const draggedItem = ref(null);
  const draggedRouteId = ref(null);
  // èŽ·å–å·¥è‰ºè·¯çº¿åˆ—è¡¨
  const getRouteList = () => {
    routeList.value = [
      {
        name: "编辑",
        type: "text",
        clickFun: (row) => {
          showEditModal(row);
        }
        id: 1,
        routeCode: "ROUTE001",
        routeName: "标准砌块生产线",
        routeDesc: "标准砌块生产流程",
        status: "1",
        expanded: false,
        processList: [
          {
            id: 1,
            processCode: "PROC001",
            processName: "原料配比",
            processDesc: "原材料配比工序",
            status: "1",
            expanded: false,
            paramList: [
              {
                id: 1,
                parameterCode: "P001",
                parameterName: "水泥比例",
                parameterType2: "1",
                parameterType: "数值格式",
                parameterFormat: "",
                standardValue: "30",
                unit: "%",
              },
              {
                id: 2,
                parameterCode: "P002",
                parameterName: "砂比例",
                parameterType2: "1",
                parameterType: "数值格式",
                parameterFormat: "",
                standardValue: "60",
                unit: "%",
              },
            ],
          },
          {
            id: 2,
            processCode: "PROC002",
            processName: "搅拌混合",
            processDesc: "搅拌混合工序",
            status: "1",
            expanded: false,
            paramList: [
              {
                id: 3,
                parameterCode: "P003",
                parameterName: "搅拌时间",
                parameterType2: "1",
                parameterType: "数值格式",
                parameterFormat: "",
                standardValue: "5",
                unit: "分钟",
              },
            ],
          },
          {
            id: 3,
            processCode: "PROC003",
            processName: "浇筑成型",
            processDesc: "浇筑成型工序",
            status: "1",
            expanded: false,
            paramList: [],
          },
        ],
      },
      {
        name: "路线项目",
        type: "text",
        clickFun: (row) => {
          showItemModal(row);
        }
        id: 2,
        routeCode: "ROUTE002",
        routeName: "板材生产线",
        routeDesc: "板材生产流程",
        status: "1",
        expanded: false,
        processList: [
          {
            id: 4,
            processCode: "PROC004",
            processName: "切割加工",
            processDesc: "切割加工工序",
            status: "1",
            expanded: false,
            paramList: [
              {
                id: 4,
                parameterCode: "P004",
                parameterName: "切割尺寸",
                parameterType2: "1",
                parameterType: "文本格式",
                parameterFormat: "",
                standardValue: "600x200x100",
                unit: "mm",
              },
            ],
          },
        ],
      },
    ];
  };
  // å±•å¼€/收起工艺路线
  const toggleExpand = route => {
    route.expanded = !route.expanded;
  };
  // å±•å¼€/收起工序参数
  const toggleProcessParams = process => {
    process.expanded = !process.expanded;
  };
  // å·¥è‰ºè·¯çº¿æ“ä½œ
  const handleAddRoute = () => {
    isRouteEdit.value = false;
    routeForm.id = null;
    routeForm.routeCode = "";
    routeForm.routeName = "";
    routeForm.routeDesc = "";
    routeForm.status = "1";
    routeDialogVisible.value = true;
  };
  const handleEditRoute = route => {
    isRouteEdit.value = true;
    routeForm.id = route.id;
    routeForm.routeCode = route.routeCode;
    routeForm.routeName = route.routeName;
    routeForm.routeDesc = route.routeDesc;
    routeForm.status = route.status;
    routeDialogVisible.value = true;
  };
  const handleDeleteRoute = route => {
    ElMessageBox.confirm("确定要删除该工艺路线吗?", "提示", {
      confirmButtonText: "确定",
      cancelButtonText: "取消",
      type: "warning",
    }).then(() => {
      ElMessage.success("删除成功");
      getRouteList();
    });
  };
  const handleRouteSubmit = () => {
    routeFormRef.value.validate(valid => {
      if (valid) {
        ElMessage.success(isRouteEdit.value ? "编辑成功" : "新增成功");
        routeDialogVisible.value = false;
        getRouteList();
      }
    ]
  }
]);
const tableData = ref([]);
const selectedRows = ref([]);
const tableLoading = ref(false);
const isShowNewModal = ref(false);
const isShowEditModal = ref(false);
const isShowItemModal = ref(false);
const record = ref({});
const page = reactive({
  current: 1,
  size: 100,
  total: 0,
});
const { proxy } = getCurrentInstance()
    });
  };
// æŸ¥è¯¢åˆ—表
/** æœç´¢æŒ‰é’®æ“ä½œ */
const handleQuery = () => {
  page.current = 1;
  getList();
};
  const handleApproveRoute = route => {
    ElMessageBox.confirm("确定要批准该工艺路线吗?", "提示", {
      confirmButtonText: "确定",
      cancelButtonText: "取消",
      type: "info",
    }).then(() => {
      route.status = "2";
      ElMessage.success("批准成功");
    });
  };
const pagination = (obj) => {
  page.current = obj.page;
  page.size = obj.limit;
  getList();
};
const getList = () => {
  tableLoading.value = true;
  const params = { ...searchForm.value, ...page };
  params.entryDate = undefined
  listPage(params).then(res => {
    tableLoading.value = false;
    tableData.value = res.data.records.map(item => ({
      ...item,
    }));
    page.total = res.data.total;
  }).catch(err => {
    tableLoading.value = false;
  })
};
// è¡¨æ ¼é€‰æ‹©æ•°æ®
const handleSelectionChange = (selection) => {
  selectedRows.value = selection;
};
  const handleRevokeApproveRoute = route => {
    ElMessageBox.confirm("确定要撤销批准该工艺路线吗?", "提示", {
      confirmButtonText: "确定",
      cancelButtonText: "取消",
      type: "warning",
    }).then(() => {
      route.status = "1";
      ElMessage.success("撤销批准成功");
    });
  };
// æ‰“开新增弹框
const showNewModal = () => {
  isShowNewModal.value = true
};
  // å·¥åºæ“ä½œ
  const handleSelectProcess = (route, index) => {
    currentRouteId.value = route.id;
    currentRouteIndex.value = index;
    // èŽ·å–å¯é€‰å·¥åºåˆ—è¡¨ï¼ˆå‡æ•°æ®ï¼‰
    availableProcessList.value = [
      {
        id: 1,
        processCode: "PROC001",
        processName: "原料配比",
        processDesc: "原材料配比工序",
        status: "1",
        paramCount: 3,
      },
      {
        id: 2,
        processCode: "PROC002",
        processName: "搅拌混合",
        processDesc: "搅拌混合工序",
        status: "1",
        paramCount: 2,
      },
      {
        id: 3,
        processCode: "PROC003",
        processName: "浇筑成型",
        processDesc: "浇筑成型工序",
        status: "1",
        paramCount: 4,
      },
      {
        id: 4,
        processCode: "PROC004",
        processName: "蒸压养护",
        processDesc: "蒸压养护工序",
        status: "0",
        paramCount: 2,
      },
      {
        id: 5,
        processCode: "PROC005",
        processName: "切割加工",
        processDesc: "切割加工工序",
        status: "1",
        paramCount: 3,
      },
    ];
    filteredProcessList.value = availableProcessList.value;
    processSearchKeyword.value = "";
    selectedProcessItem.value = null;
    selectProcessDialogVisible.value = true;
  };
const showEditModal = (row) => {
  isShowEditModal.value = true
  record.value = row
};
  const handleEditProcess = (routeId, process) => {
    currentRouteId.value = routeId;
    isProcessEdit.value = true;
    processForm.id = process.id;
    processForm.processCode = process.processCode;
    processForm.processName = process.processName;
    processForm.processDesc = process.processDesc;
    processForm.status = process.status;
    processDialogVisible.value = true;
  };
const showItemModal = (row) => {
  router.push({
    path: '/productionManagement/processRouteItem',
    query: {
      id: row.id,
      processRouteCode: row.processRouteCode || '',
      productName: row.productName || '',
      model: row.model || '',
      bomNo: row.bomNo || '',
      description: row.description || '',
      type: 'route',
  const handleDeleteProcess = (routeId, process) => {
    ElMessageBox.confirm("确定要删除该工序吗?", "提示", {
      confirmButtonText: "确定",
      cancelButtonText: "取消",
      type: "warning",
    }).then(() => {
      ElMessage.success("删除成功");
      getRouteList();
    });
  };
  const handleProcessSubmit = () => {
    processFormRef.value.validate(valid => {
      if (valid) {
        ElMessage.success(isProcessEdit.value ? "编辑成功" : "新增成功");
        processDialogVisible.value = false;
        getRouteList();
      }
    });
  };
  // é€‰æ‹©å·¥åºç›¸å…³æ–¹æ³•
  const handleProcessSearch = () => {
    const keyword = processSearchKeyword.value.trim().toLowerCase();
    if (!keyword) {
      filteredProcessList.value = availableProcessList.value;
    } else {
      filteredProcessList.value = availableProcessList.value.filter(item =>
        item.processName.toLowerCase().includes(keyword)
      );
    }
  })
};
  };
// åˆ é™¤
function handleDelete() {
  const ids = selectedRows.value.map((item) => item.id);
  proxy.$modal
      .confirm('是否确认删除已勾选的数据项?')
      .then(function () {
        return del(ids);
      })
      .then(() => {
        getList();
        proxy.$modal.msgSuccess("删除成功");
      })
      .catch(() => {});
}
  const handleProcessSelect = row => {
    selectedProcessItem.value = row;
  };
onMounted(() => {
  getList();
});
  const handleProcessSelectSubmit = () => {
    if (!selectedProcessItem.value) {
      ElMessage.warning("请先选择一个工序");
      return;
    }
    // æ£€æŸ¥å·¥åºæ˜¯å¦å·²å­˜åœ¨
    const route = routeList.value[currentRouteIndex.value];
    const exists = route.processList.some(
      p => p.id === selectedProcessItem.value.id
    );
    if (exists) {
      ElMessage.warning("该工序已存在于工艺路线中");
      return;
    }
    // æ·»åŠ å·¥åºåˆ°å·¥è‰ºè·¯çº¿
    const newProcess = {
      id: Date.now(),
      processCode: selectedProcessItem.value.processCode,
      processName: selectedProcessItem.value.processName,
      processDesc: selectedProcessItem.value.processDesc,
      status: selectedProcessItem.value.status,
      paramList: [],
      expanded: false,
    };
    route.processList.push(newProcess);
    ElMessage.success("添加工序成功");
    selectProcessDialogVisible.value = false;
  };
  // å‚数操作
  const handleAddParam = (routeId, process) => {
    currentRouteId.value = routeId;
    currentProcessId.value = process.id;
    isParamEdit.value = false;
    paramForm.id = null;
    paramForm.parameterCode = "";
    paramForm.parameterName = "";
    paramForm.parameterType2 = "1";
    paramForm.parameterType = "";
    paramForm.parameterFormat = "";
    paramForm.standardValue = "";
    paramForm.unit = "";
    paramDialogVisible.value = true;
  };
  const handleEditParam = (routeId, process, param) => {
    currentRouteId.value = routeId;
    currentProcessId.value = process.id;
    isParamEdit.value = true;
    paramForm.id = param.id;
    paramForm.parameterCode = param.parameterCode;
    paramForm.parameterName = param.parameterName;
    paramForm.parameterType2 = param.parameterType2 || "1";
    paramForm.parameterType = param.parameterType;
    paramForm.parameterFormat = param.parameterFormat;
    paramForm.standardValue = param.standardValue;
    paramForm.unit = param.unit;
    paramDialogVisible.value = true;
  };
  const handleDeleteParam = (routeId, process, param) => {
    ElMessageBox.confirm("确定要删除该参数吗?", "提示", {
      confirmButtonText: "确定",
      cancelButtonText: "取消",
      type: "warning",
    }).then(() => {
      ElMessage.success("删除成功");
      getRouteList();
    });
  };
  const handleParamSubmit = () => {
    paramFormRef.value.validate(valid => {
      if (valid) {
        ElMessage.success(isParamEdit.value ? "编辑成功" : "新增成功");
        paramDialogVisible.value = false;
        getRouteList();
      }
    });
  };
  const handleParamTypeChange = () => {
    if (paramForm.parameterType === "数值格式") {
      paramForm.parameterFormat = "#.0000";
    } else if (paramForm.parameterType === "时间格式") {
      paramForm.parameterFormat = "YYYY-MM-DD HH:mm:ss";
    } else {
      paramForm.parameterFormat = "";
    }
  };
  const getParamTypeTag = type => {
    const typeMap = {
      æ•°å€¼æ ¼å¼: "primary",
      æ–‡æœ¬æ ¼å¼: "info",
      ä¸‹æ‹‰é€‰é¡¹: "warning",
      æ—¶é—´æ ¼å¼: "success",
    };
    return typeMap[type] || "default";
  };
  // æ‹–拽排序
  const handleDragStart = (event, index, routeId) => {
    draggedItem.value = index;
    draggedRouteId.value = routeId;
    event.dataTransfer.effectAllowed = "move";
  };
  const handleDragOver = event => {
    event.preventDefault();
    event.dataTransfer.dropEffect = "move";
  };
  const handleDrop = (event, dropIndex, routeId) => {
    event.preventDefault();
    if (draggedItem.value === null || draggedItem.value === dropIndex) return;
    const route = routeList.value.find(r => r.id === routeId);
    if (route && route.processList) {
      const draggedProcess = route.processList[draggedItem.value];
      route.processList.splice(draggedItem.value, 1);
      route.processList.splice(dropIndex, 0, draggedProcess);
      ElMessage.success("排序成功");
    }
  };
  const handleDragEnd = () => {
    draggedItem.value = null;
    draggedRouteId.value = null;
  };
  // èŽ·å–æ•°æ®å­—å…¸
  const getDictTypes = () => {
    listType({ pageNum: 1, pageSize: 1000 }).then(res => {
      dictTypes.value = res.rows || [];
    });
  };
  getRouteList();
  getDictTypes();
</script>
<style scoped></style>
<style scoped lang="scss">
  .app-container {
    padding: 20px;
    background-color: #f0f2f5;
    min-height: calc(100vh - 84px);
  }
  .route-header {
    margin-bottom: 20px;
    .add-route-btn {
      width: 100%;
      display: inline-flex;
      flex-direction: column;
      align-items: center;
      justify-content: center;
      min-width: 120px;
      height: 100px;
      border: 2px dashed #dcdfe6;
      border-radius: 12px;
      background: #fafafa;
      cursor: pointer;
      transition: all 0.3s ease;
      color: #909399;
      padding: 0 20px;
      .el-icon {
        font-size: 24px;
        margin-bottom: 8px;
      }
      span {
        font-size: 13px;
      }
      &:hover {
        border-color: #409eff;
        background: #ecf5ff;
        color: #409eff;
      }
    }
  }
  .route-card-list {
    display: flex;
    flex-direction: column;
    gap: 20px;
  }
  .route-card {
    background: #fff;
    border-radius: 8px;
    box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
    overflow: hidden;
    .card-header {
      display: flex;
      justify-content: space-between;
      align-items: center;
      padding: 20px 40px;
      border-bottom: 1px solid #ebeef5;
      background: #f8f9fa;
      .route-info {
        display: flex;
        // flex-direction: column;
        // justify-content: center;
        // items-align: center;
        gap: 4px;
        .route-code {
          font-size: 12px;
          color: #909399;
          font-family: "Courier New", monospace;
          line-height: 30px;
        }
        .route-name {
          font-size: 18px;
          font-weight: 600;
          color: #303133;
          display: flex;
          align-items: center;
        }
      }
      .route-actions {
        display: flex;
        gap: 8px;
        // .el-button {
        //   color: #409eff;
        // }
      }
    }
    .card-body {
      padding: 16px 40px;
      .route-desc {
        font-size: 14px;
        color: #606266;
        margin-bottom: 12px;
      }
      .expand-icon {
        margin-left: 4px;
      }
    }
    .process-route {
      padding: 0 20px 20px;
      background: #f5f7fa;
      border-top: 1px solid #ebeef5;
      .process-flow {
        display: flex;
        align-items: flex-start;
        gap: 8px;
        padding: 20px 0;
        overflow-x: auto;
        overflow-y: hidden;
        .process-flow-item {
          display: flex;
          align-items: center;
          gap: 8px;
          .process-node {
            background: #fff;
            border-radius: 12px;
            padding: 16px;
            border: 2px solid #ebeef5;
            cursor: move;
            transition: all 0.3s ease;
            // min-width: 180px;
            // max-width: 220px;
            width: 300px;
            &.expanded {
              width: 400px;
            }
            &:hover {
              box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
              transform: translateY(-2px);
              border-color: #409eff;
            }
            &:active {
              cursor: grabbing;
            }
            .process-node-header {
              display: flex;
              justify-content: space-between;
              align-items: center;
              margin-bottom: 12px;
              .process-number {
                width: 28px;
                height: 28px;
                border-radius: 50%;
                background: #409eff;
                color: #ffffff;
                font-size: 12px;
                font-weight: 600;
                display: flex;
                align-items: center;
                justify-content: center;
              }
              .process-actions {
                display: flex;
                gap: 4px;
              }
            }
            .process-node-body {
              text-align: center;
              margin-bottom: 12px;
              .process-code {
                font-size: 11px;
                color: #909399;
                font-family: "Courier New", monospace;
                margin-bottom: 4px;
              }
              .process-name {
                font-size: 15px;
                font-weight: 600;
                color: #303133;
                margin-bottom: 6px;
              }
              .process-desc {
                font-size: 12px;
                color: #606266;
                overflow: hidden;
                text-overflow: ellipsis;
                display: -webkit-box;
                -webkit-line-clamp: 2;
                -webkit-box-orient: vertical;
              }
            }
            .process-node-footer {
              display: flex;
              justify-content: flex-end;
              align-items: center;
              padding-top: 10px;
              border-top: 1px solid #ebeef5;
            }
            .process-params-section {
              margin-top: 12px;
              padding-top: 12px;
              border-top: 1px solid #ebeef5;
              .params-header {
                display: flex;
                justify-content: space-between;
                align-items: center;
                margin-bottom: 8px;
                font-size: 13px;
                font-weight: 600;
                color: #303133;
              }
              .params-list {
                display: flex;
                flex-direction: column;
                gap: 6px;
                max-height: 200px;
                overflow-y: auto;
                .param-item {
                  display: flex;
                  justify-content: space-between;
                  align-items: center;
                  padding: 6px 8px;
                  background: #fafafa;
                  border-radius: 4px;
                  border-left: 2px solid #409eff;
                  font-size: 12px;
                  .param-info {
                    display: flex;
                    flex-direction: row;
                    align-items: center;
                    gap: 6px;
                    flex: 1;
                    min-width: 0;
                    .param-code {
                      font-size: 11px;
                      color: #e6a23c;
                      font-family: "Courier New", monospace;
                      margin-right: 20px;
                    }
                    .param-name {
                      font-size: 12px;
                      color: #303133;
                      font-weight: 500;
                      margin-right: 20px;
                    }
                    .param-value {
                      font-size: 11px;
                      color: #606266;
                    }
                  }
                  .param-actions {
                    display: flex;
                    gap: 4px;
                    flex-shrink: 0;
                  }
                }
              }
            }
          }
          .flow-arrow {
            display: flex;
            align-items: center;
            color: #c0c4cc;
            font-size: 24px;
            padding: 0 4px;
            .el-icon {
              font-size: 20px;
            }
          }
        }
        .add-process-node {
          display: flex;
          flex-direction: column;
          align-items: center;
          justify-content: center;
          min-width: 100px;
          height: 175px;
          border: 2px dashed #dcdfe6;
          border-radius: 12px;
          background: #fafafa;
          cursor: pointer;
          transition: all 0.3s ease;
          color: #909399;
          // margin-left: 10px;
          .el-icon {
            font-size: 24px;
            margin-bottom: 8px;
          }
          span {
            font-size: 13px;
          }
          &:hover {
            border-color: #409eff;
            background: #ecf5ff;
            color: #409eff;
          }
        }
      }
    }
  }
  // æ‹–拽时的样式
  .process-flow-item.dragging {
    opacity: 0.5;
    transform: scale(0.98);
  }
  // é€‰æ‹©å·¥åºå¯¹è¯æ¡†æ ·å¼
  .process-select-container {
    display: flex;
    gap: 20px;
    height: 450px;
    .process-list-area {
      flex: 1;
      display: flex;
      flex-direction: column;
      .area-title {
        font-size: 14px;
        font-weight: 600;
        color: #303133;
        margin-bottom: 12px;
        padding-bottom: 8px;
        border-bottom: 1px solid #ebeef5;
      }
      .search-box {
        margin-bottom: 12px;
        .el-input {
          width: 100%;
        }
      }
    }
    .process-detail-area {
      width: 380px;
      display: flex;
      flex-direction: column;
      background: #f5f7fa;
      border-radius: 8px;
      padding: 16px;
      .area-title {
        font-size: 14px;
        font-weight: 600;
        color: #303133;
        margin-bottom: 16px;
        padding-bottom: 8px;
        border-bottom: 1px solid #ebeef5;
      }
      .process-detail-form {
        .el-form-item {
          margin-bottom: 12px;
          .el-form-item__label {
            color: #606266;
            font-weight: 500;
          }
        }
        .detail-text {
          color: #303133;
          font-weight: 500;
        }
      }
    }
  }
</style>
src/views/productionManagement/processRoute/processRouteItem/index.vue
ÎļþÒÑɾ³ý
src/views/productionManagement/productionProcess/Edit.vue
ÎļþÒÑɾ³ý
src/views/productionManagement/productionProcess/New.vue
ÎļþÒÑɾ³ý
src/views/productionManagement/productionProcess/index.vue
@@ -1,314 +1,997 @@
<template>
  <div class="app-container">
    <div class="search_form">
      <el-form :model="searchForm"
               :inline="true">
        <el-form-item label="工序名称:">
          <el-input v-model="searchForm.name"
                    placeholder="请输入"
                    clearable
                    prefix-icon="Search"
                    style="width: 200px;"
                    @change="handleQuery" />
        </el-form-item>
        <el-form-item label="工序编号:">
          <el-input v-model="searchForm.no"
                    placeholder="请输入"
                    clearable
                    prefix-icon="Search"
                    style="width: 200px;"
                    @change="handleQuery" />
        </el-form-item>
        <el-form-item>
    <div class="process-config-container">
      <!-- å·¦ä¾§å·¥åºåˆ—表 -->
      <div class="process-list-section">
        <div class="section-header">
          <h3 class="section-title">工序列表</h3>
          <el-button type="primary"
                     @click="handleQuery">搜索</el-button>
                     size="small"
                     @click="handleAddProcess">
            <el-icon>
              <Plus />
            </el-icon>新增工序
          </el-button>
        </div>
        <div class="process-card-list">
          <div v-for="process in processList"
               :key="process.id"
               class="process-card"
               :class="{ active: selectedProcess?.id === process.id }"
               @click="selectProcess(process)">
            <div class="card-header">
              <span class="process-code">{{ process.processCode }}</span>
              <div class="card-actions">
                <el-button link
                           type="primary"
                           @click.stop="handleEditProcess(process)">
                  <el-icon>
                    <Edit />
                  </el-icon>
                  ç¼–辑
                </el-button>
                <el-button link
                           type="danger"
                           @click.stop="handleDeleteProcess(process)">
                  <el-icon>
                    <Delete />
                  </el-icon>
                  åˆ é™¤
                </el-button>
              </div>
            </div>
            <div class="card-body">
              <div class="process-name">{{ process.processName }}</div>
              <div class="process-desc">{{ process.processDesc || '暂无描述' }}</div>
            </div>
            <div class="card-footer">
              <el-tag size="small"
                      :type="process.status === '1' ? 'success' : 'info'">
                {{ process.status === '1' ? '启用' : '停用' }}
              </el-tag>
              <span class="param-count">参数: {{ process.paramCount || 0 }}个</span>
            </div>
          </div>
        </div>
      </div>
      <!-- å³ä¾§å‚数列表 -->
      <div class="param-list-section">
        <div class="section-header">
          <h3 class="section-title">
            {{ selectedProcess ? selectedProcess.processName + ' - å‚数配置' : '请选择工序' }}
          </h3>
          <el-button type="primary"
                     size="small"
                     :disabled="!selectedProcess"
                     @click="handleSelectParam">
            <el-icon>
              <Plus />
            </el-icon>选择参数
          </el-button>
        </div>
        <div class="param-table-wrapper">
          <PIMTable v-if="selectedProcess"
                    rowKey="id"
                    :column="paramColumn"
                    :tableData="paramList"
                    :page="paramPage"
                    height="calc(100vh - 280px)"
                    :tableLoading="paramLoading"
                    :isSelection="false"
                    @pagination="handleParamPagination" />
          <div v-else
               class="empty-tip">
            <el-empty description="请从左侧选择一个工序" />
          </div>
        </div>
      </div>
    </div>
    <!-- å·¥åºæ–°å¢ž/编辑对话框 -->
    <el-dialog v-model="processDialogVisible"
               :title="isProcessEdit ? '编辑工序' : '新增工序'"
               width="500px">
      <el-form :model="processForm"
               :rules="processRules"
               ref="processFormRef"
               label-width="100px">
        <el-form-item label="工序编码"
                      prop="processCode">
          <el-input v-model="processForm.processCode"
                    placeholder="请输入工序编码" />
        </el-form-item>
        <el-form-item label="工序名称"
                      prop="processName">
          <el-input v-model="processForm.processName"
                    placeholder="请输入工序名称" />
        </el-form-item>
        <el-form-item label="工序描述"
                      prop="processDesc">
          <el-input v-model="processForm.processDesc"
                    type="textarea"
                    :rows="3"
                    placeholder="请输入工序描述" />
        </el-form-item>
        <el-form-item label="状态"
                      prop="status">
          <el-radio-group v-model="processForm.status">
            <el-radio label="1">启用</el-radio>
            <el-radio label="0">停用</el-radio>
          </el-radio-group>
        </el-form-item>
      </el-form>
    </div>
    <div class="table_list">
      <div style="text-align: right"
           class="mb10">
        <el-button type="primary"
                   @click="showNewModal">新增工序</el-button>
        <el-button type="info"
                   plain
                   @click="handleImport">导入</el-button>
        <el-button type="danger"
                   @click="handleDelete"
                   :disabled="selectedRows.length === 0"
                   plain>删除工序</el-button>
      <template #footer>
        <span class="dialog-footer">
          <el-button @click="processDialogVisible = false">取消</el-button>
          <el-button type="primary"
                     @click="handleProcessSubmit">确定</el-button>
        </span>
      </template>
    </el-dialog>
    <!-- é€‰æ‹©å‚数对话框 -->
    <el-dialog v-model="paramDialogVisible"
               title="选择参数"
               width="1000px">
      <div class="param-select-container">
        <!-- å·¦ä¾§å‚数列表 -->
        <div class="param-list-area">
          <div class="area-title">可选参数</div>
          <div class="search-box">
            <el-input v-model="paramSearchKeyword"
                      placeholder="请输入参数名称搜索"
                      clearable
                      size="small"
                      @input="handleParamSearch">
              <template #prefix>
                <el-icon>
                  <Search />
                </el-icon>
              </template>
            </el-input>
          </div>
          <el-table :data="filteredParamList"
                    height="360"
                    border
                    highlight-current-row
                    @current-change="handleParamSelect">
            <el-table-column prop="parameterCode"
                             label="参数编号"
                             width="100" />
            <el-table-column prop="parameterName"
                             label="参数名称" />
            <el-table-column prop="parameterType"
                             label="参数类型"
                             width="100">
              <template #default="scope">
                <el-tag size="small"
                        :type="getParamTypeTag(scope.row.parameterType)">
                  {{ scope.row.parameterType }}
                </el-tag>
              </template>
            </el-table-column>
          </el-table>
        </div>
        <!-- å³ä¾§å‚数详情 -->
        <div class="param-detail-area">
          <div class="area-title">参数详情</div>
          <el-form v-if="selectedParam"
                   :model="selectedParam"
                   label-width="100px"
                   class="param-detail-form">
            <el-form-item label="参数编号">
              <span class="detail-text">{{ selectedParam.parameterCode }}</span>
            </el-form-item>
            <el-form-item label="参数名称">
              <span class="detail-text">{{ selectedParam.parameterName }}</span>
            </el-form-item>
            <el-form-item label="参数模式">
              <el-tag size="small"
                      :type="selectedParam.parameterType2 === '1' ? 'success' : 'warning'">
                {{ selectedParam.parameterType2 === '1' ? '单值' : '区间' }}
              </el-tag>
            </el-form-item>
            <el-form-item label="参数类型">
              <el-tag size="small"
                      :type="getParamTypeTag(selectedParam.parameterType)">
                {{ selectedParam.parameterType }}
              </el-tag>
            </el-form-item>
            <el-form-item label="参数格式">
              <span class="detail-text">{{ selectedParam.parameterFormat || '-' }}</span>
            </el-form-item>
            <el-form-item label="标准值">
              <span class="detail-text">{{ selectedParam.standardValue }}</span>
            </el-form-item>
            <el-form-item label="单位">
              <span class="detail-text">{{ selectedParam.unit || '-' }}</span>
            </el-form-item>
          </el-form>
          <el-empty v-else
                    description="请从左侧选择参数" />
        </div>
      </div>
      <PIMTable rowKey="id"
                :column="tableColumn"
                :tableData="tableData"
                :page="page"
                :isSelection="true"
                @selection-change="handleSelectionChange"
                :tableLoading="tableLoading"
                @pagination="pagination"
                :total="page.total"></PIMTable>
    </div>
    <new-process v-if="isShowNewModal"
                 v-model:visible="isShowNewModal"
                 @completed="getList" />
    <edit-process v-if="isShowEditModal"
                  v-model:visible="isShowEditModal"
                  :record="record"
                  @completed="getList" />
    <ImportDialog ref="importDialogRef"
                  v-model="importDialogVisible"
                  title="导入工序"
                  :action="importAction"
                  :headers="importHeaders"
                  :auto-upload="false"
                  :on-success="handleImportSuccess"
                  :on-error="handleImportError"
                  @confirm="handleImportConfirm"
                  @download-template="handleDownloadTemplate"
                  @close="handleImportClose" />
      <template #footer>
        <span class="dialog-footer">
          <el-button @click="paramDialogVisible = false">取消</el-button>
          <el-button type="primary"
                     :disabled="!selectedParam"
                     @click="handleParamSubmit">确定</el-button>
        </span>
      </template>
    </el-dialog>
  </div>
</template>
<script setup>
  import { onMounted, ref, reactive, toRefs, getCurrentInstance } from "vue";
  import NewProcess from "@/views/productionManagement/productionProcess/New.vue";
  import EditProcess from "@/views/productionManagement/productionProcess/Edit.vue";
  import ImportDialog from "@/components/Dialog/ImportDialog.vue";
  import {
    listPage,
    del,
    importData,
    downloadTemplate,
  } from "@/api/productionManagement/productionProcess.js";
  import { getToken } from "@/utils/auth";
  import { ref, reactive, onMounted } from "vue";
  import { ElMessage, ElMessageBox } from "element-plus";
  import { Plus, Edit, Delete, Search } from "@element-plus/icons-vue";
  import PIMTable from "@/components/PIMTable/PIMTable.vue";
  import { listType } from "@/api/system/dict/type";
  const data = reactive({
    searchForm: {
      name: "",
      no: "",
    },
  // å·¥åºåˆ—表数据
  const processList = ref([]);
  const selectedProcess = ref(null);
  const processLoading = ref(false);
  // å‚数列表数据
  const paramList = ref([]);
  const paramLoading = ref(false);
  const paramPage = reactive({
    current: 1,
    size: 10,
    total: 0,
  });
  const { searchForm } = toRefs(data);
  const tableColumn = ref([
  // æ•°æ®å­—å…¸
  const dictTypes = ref([]);
  // å·¥åºå¯¹è¯æ¡†
  const processDialogVisible = ref(false);
  const isProcessEdit = ref(false);
  const processFormRef = ref(null);
  const processForm = reactive({
    id: null,
    processCode: "",
    processName: "",
    processDesc: "",
    status: "1",
  });
  const processRules = {
    processCode: [{ required: true, message: "请输入工序编码", trigger: "blur" }],
    processName: [{ required: true, message: "请输入工序名称", trigger: "blur" }],
  };
  // å‚数对话框
  const paramDialogVisible = ref(false);
  const availableParamList = ref([]);
  const filteredParamList = ref([]);
  const selectedParam = ref(null);
  const paramSearchKeyword = ref("");
  // å‚数表格列配置
  const paramColumn = ref([
    {
      label: "工序编号",
      prop: "no",
      label: "参数编号",
      prop: "parameterCode",
      className: "code-cell",
    },
    {
      label: "工序名称",
      prop: "name",
      label: "参数名称",
      prop: "parameterName",
    },
    {
      label: "工资定额",
      prop: "salaryQuota",
      label: "参数模式",
      prop: "parameterType2",
      dataType: "tag",
      formatType: row => (row.parameterType2 === "1" ? "success" : "warning"),
      formatData: row => (row.parameterType2 === "1" ? "单值" : "区间"),
    },
    {
      label: "是否质检",
      prop: "isQuality",
      formatData: (params) => {
        return params ? "是" : "否";
      label: "参数类型",
      prop: "parameterType",
      dataType: "tag",
      formatType: row => {
        const typeMap = {
          æ•°å€¼æ ¼å¼: "primary",
          æ–‡æœ¬æ ¼å¼: "info",
          ä¸‹æ‹‰é€‰é¡¹: "warning",
          æ—¶é—´æ ¼å¼: "success",
        };
        return typeMap[row.parameterType] || "default";
      },
    },
    {
      label: "备注",
      prop: "remark",
      label: "参数格式",
      prop: "parameterFormat",
    },
    {
      label: "更新时间",
      prop: "updateTime",
      label: "标准值",
      prop: "standardValue",
      className: row => (row.parameterType === "数值格式" ? "quantity-cell" : ""),
    },
    {
      dataType: "action",
      label: "单位",
      prop: "unit",
    },
    {
      label: "操作",
      align: "center",
      fixed: "right",
      width: 280,
      dataType: "action",
      width: "100",
      operation: [
        {
          name: "编辑",
          type: "text",
          clickFun: row => {
            showEditModal(row);
          },
          name: "删除",
          clickFun: row => handleDeleteParam(row),
        },
      ],
    },
  ]);
  const tableData = ref([]);
  const selectedRows = ref([]);
  const tableLoading = ref(false);
  const isShowNewModal = ref(false);
  const isShowEditModal = ref(false);
  const record = ref({});
  const importDialogVisible = ref(false);
  const importDialogRef = ref(null);
  const page = reactive({
    current: 1,
    size: 100,
    total: 0,
  });
  const { proxy } = getCurrentInstance();
  // å¯¼å…¥ç›¸å…³é…ç½®
  const importAction =
    import.meta.env.VITE_APP_BASE_API + "/productProcess/importData";
  const importHeaders = { Authorization: "Bearer " + getToken() };
  // æŸ¥è¯¢åˆ—表
  /** æœç´¢æŒ‰é’®æ“ä½œ */
  const handleQuery = () => {
    page.current = 1;
    getList();
  // èŽ·å–å·¥åºåˆ—è¡¨
  const getProcessList = () => {
    // å‡æ•°æ®
    processList.value = [
      {
        id: 1,
        processCode: "PROC001",
        processName: "原料配比",
        processDesc: "原材料配比工序",
        status: "1",
        paramCount: 3,
      },
      {
        id: 2,
        processCode: "PROC002",
        processName: "搅拌混合",
        processDesc: "搅拌混合工序",
        status: "1",
        paramCount: 2,
      },
      {
        id: 3,
        processCode: "PROC003",
        processName: "浇筑成型",
        processDesc: "浇筑成型工序",
        status: "1",
        paramCount: 4,
      },
      {
        id: 4,
        processCode: "PROC004",
        processName: "蒸压养护",
        processDesc: "蒸压养护工序",
        status: "0",
        paramCount: 2,
      },
      {
        id: 5,
        processCode: "PROC005",
        processName: "切割加工",
        processDesc: "切割加工工序",
        status: "1",
        paramCount: 3,
      },
    ];
  };
  const pagination = obj => {
    page.current = obj.page;
    page.size = obj.limit;
    getList();
  };
  const getList = () => {
    tableLoading.value = true;
    const params = { ...searchForm.value, ...page };
    params.entryDate = undefined;
    listPage(params)
      .then(res => {
        tableLoading.value = false;
        tableData.value = res.data.records.map(item => ({
          ...item,
        }));
        page.total = res.data.total;
      })
      .catch(err => {
        tableLoading.value = false;
      });
  };
  // è¡¨æ ¼é€‰æ‹©æ•°æ®
  const handleSelectionChange = selection => {
    selectedRows.value = selection;
  // èŽ·å–å‚æ•°åˆ—è¡¨
  const getParamList = processId => {
    paramLoading.value = true;
    // å‡æ•°æ®
    setTimeout(() => {
      paramLoading.value = false;
      const mockData = {
        1: [
          {
            id: 1,
            parameterCode: "P001",
            parameterName: "水泥比例",
            parameterType2: "1",
            parameterType: "数值格式",
            parameterFormat: "",
            standardValue: "30",
            unit: "%",
          },
          {
            id: 2,
            parameterCode: "P002",
            parameterName: "砂比例",
            parameterType2: "1",
            parameterType: "数值格式",
            parameterFormat: "",
            standardValue: "60",
            unit: "%",
          },
          {
            id: 3,
            parameterCode: "P003",
            parameterName: "水比例",
            parameterType2: "1",
            parameterType: "数值格式",
            parameterFormat: "",
            standardValue: "10",
            unit: "%",
          },
        ],
        2: [
          {
            id: 4,
            parameterCode: "P004",
            parameterName: "搅拌时间",
            parameterType2: "1",
            parameterType: "数值格式",
            parameterFormat: "",
            standardValue: "5",
            unit: "分钟",
          },
          {
            id: 5,
            parameterCode: "P005",
            parameterName: "搅拌速度",
            parameterType2: "2",
            parameterType: "数值格式",
            parameterFormat: "",
            standardValue: "100-200",
            unit: "rpm",
          },
        ],
        3: [
          {
            id: 6,
            parameterCode: "P006",
            parameterName: "浇筑温度",
            parameterType2: "2",
            parameterType: "数值格式",
            parameterFormat: "",
            standardValue: "20-30",
            unit: "℃",
          },
          {
            id: 7,
            parameterCode: "P007",
            parameterName: "浇筑压力",
            parameterType2: "1",
            parameterType: "数值格式",
            parameterFormat: "",
            standardValue: "0.5",
            unit: "MPa",
          },
          {
            id: 8,
            parameterCode: "P008",
            parameterName: "成型状态",
            parameterType2: "1",
            parameterType: "下拉选项",
            parameterFormat: "status",
            standardValue: "正常",
            unit: "",
          },
          {
            id: 9,
            parameterCode: "P009",
            parameterName: "成型时间",
            parameterType2: "1",
            parameterType: "时间格式",
            parameterFormat: "YYYY-MM-DD HH:mm:ss",
            standardValue: "2024-01-01 08:00:00",
            unit: "",
          },
        ],
        4: [
          {
            id: 10,
            parameterCode: "P010",
            parameterName: "蒸压温度",
            parameterType2: "2",
            parameterType: "数值格式",
            parameterFormat: "",
            standardValue: "180-200",
            unit: "℃",
          },
          {
            id: 11,
            parameterCode: "P011",
            parameterName: "蒸压压力",
            parameterType2: "1",
            parameterType: "数值格式",
            parameterFormat: "",
            standardValue: "1.2",
            unit: "MPa",
          },
        ],
        5: [
          {
            id: 12,
            parameterCode: "P012",
            parameterName: "切割尺寸",
            parameterType2: "1",
            parameterType: "文本格式",
            parameterFormat: "",
            standardValue: "600x200x100",
            unit: "mm",
          },
          {
            id: 13,
            parameterCode: "P013",
            parameterName: "切割精度",
            parameterType2: "1",
            parameterType: "数值格式",
            parameterFormat: "",
            standardValue: "±1",
            unit: "mm",
          },
          {
            id: 14,
            parameterCode: "P014",
            parameterName: "切割速度",
            parameterType2: "1",
            parameterType: "数值格式",
            parameterFormat: "",
            standardValue: "2",
            unit: "m/min",
          },
        ],
      };
      paramList.value = mockData[processId] || [];
      paramPage.total = paramList.value.length;
    }, 300);
  };
  // æ‰“开新增弹框
  const showNewModal = () => {
    isShowNewModal.value = true;
  // é€‰æ‹©å·¥åº
  const selectProcess = process => {
    selectedProcess.value = process;
    getParamList(process.id);
  };
  const showEditModal = row => {
    isShowEditModal.value = true;
    record.value = row;
  // å·¥åºæ“ä½œ
  const handleAddProcess = () => {
    isProcessEdit.value = false;
    processForm.id = null;
    processForm.processCode = "";
    processForm.processName = "";
    processForm.processDesc = "";
    processForm.status = "1";
    processDialogVisible.value = true;
  };
  // åˆ é™¤
  function handleDelete() {
    const no = selectedRows.value.map(item => item.no);
    const ids = selectedRows.value.map(item => item.id);
    if (no.length > 2) {
      proxy.$modal
        .confirm(
          '是否确认删除工序编号为"' +
            no[0] +
            "、" +
            no[1] +
            '"等' +
            no.length +
            "条数据项?"
        )
        .then(function () {
          return del(ids);
        })
        .then(() => {
          getList();
          proxy.$modal.msgSuccess("删除成功");
        })
        .catch(() => {});
    } else {
      proxy.$modal
        .confirm('是否确认删除工序编号为"' + no + '"的数据项?')
        .then(function () {
          return del(ids);
        })
        .then(() => {
          getList();
          proxy.$modal.msgSuccess("删除成功");
        })
        .catch(() => {});
    }
  }
  // å¯¼å…¥
  const handleImport = () => {
    importDialogVisible.value = true;
  const handleEditProcess = process => {
    isProcessEdit.value = true;
    processForm.id = process.id;
    processForm.processCode = process.processCode;
    processForm.processName = process.processName;
    processForm.processDesc = process.processDesc;
    processForm.status = process.status;
    processDialogVisible.value = true;
  };
  // ç¡®è®¤å¯¼å…¥
  const handleImportConfirm = () => {
    if (importDialogRef.value) {
      importDialogRef.value.submit();
    }
  };
  // å¯¼å…¥æˆåŠŸ
  const handleImportSuccess = response => {
    if (response.code === 200) {
      proxy.$modal.msgSuccess("导入成功");
      importDialogVisible.value = false;
      if (importDialogRef.value) {
        importDialogRef.value.clearFiles();
  const handleDeleteProcess = process => {
    ElMessageBox.confirm("确定要删除该工序吗?", "提示", {
      confirmButtonText: "确定",
      cancelButtonText: "取消",
      type: "warning",
    }).then(() => {
      ElMessage.success("删除成功");
      getProcessList();
      if (selectedProcess.value?.id === process.id) {
        selectedProcess.value = null;
        paramList.value = [];
      }
      getList();
    });
  };
  const handleProcessSubmit = () => {
    processFormRef.value.validate(valid => {
      if (valid) {
        ElMessage.success(isProcessEdit.value ? "编辑成功" : "新增成功");
        processDialogVisible.value = false;
        getProcessList();
      }
    });
  };
  // å‚数操作
  const handleSelectParam = () => {
    if (!selectedProcess.value) {
      ElMessage.warning("请先选择一个工序");
      return;
    }
    // èŽ·å–å¯é€‰å‚æ•°åˆ—è¡¨ï¼ˆå‡æ•°æ®ï¼‰
    availableParamList.value = [
      {
        id: 101,
        parameterCode: "P101",
        parameterName: "温度",
        parameterType2: "2",
        parameterType: "数值格式",
        parameterFormat: "",
        standardValue: "20-30",
        unit: "℃",
      },
      {
        id: 102,
        parameterCode: "P102",
        parameterName: "压力",
        parameterType2: "1",
        parameterType: "数值格式",
        parameterFormat: "",
        standardValue: "0.5",
        unit: "MPa",
      },
      {
        id: 103,
        parameterCode: "P103",
        parameterName: "湿度",
        parameterType2: "2",
        parameterType: "数值格式",
        parameterFormat: "",
        standardValue: "40-60",
        unit: "%",
      },
      {
        id: 104,
        parameterCode: "P104",
        parameterName: "速度",
        parameterType2: "1",
        parameterType: "数值格式",
        parameterFormat: "",
        standardValue: "100",
        unit: "m/min",
      },
      {
        id: 105,
        parameterCode: "P105",
        parameterName: "状态",
        parameterType2: "1",
        parameterType: "下拉选项",
        parameterFormat: "status",
        standardValue: "正常",
        unit: "",
      },
      {
        id: 106,
        parameterCode: "P106",
        parameterName: "记录时间",
        parameterType2: "1",
        parameterType: "时间格式",
        parameterFormat: "YYYY-MM-DD HH:mm:ss",
        standardValue: "2024-01-01 08:00:00",
        unit: "",
      },
      {
        id: 107,
        parameterCode: "P107",
        parameterName: "备注",
        parameterType2: "1",
        parameterType: "文本格式",
        parameterFormat: "",
        standardValue: "无",
        unit: "",
      },
    ];
    filteredParamList.value = availableParamList.value;
    paramSearchKeyword.value = "";
    selectedParam.value = null;
    paramDialogVisible.value = true;
  };
  const handleParamSelect = row => {
    selectedParam.value = row;
  };
  const handleParamSearch = () => {
    const keyword = paramSearchKeyword.value.trim().toLowerCase();
    if (!keyword) {
      filteredParamList.value = availableParamList.value;
    } else {
      proxy.$modal.msgError(response.msg || "导入失败");
      filteredParamList.value = availableParamList.value.filter(item =>
        item.parameterName.toLowerCase().includes(keyword)
      );
    }
  };
  // å¯¼å…¥å¤±è´¥
  const handleImportError = error => {
    proxy.$modal.msgError("导入失败:" + (error.message || "未知错误"));
  const getParamTypeTag = type => {
    const typeMap = {
      æ•°å€¼æ ¼å¼: "primary",
      æ–‡æœ¬æ ¼å¼: "info",
      ä¸‹æ‹‰é€‰é¡¹: "warning",
      æ—¶é—´æ ¼å¼: "success",
    };
    return typeMap[type] || "default";
  };
  // å…³é—­å¯¼å…¥å¼¹çª—
  const handleImportClose = () => {
    if (importDialogRef.value) {
      importDialogRef.value.clearFiles();
  const handleDeleteParam = row => {
    ElMessageBox.confirm("确定要删除该参数吗?", "提示", {
      confirmButtonText: "确定",
      cancelButtonText: "取消",
      type: "warning",
    }).then(() => {
      ElMessage.success("删除成功");
      getParamList(selectedProcess.value.id);
    });
  };
  const handleParamSubmit = () => {
    if (!selectedParam.value) {
      ElMessage.warning("请先选择一个参数");
      return;
    }
    ElMessage.success("添加成功");
    paramDialogVisible.value = false;
    getParamList(selectedProcess.value.id);
  };
  // ä¸‹è½½æ¨¡æ¿
  const handleDownloadTemplate = async () => {
    try {
      const res = await downloadTemplate();
      const blob = new Blob([res], {
        type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
      });
      const url = window.URL.createObjectURL(blob);
      const link = document.createElement("a");
      link.href = url;
      link.download = "工序导入模板.xlsx";
      link.click();
      window.URL.revokeObjectURL(url);
      proxy.$modal.msgSuccess("模板下载成功");
    } catch (error) {
      proxy.$modal.msgError("模板下载失败");
    }
  const handleParamPagination = obj => {
    paramPage.current = obj.page;
    paramPage.size = obj.limit;
    getParamList(selectedProcess.value.id);
  };
  // å¯¼å‡º
  // const handleOut = () => {
  //     ElMessageBox.confirm("选中的内容将被导出,是否确认导出?", "导出", {
  //         confirmButtonText: "确认",
  //         cancelButtonText: "取消",
  //         type: "warning",
  //     })
  //         .then(() => {
  //             proxy.download("/salesLedger/scheduling/exportTwo", {}, "工序排产.xlsx");
  //         })
  //         .catch(() => {
  //             proxy.$modal.msg("已取消");
  //         });
  // };
  // èŽ·å–æ•°æ®å­—å…¸
  const getDictTypes = () => {
    listType({ pageNum: 1, pageSize: 1000 }).then(res => {
      dictTypes.value = res.rows || [];
    });
  };
  onMounted(() => {
    getList();
    getProcessList();
    getDictTypes();
  });
</script>
<style scoped></style>
<style scoped lang="scss">
  .app-container {
    padding: 20px;
    background-color: #f0f2f5;
    min-height: calc(100vh - 84px);
  }
  .process-config-container {
    display: flex;
    gap: 20px;
    height: calc(100vh - 124px);
  }
  // å·¦ä¾§å·¥åºåˆ—表
  .process-list-section {
    width: 370px;
    background: #fff;
    border-radius: 8px;
    box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
    display: flex;
    flex-direction: column;
  }
  .section-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 16px 20px;
    border-bottom: 1px solid #ebeef5;
    .section-title {
      margin: 0;
      font-size: 16px;
      font-weight: 600;
      color: #303133;
    }
  }
  .process-card-list {
    flex: 1;
    overflow-y: auto;
    padding: 16px;
  }
  .process-card {
    background: #fff;
    border: 1px solid #ebeef5;
    border-radius: 8px;
    padding: 16px;
    margin-bottom: 12px;
    cursor: pointer;
    transition: all 0.3s ease;
    &:hover {
      box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
      transform: translateY(-2px);
    }
    &.active {
      border-color: #409eff;
      background: #f5f7fa;
      box-shadow: 0 4px 12px rgba(64, 158, 255, 0.2);
    }
    .card-header {
      display: flex;
      justify-content: space-between;
      align-items: center;
      margin-bottom: 8px;
      .process-code {
        font-size: 12px;
        color: #909399;
        font-family: "Courier New", monospace;
      }
      .card-actions {
        display: flex;
        gap: 4px;
        .el-button {
          padding: 4px;
        }
      }
    }
    .card-body {
      margin-bottom: 12px;
      .process-name {
        font-size: 16px;
        font-weight: 600;
        color: #303133;
        margin-bottom: 4px;
      }
      .process-desc {
        font-size: 12px;
        color: #909399;
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
      }
    }
    .card-footer {
      display: flex;
      justify-content: space-between;
      align-items: center;
      .param-count {
        font-size: 12px;
        color: #606266;
      }
    }
  }
  // å³ä¾§å‚数列表
  .param-list-section {
    flex: 1;
    background: #fff;
    border-radius: 8px;
    box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
    display: flex;
    flex-direction: column;
  }
  .param-table-wrapper {
    flex: 1;
    padding: 0 20px 20px;
    overflow: hidden;
  }
  .empty-tip {
    flex: 1;
    display: flex;
    align-items: center;
    justify-content: center;
  }
  // è¡¨æ ¼æ ·å¼
  :deep(.el-table) {
    border: none;
    border-radius: 6px;
    overflow: hidden;
    .el-table__header-wrapper {
      background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
      th {
        background: transparent;
        font-weight: 600;
        color: #ffffff;
        border-bottom: none;
        padding: 16px 0;
      }
    }
    .el-table__body-wrapper {
      tr {
        transition: all 0.3s ease;
        &:hover {
          background: linear-gradient(
            90deg,
            rgba(102, 126, 234, 0.05) 0%,
            rgba(118, 75, 162, 0.05) 100%
          );
        }
        td {
          border-bottom: 1px solid #f0f0f0;
          padding: 14px 0;
          color: #303133;
        }
      }
    }
  }
  // ç¼–码单元格样式
  :deep(.code-cell) {
    color: #e6a23c;
    font-family: "Courier New", monospace;
    font-weight: 500;
  }
  // æ•°å€¼å•元格样式
  :deep(.quantity-cell) {
    font-weight: 600;
    color: #409eff;
    font-family: "Courier New", monospace;
  }
  // é€‰æ‹©å‚数对话框样式
  .param-select-container {
    display: flex;
    gap: 20px;
    height: 450px;
    .param-list-area {
      flex: 1;
      display: flex;
      flex-direction: column;
      .area-title {
        font-size: 14px;
        font-weight: 600;
        color: #303133;
        margin-bottom: 12px;
        padding-bottom: 8px;
        border-bottom: 1px solid #ebeef5;
      }
      .search-box {
        margin-bottom: 12px;
        .el-input {
          width: 100%;
        }
      }
    }
    .param-detail-area {
      width: 380px;
      display: flex;
      flex-direction: column;
      background: #f5f7fa;
      border-radius: 8px;
      padding: 16px;
      .area-title {
        font-size: 14px;
        font-weight: 600;
        color: #303133;
        margin-bottom: 16px;
        padding-bottom: 8px;
        border-bottom: 1px solid #ebeef5;
      }
      .param-detail-form {
        .el-form-item {
          margin-bottom: 12px;
          .el-form-item__label {
            color: #606266;
            font-weight: 500;
          }
        }
        .detail-text {
          color: #303133;
          font-weight: 500;
        }
      }
    }
  }
</style>