gaoluyang
2026-06-16 ffe58e0cf73fa61d8b05de09645c5d8d89007ce5
src/views/productionManagement/productionProcess/index.vue
@@ -44,7 +44,7 @@
            <div class="card-body">
              <!-- <div class="process-name">{{ process.name }}</div> -->
              <div class="process-desc">{{ process.remark || '暂无描述' }}</div>
              <div class="process-device">关联设备: {{ deviceOptions.find(item => item.id === Number(process.deviceLedgerId))?.deviceName|| '未关联' }}</div>
              <div class="process-device">关联设备: {{ (deviceOptions.find(item => item.id === Number(process.deviceLedgerId))?.deviceName) || '未关联' }}</div>
            </div>
            <div class="card-footer">
              <div class="status-tag">
@@ -52,14 +52,13 @@
                        :type="process.isQuality ? 'warning' : 'info'">
                  {{ process.isQuality ? '质检' : '非质检' }}
                </el-tag>
                <el-tag v-if="process.type !== null && process.type !== undefined"
                        size="small"
                        :type="process.type == 1 ? 'primary' : 'success'"
                        style="margin-left: 8px">
                  {{ process.type == 0 ? '计时' : '计件' }}
                <el-tag size="small"
                        style="margin-left: 8px"
                        :type="process.isProduction ? 'warning' : 'info'">
                  {{ process.isProduction ? '生产' : '不生产' }}
                </el-tag>
              </div>
              <span class="param-count">工资定额: ¥{{ process.salaryQuota || 0 }}</span>
              <span class="param-count">计划工时: {{ process.salaryQuota || 0 }}小时</span>
            </div>
          </div>
        </div>
@@ -96,39 +95,76 @@
      </div>
    </div>
    <!-- 工序新增/编辑对话框 -->
    <el-dialog v-model="processDialogVisible"
               :title="isProcessEdit ? '编辑工序' : '新增工序'"
               width="500px">
    <FormDialog v-model="processDialogVisible"
                :title="isProcessEdit ? '编辑部件' : '新增部件'"
                width="600"
                @confirm="handleProcessSubmit"
                @cancel="processDialogVisible = false">
      <el-form :model="processForm"
               :rules="processRules"
               ref="processFormRef"
               label-width="100px">
        <el-form-item label="工序编码"
                      prop="no">
          <el-input v-model="processForm.no"
                    placeholder="请输入工序编码" />
        </el-form-item>
        <el-form-item label="工序名称"
               label-width="120px">
        <el-form-item label="部件名称"
                      prop="name">
          <el-input v-model="processForm.name"
                    placeholder="请输入工序名称" />
                    placeholder="请输入部件名称" />
        </el-form-item>
        <el-form-item label="工资定额"
            <el-form-item label="部件编号"
                       prop="no">
               <el-input v-model="processForm.no"
                      placeholder="请输入部件编号" />
            </el-form-item>
        <el-form-item label="部件类型"
                      prop="processType">
          <el-select v-model="processForm.processType"
                     placeholder="请选择部件类型"
                     style="width: 100%">
            <el-option v-for="item in processTypeOptions"
                       :key="item"
                       :label="item"
                       :value="item" />
          </el-select>
        </el-form-item>
        <el-form-item label="计划工时(小时)"
                      prop="salaryQuota">
          <el-input v-model="processForm.salaryQuota"
                    type="number"
                    :step="0.001" />
                    :step="0.5"
                    placeholder="请输入计划工时" />
        </el-form-item>
        <el-form-item label="计划人员"
                      prop="planPerson">
          <el-select v-model="processForm.planPerson"
                     placeholder="请选择计划人员"
                     clearable
                     filterable
                     style="width: 100%">
            <el-option v-for="item in employeeOptions"
                       :key="item.id"
                       :label="item.staffName"
                       :value="item.id" />
          </el-select>
        </el-form-item>
        <el-form-item label="计划执行人员"
                      prop="executor">
          <el-select v-model="processForm.executor"
                     placeholder="请选择计划执行人员"
                     clearable
                     filterable
                     style="width: 100%">
            <el-option v-for="item in employeeOptions"
                       :key="item.id"
                       :label="item.staffName"
                       :value="item.id" />
          </el-select>
        </el-form-item>
        <el-form-item label="是否质检"
                      prop="isQuality">
          <el-switch v-model="processForm.isQuality" />
        </el-form-item>
        <el-form-item label="计费类型"
                      prop="type">
          <el-radio-group v-model="processForm.type">
            <el-radio :label="0">计时</el-radio>
            <el-radio :label="1">计件</el-radio>
          </el-radio-group>
        <el-form-item label="是否生产"
                      prop="isProduction">
          <el-switch v-model="processForm.isProduction" />
        </el-form-item>
        <el-form-item label="关联设备"
                      prop="deviceLedgerId">
