spring
2026-05-25 0c4429a719f5c95a7690fae51efaaa799ef4e77d
src/views/productionManagement/workOrder/components/ProductionRecordForm.vue
@@ -12,6 +12,25 @@
    default() {
      return [];
    }
  },
  labelWidth: {
    type: Number,
    default: 120
  },
  /** 本次生产数量(成型工序用于计算投入重量/数量) */
  quantity: {
    type: Number,
    default: null
  },
  /** 当前工序是否为「成型」 */
  isFormingProcess: {
    type: Boolean,
    default: false
  },
  /** 工单 BOM 投入重量,非成型工序回显到「投入重量/数量」 */
  bomInputQty: {
    type: Number,
    default: null
  }
});
@@ -20,11 +39,21 @@
  list: [] as any[],
});
const INPUT_WEIGHT_PARAM_ITEM = "投入重量/数量";
/** 参数项展示名(兼容库内旧名「投入重量」) */
const displayParameterItem = (name) => {
  const trimmed = String(name ?? "").trim();
  if (trimmed === "投入重量") return INPUT_WEIGHT_PARAM_ITEM;
  return trimmed;
};
const fieldLabel = (item: any) => {
  const parameterItem = displayParameterItem(item.parameterItem);
  if (!item.unit || item.unit === "/") {
    return item.parameterItem;
    return parameterItem;
  }
  return `${item.parameterItem}(${item.unit})`;
  return `${parameterItem}(${item.unit})`;
};
const getType = (item: any) => item.type || "文本格式";
@@ -33,7 +62,11 @@
  const result: Record<string, any[]> = {};
  formData.list.forEach((item, index) => {
    if (String(item.isRequired) === "1") {
      result[`list.${index}.value`] = [{required: true, message: `请输入${item.parameterItem}`, trigger: "blur"}];
      result[`list.${index}.value`] = [{
        required: true,
        message: `请输入${displayParameterItem(item.parameterItem)}`,
        trigger: "blur"
      }];
    }
  });
  return result;
@@ -45,14 +78,79 @@
  deviceOptions.value = data;
};
const normalizeUnit = (unit) => String(unit ?? "").trim().toLowerCase();
const isInputWeightItem = (item) => {
  const name = String(item?.parameterItem ?? "").trim();
  return (name === "投入重量" || name.includes(INPUT_WEIGHT_PARAM_ITEM)) &&
    normalizeUnit(item?.unit) === "kg";
};
const isBlankCoeffItem = (item) =>
  String(item?.parameterItem ?? "").includes("生坯系数") &&
  normalizeUnit(item?.unit) === "g";
/** 投入重量/数量(KG) = 本次生产数量 × 生坯系数(g) / 1000 */
const syncFormingInputWeight = () => {
  if (!props.isFormingProcess) return;
  const weightItem = formData.list.find(isInputWeightItem);
  if (!weightItem) return;
  const qty = Number(props.quantity);
  const coeffItem = formData.list.find(isBlankCoeffItem);
  const coeff = coeffItem?.value === null || coeffItem?.value === undefined || coeffItem?.value === ""
    ? NaN
    : Number(coeffItem.value);
  if (!Number.isFinite(qty) || qty < 1 || !Number.isFinite(coeff)) {
    return;
  }
  weightItem.value = Number(((qty * coeff) / 1000).toFixed(4));
};
/** 非成型:投入重量/数量取工单 bomInputQty(仅回显,不覆盖用户已编辑的值) */
const syncBomInputWeight = (force = false) => {
  if (props.isFormingProcess) return;
  const weightItem = formData.list.find(isInputWeightItem);
  if (!weightItem) return;
  const bom = props.bomInputQty;
  if (bom === null || bom === undefined || Number.isNaN(Number(bom))) {
    return;
  }
  const current = weightItem.value;
  const isEmpty =
    current === null || current === undefined || current === "";
  if (!force && !isEmpty) {
    return;
  }
  weightItem.value = Number(bom);
};
const syncInputWeight = () => {
  if (props.isFormingProcess) {
    syncFormingInputWeight();
  } else {
    syncBomInputWeight();
  }
};
const cloneParamList = (list) =>
  JSON.parse(JSON.stringify(list || []));
