spring
9 天以前 d991871847391f150dd9c5aa9c871a96b75b7880
src/views/qualityManagement/nonconformingManagement/components/formDia.vue
@@ -11,6 +11,7 @@
          <el-col :span="12">
            <el-form-item label="产品名称:" prop="productId">
              <el-tree-select
                  v-if="operationType !== 'edit'"
                  v-model="form.productId"
                  placeholder="请选择"
                  clearable
@@ -18,7 +19,13 @@
                  @change="getModels"
                  :data="productOptions"
                  :render-after-expand="false"
                  :disabled="operationType === 'edit'"
                  style="width: 100%"
              />
              <!-- 编辑态:不依赖下拉选项回显,直接展示文本 -->
              <el-input
                  v-else
                  v-model="form.productName"
                  disabled
                  style="width: 100%"
              />
            </el-form-item>
@@ -26,16 +33,28 @@
          <el-col :span="12">
            <el-form-item label="规格型号:" prop="productModelId">
              <el-select
                  v-if="operationType !== 'edit'"
                  v-model="form.productModelId"
                  placeholder="请选择"
                  clearable
                  :disabled="operationType === 'edit'"
                  filterable
                  readonly
                  @change="handleChangeModel"
              >
                <el-option v-for="item in modelOptions" :key="item.id" :label="item.model" :value="item.id" />
                <el-option
                    v-for="item in modelOptions"
                    :key="item.id"
                    :label="item.model"
                    :value="item.id"
                />
              </el-select>
              <!-- 编辑态:不展示规格型号列表,直接展示文本 -->
              <el-input
                  v-else
                  v-model="form.model"
                  disabled
                  style="width: 100%"
              />
            </el-form-item>
          </el-col>
        </el-row>