@@ -151,18 +187,11 @@
                    placeholder="请输入工序描述" />
        </el-form-item>
      </el-form>
      <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>
    </FormDialog>
    <!-- 选择参数对话框 -->
    <el-dialog v-model="paramDialogVisible"
               title="选择参数"
               width="1000px">
    <FormDialog v-model="paramDialogVisible"
                title="选择参数"
                width="1000px">
      <div class="param-select-container">
        <!-- 左侧参数列表 -->
        <div class="param-list-area">
@@ -234,6 +263,7 @@
            </el-form-item>
            <el-form-item label="标准值">
              <el-input v-model="selectedParam.standardValue"
                        @input="val => onStandardValueInput(val, selectedParam)"
                        placeholder="请输入默认值" />
            </el-form-item>
          </el-form>
@@ -243,13 +273,13 @@
      </div>
      <template #footer>
        <span class="dialog-footer">
          <el-button @click="paramDialogVisible = false">取消</el-button>
          <el-button type="primary"
                     :disabled="!selectedParam"
                     @click="handleParamSubmit">确定</el-button>
          <el-button @click="paramDialogVisible = false">取消</el-button>
        </span>
      </template>
    </el-dialog>
    </FormDialog>
    <!-- 编辑参数对话框 -->
    <el-dialog v-model="editParamDialogVisible"
               title="编辑参数"
@@ -264,14 +294,15 @@
        <el-form-item label="标准值"
                      prop="standardValue">
          <el-input v-model="editParamForm.standardValue"
                    @input="val => onStandardValueInput(val, editParamForm)"
                    placeholder="请输入标准值" />
        </el-form-item>
      </el-form>
      <template #footer>
        <span class="dialog-footer">
          <el-button @click="editParamDialogVisible = false">取消</el-button>
          <el-button type="primary"
                     @click="handleEditParamSubmit">确定</el-button>
          <el-button @click="editParamDialogVisible = false">取消</el-button>
        </span>
      </template>
    </el-dialog>
@@ -279,7 +310,7 @@
</template>
<script setup>
  import { ref, reactive, onMounted } from "vue";
  import { ref, reactive, computed, 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";
@@ -297,6 +328,18 @@
  } from "@/api/productionManagement/productionProcess.js";
  import { getDeviceLedger } from "@/api/equipmentManagement/ledger";
  import { getBaseParamList } from "@/api/basicData/parameterMaintenance.js";
  import { staffOnJobListPage } from "@/api/personnelManagement/staffOnJob.js";
  import FormDialog from "@/components/Dialog/FormDialog.vue";
  // 部件类型下拉选项(写死)
  const processTypeOptions = [
    "机加工",
    "刮板冷芯制作",
    "管路组对",
    "罐体连接及调试",
    "测试打压",
    "其他",
  ];
  // 工序列表数据
  const processValueList = ref([]);
@@ -304,12 +347,26 @@
  const processLoading = ref(false);
  const deviceOptions = ref([]);
  // 参数列表数据
  const paramList = ref([]);
  // 工序已选参数表格分页(接口一次返回全量)
  const paramPage2 = ref({
    current: 1,
    size: 10,
    total: 0,
  });
  const paramListRaw = ref([]);
  const paramList = computed(() => {
    const all = paramListRaw.value;
    const { current, size } = paramPage2.value;
    const start = (current - 1) * size;
    return all.slice(start, start + size);
  });
  const paramLoading = ref(false);
  // 数据字典
  const dictTypes = ref([]);
  // 员工列表(计划人员、计划执行人员下拉用)
  const employeeOptions = ref([]);
  // 工序对话框
  const processDialogVisible = ref(false);