const initData = () => {
  formData.list = props.list || [];
  formData.list = cloneParamList(props.list);
  formData.list.forEach(item => {
    if (item.value === undefined) {
      item.value = null;
    }
  });
  loadDeviceName()
  loadDeviceName();
  if (props.isFormingProcess) {
    syncFormingInputWeight();
  } else {
    syncBomInputWeight(true);
  }
};
const submitData = async () => {
@@ -70,77 +168,113 @@
    () => {
      initData();
    },
    {immediate: true, deep: true}
    {immediate: true}
);
watch(
    () => [props.quantity, props.isFormingProcess],
    () => {
      if (props.isFormingProcess) {
        syncFormingInputWeight();
      }
    }
);
watch(
    () => {
      const coeffItem = formData.list.find(isBlankCoeffItem);
      return coeffItem?.value;
    },
    () => {
      if (props.isFormingProcess) {
        syncFormingInputWeight();
      }
    }
);
watch(
    () => [props.bomInputQty, props.isFormingProcess],
    () => {
      if (!props.isFormingProcess) {
        syncBomInputWeight();
      }
    }
);
defineExpose({
  submitData
  submitData,
  syncFormingInputWeight,
  syncBomInputWeight,
  syncInputWeight
})
</script>
<template>
  <el-form ref="formRef" :model="formData" :rules="rules" label-width="120px">
    <el-form-item
        v-for="(item, index) in formData.list"
        :key="item.id"
        :label="fieldLabel(item)"
        :prop="`list.${index}.value`"
    >
      <el-input-number
          v-if="getType(item) === '数值格式'"
          v-model="item.value"
          :controls="false"
          style="width: 100%"
          placeholder="请输入"
      />
      <el-date-picker
          v-else-if="getType(item) === '时间格式'"
          v-model="item.value"
          type="datetime"
          value-format="YYYY-MM-DD HH:mm:ss"
          format="YYYY-MM-DD HH:mm:ss"
          placeholder="请选择"
          style="width: 100%"
      />
      <el-date-picker
          v-else-if="getType(item) === '日期格式'"
          v-model="item.value"
          type="date"
          value-format="YYYY-MM-DD"
          format="YYYY-MM-DD"
          placeholder="请选择"
          style="width: 100%"
      />
      <el-select
          v-else-if="getType(item) === '是/否选框'"
          v-model="item.value"
          placeholder="请选择"
          clearable
          style="width: 100%"
      >
        <el-option label="是" value="是"/>
        <el-option label="否" value="否"/>
      </el-select>
      <el-select
          v-else-if="getType(item) === '机台选择'"
          v-model="item.value"
          placeholder="请选择"
          clearable
          style="width: 100%"
      >
        <el-option
            v-for="(item, index) in deviceOptions"
            :key="index"
            :label="item.deviceName"
            :value="item.deviceName"
        ></el-option>
      </el-select>
      <el-input
          v-else
          v-model="item.value"
          placeholder="请输入"
          clearable
      />
    </el-form-item>
  <el-form ref="formRef" :model="formData" :rules="rules" :label-width="`${labelWidth}px`">
    <el-row :gutter="20">
      <el-col :span="12" v-for="(item, index) in formData.list" :key="item.id">
        <el-form-item
            :label="fieldLabel(item)"
            :prop="`list.${index}.value`"
        >
          <el-input-number
              v-if="getType(item) === '数值格式'"
              v-model="item.value"
              :controls="false"
              style="width: 100%"
              placeholder="请输入"
          />
          <el-date-picker
              v-else-if="getType(item) === '时间格式'"
              v-model="item.value"
              type="datetime"
              value-format="YYYY-MM-DD HH:mm:ss"
              format="YYYY-MM-DD HH:mm:ss"
              placeholder="请选择"
              style="width: 100%"
          />
          <el-date-picker
              v-else-if="getType(item) === '日期格式'"
              v-model="item.value"
              type="date"
              value-format="YYYY-MM-DD"
              format="YYYY-MM-DD"
              placeholder="请选择"
              style="width: 100%"
          />
          <el-select
              v-else-if="getType(item) === '是/否选框'"
              v-model="item.value"
              placeholder="请选择"
              clearable
              style="width: 100%"
          >
            <el-option label="是" value="是"/>
            <el-option label="否" value="否"/>
          </el-select>
          <el-select
              v-else-if="getType(item) === '机台选择'"
              v-model="item.value"
              placeholder="请选择"
              clearable
              style="width: 100%"
          >
            <el-option
                v-for="(device, deviceIndex) in deviceOptions"
                :key="deviceIndex"
                :label="device.deviceName"
                :value="device.deviceName"
            ></el-option>
          </el-select>
          <el-input
              v-else
              v-model="item.value"
              placeholder="请输入"
              clearable
              style="width: 100%"
          />
        </el-form-item>
      </el-col>
    </el-row>
  </el-form>
</template>