@@ -187,7 +206,7 @@
  },
  rules: {
    checkTime: [{ required: true, message: "请选择检测日期", trigger: "change" }],
    checkUserName: [{ required: true, message: "请选择检验员", trigger: "change" }],
    checkName: [{ required: true, message: "请选择检验员", trigger: "change" }],
    productId: [{ required: true, message: "请选择产品名称", trigger: "change" }],
    productModelId: [{ required: true, message: "请选择规格型号", trigger: "change" }],
    batchNo: [{ required: true, message: "请输入批号", trigger: "blur" }],
@@ -203,27 +222,114 @@
const modelOptions = ref([])
// 打开弹框
const openDialog = (type, row) => {
const openDialog = async (type, row) => {
  operationType.value = type;
  userListNoPage().then(res => {
    userList.value = res.data || [];
  })
  dialogFormVisible.value = true;
  form.value = {}
  getProductOptions();
  // 编辑态不校验规格型号(prop 仍绑定 productModelId,但编辑态改为文本展示)
  data.rules.productModelId = [
    {
      required: type !== "edit",
      message: "请选择规格型号",
      trigger: "change",
    },
  ];
  // 先加载下拉选项,确保编辑数据可以正确匹配回显
  const userRes = await userListNoPage();
  userList.value = userRes.data || [];
  await getProductOptions();
  // 处理结果默认“报废”,且不可选择其它项
  form.value.dealResult = getScrapDealResultValue();
  if (operationType.value === 'edit') {
    getQualityUnqualifiedInfo(row.id).then(res => {
      const { inspectState, ...rest } = (res.data || {})
      form.value = { ...rest, dealResult: getScrapDealResultValue() }
    })
    const fallback = row || {};
    const res = await getQualityUnqualifiedInfo(fallback.id);
    const { inspectState, ...rest } = res.data || {};
    // 先用列表行数据把“必回显字段”直接填上,避免详情接口字段名不一致导致全空。
    const productName = rest?.productName ?? fallback?.productName;
    const modelName = rest?.model ?? fallback?.model;
    const checkTypeValue = rest?.checkType ?? fallback?.checkType;
    const checkNameValue =
      rest?.checkName ??
      rest?.checkUserName ??
      fallback?.checkName ??
      fallback?.checkUserName;
    const productId =
      rest?.productId ??
      findProductIdByLabel(productOptions.value, productName);
    // 先回填字段(productModelId 需要依赖 modelOptions,稍后再补)
    const normalizedProductId = normalizeProductIdByOptions(productId);
    // 编辑态产品名称展示只展示 label,避免树组件回显依赖 value 匹配
    const productNameLabel =
      rest?.productName ??
      fallback?.productName ??
      findNodeById(productOptions.value, normalizedProductId) ??
      productName;
    form.value = {
      ...rest,
      productName: productNameLabel,
      productId: normalizedProductId,
      productModelId: rest?.productModelId ?? undefined,
      model: rest?.model ?? fallback?.model,
      unit: rest?.unit ?? fallback?.unit,
      batchNo: rest?.batchNo ?? fallback?.batchNo ?? "",
      checkType:
        checkTypeValue === undefined || checkTypeValue === null
          ? undefined
          : Number(checkTypeValue),
      checkName: checkNameValue ?? "",
      checkTime: rest?.checkTime ?? fallback?.checkTime ?? "",
      defectivePhenomena:
        rest?.defectivePhenomena ?? fallback?.defectivePhenomena ?? "",
      dealName: rest?.dealName ?? fallback?.dealName ?? "",
      dealTime: rest?.dealTime ?? fallback?.dealTime ?? "",
      dealResult: getScrapDealResultValue(),
    };
    // 规格型号下拉需要依赖 productId
    await loadModelsForProductId(form.value.productId);
    // 规格型号回显(如详情没给 productModelId,就用 model 名称反查)
    if (!form.value.productModelId) {
      form.value.productModelId = findModelIdByModel(
        modelOptions.value,
        modelName
      );
    }
    // 根据 productModelId 回填 model/unit
    if (form.value.productModelId) {
      form.value.productModelId = normalizeModelIdByOptions(form.value.productModelId);
      handleChangeModel(form.value.productModelId);
    } else if (modelName) {
      // productModelId 仍然拿不到时,至少保证 model/unit 文本回显
      const matched =
        (modelOptions.value || []).find((m) => {
          const model = String(m?.model ?? "");
          const id = String(m?.id ?? "");
          const target = String(modelName ?? "");
          return model === target || id === target;
        }) ?? null;
      if (matched) {
        form.value.model = matched.model ?? form.value.model;
        form.value.unit = matched.unit ?? form.value.unit;
      } else {
        form.value.model = modelName;
      }
    }
  }
}
const getProductOptions = () => {
  productTreeList().then((res) => {
    productOptions.value = convertIdToValue(res);
  });
const getProductOptions = async () => {
  const res = await productTreeList();
  productOptions.value = convertIdToValue(res);
};
const getModels = (value) => {
  form.value.productName = findNodeById(productOptions.value, value);
@@ -236,9 +342,41 @@
  })
};
// 编辑模式/或任意需要时:只拉取规格型号列表,不清空已回填的字段
const loadModelsForProductId = async (productId) => {
  if (!productId) return;
  const res = await modelList({ id: productId });
  modelOptions.value = res || [];
  // 让单位/型号等字段保持与当前 productModelId 一致
  if (form.value.productModelId) {
    form.value.productModelId = normalizeModelIdByOptions(form.value.productModelId);
    handleChangeModel(form.value.productModelId);
  }
};
const handleChangeModel = (value) => {
  form.value.model = modelOptions.value.find(item => item.id == value)?.model || '';
  form.value.unit = modelOptions.value.find(item => item.id == value)?.unit || '';
};
// 解决回显时类型不一致导致 el-tree-select / el-select 只显示 value(id)
const normalizeProductIdByOptions = (productId) => {
  if (productId === undefined || productId === null) return productId;
  const target = String(productId);
  const stack = Array.isArray(productOptions.value) ? [...productOptions.value] : [];
  while (stack.length) {
    const node = stack.shift();
    if (node && String(node?.value ?? "") === target) return node?.value;
    if (node?.children?.length) stack.push(...node.children);
  }
  return productId;
};
const normalizeModelIdByOptions = (modelId) => {
  if (modelId === undefined || modelId === null) return modelId;
  const target = String(modelId);
  return (modelOptions.value || []).find((m) => String(m?.id ?? "") === target)?.id ?? modelId;
};
const findNodeById = (nodes, productId) => {
  for (let i = 0; i < nodes.length; i++) {
@@ -254,6 +392,33 @@
  }
  return null; // 没有找到节点,返回null
};
// 根据树节点 label 回填 value(编辑回显兜底用)
const findProductIdByLabel = (nodes, label) => {
  const target = String(label ?? "");
  if (!target) return undefined;
  const stack = Array.isArray(nodes) ? [...nodes] : [];
  while (stack.length) {
    const node = stack.shift();
    if (node && String(node?.label ?? "") === target) return node?.value;
    if (node?.children?.length) stack.push(...node.children);
  }
  return undefined;
};
// 根据规格型号名称反查 id(编辑回显兜底用)
const findModelIdByModel = (models, model) => {
  const target = String(model ?? "");
  if (!target) return undefined;
  return (
    (models || []).find((m) => {
      const mModel = String(m?.model ?? "");
      const mId = String(m?.id ?? "");
      return mModel === target || mId === target;
    })?.id
  );
};
function convertIdToValue(data) {
  return data.map((item) => {
    const { id, children, ...rest } = item;