@@ -321,21 +378,22 @@
    name: "",
    salaryQuota: null,
    isQuality: false,
    isProduction: false,
    remark: "",
    deviceLedgerId: null,
    type: 0,
    processType: "",
    planPerson: null,
    executor: null,
  });
  const processRules = {
    no: [{ required: true, message: "请输入工序编码", trigger: "blur" }],
    name: [{ required: true, message: "请输入工序名称", trigger: "blur" }],
    no: [{ required: true, message: "请输入部件编码", trigger: "blur" }],
    name: [{ required: true, message: "请输入部件名称", trigger: "blur" }],
    salaryQuota: [
      {
        required: false,
        message: "请输入工资定额",
        trigger: "blur",
        validator: (rule, value, callback) => {
          if (isNaN(value) || value < 0) {
            callback(new Error("工资定额必须是非负数字"));
          if (value !== null && value !== undefined && value !== "" && (isNaN(value) || Number(value) < 0)) {
            callback(new Error("计划工时必须是非负数字"));
          } else {
            callback();
          }
@@ -345,7 +403,7 @@
    deviceLedgerId: [
      { required: false, message: "请选择设备", trigger: "change" },
    ],
    type: [{ required: false, message: "请选择计费类型", trigger: "change" }],
    processType: [{ required: true, message: "请选择部件类型", trigger: "change" }],
  };
  // 参数对话框
@@ -371,7 +429,18 @@
    technologyParamId: null,
    paramName: "",
    standardValue: null,
    paramType: null,
  });
  const onStandardValueInput = (val, target) => {
    const data = target.value || target;
    const type = data.paramType;
    if (type === 1) {
      // 数值格式:不能输入中文或英文字符
      data.standardValue = val.replace(/[a-zA-Z\u4e00-\u9fa5]/g, "");
    }
  };
  const editParamRules = {
    standardValue: [
      {
@@ -382,6 +451,12 @@
          if (value === null || value === undefined || value === "") {
            callback(new Error("请输入标准值"));
          } else {
            const type = editParamForm.paramType;
            if (type === 1 && value) {
              if (/[a-zA-Z\u4e00-\u9fa5]/.test(value)) {
                return callback(new Error("数值格式不能包含中英文字符"));
              }
            }
            callback();
          }
        },
@@ -475,21 +550,21 @@
    }
  };
  const paramPage2 = ref({
    current: 1,
    size: 10,
    total: 0,
  });
  // 获取参数列表
  const getParamList = processId => {
    paramLoading.value = true;
    console.log(paramPage2.value, "paramPage2.value");
    getProcessParamList({ technologyOperationId: processId })
      .then(res => {
        console.log(res, "res");
        paramList.value = res.data || [];
        paramPage2.value.total = 0;
        const list = res.data || [];
        paramListRaw.value = Array.isArray(list) ? list : [];
        paramPage2.value.total = paramListRaw.value.length;
        const maxPage = Math.max(
          1,
          Math.ceil(paramPage2.value.total / paramPage2.value.size) || 1
        );
        if (paramPage2.value.current > maxPage) {
          paramPage2.value.current = maxPage;
        }
      })
      .catch(() => {
        ElMessage.error("获取参数列表失败");
@@ -502,6 +577,7 @@
  // 选择工序
  const selectProcess = process => {
    selectedProcess.value = process;
    paramPage2.value.current = 1;
    getParamList(process.id);
  };
@@ -513,9 +589,12 @@
    processForm.name = "";
    processForm.salaryQuota = null;
    processForm.isQuality = false;
    processForm.isProduction = false;
    processForm.remark = "";
    processForm.deviceLedgerId = null;
    processForm.type = 0;
    processForm.processType = "";
    processForm.planPerson = null;
    processForm.executor = null;
    processDialogVisible.value = true;
  };
@@ -526,9 +605,15 @@
    processForm.name = process.name;
    processForm.salaryQuota = process.salaryQuota;
    processForm.isQuality = !!process.isQuality;
    processForm.isProduction = !!process.isProduction;
    processForm.remark = process.remark || "";
    processForm.deviceLedgerId = Number(process.deviceLedgerId);
    processForm.type = process.type;
    // 如果设备 ID 为 0 或者在设备列表中找不到,则回显为空(null)
    const deviceId = Number(process.deviceLedgerId);
    const hasDevice = deviceOptions.value.some(item => item.id === deviceId);
    processForm.deviceLedgerId = deviceId && hasDevice ? deviceId : null;
    processForm.processType = process.processType || "";
    processForm.planPerson = process.planPerson || null;
    processForm.executor = process.executor || null;
    processDialogVisible.value = true;
  };
@@ -544,7 +629,8 @@
          getProcessList();
          if (selectedProcess.value?.id === process.id) {
            selectedProcess.value = null;
            paramList.value = [];
            paramListRaw.value = [];
            paramPage2.value.total = 0;
          }
        })
        .catch(() => {
@@ -692,6 +778,7 @@
    editParamForm.technologyParamId = row.technologyParamId;
    editParamForm.paramName = row.paramName;
    editParamForm.standardValue = row.standardValue;
    editParamForm.paramType = row.paramType;
    editParamDialogVisible.value = true;
  };
@@ -732,10 +819,8 @@
  };
  const handleParamPagination = obj => {
    console.log(obj, "obj");
    paramPage2.value.current = obj.page;
    paramPage2.value.size = obj.limit;
    getParamList(selectedProcess.value.id);
  };
  // 获取数据字典
@@ -745,10 +830,20 @@
    });
  };
  const loadEmployees = async () => {
    try {
      const res = await staffOnJobListPage({ current: -1, size: -1, staffState: 1 });
      employeeOptions.value = res.data?.records || [];
    } catch (error) {
      console.error("加载员工列表失败", error);
    }
  };
  onMounted(() => {
    loadDeviceName();
    getProcessList();
    getDictTypes();
    loadEmployees();
  });
</script>