gongchunyi
2026-05-15 c6c1caafba75438cc0eff215f19e9e0b900778d7
src/views/qualityManagement/finalInspection/components/formDia.vue
@@ -18,13 +18,17 @@
                  @change="getModels"
                  :data="productOptions"
                  :render-after-expand="false"
                  :disabled="operationType === 'edit'"
                  style="width: 100%"
              />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="规格型号:" prop="model">
              <el-input v-model="form.model" placeholder="请输入" clearable/>
            <el-form-item label="规格型号:" prop="productModelId">
              <el-select 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-select>
            </el-form-item>
          </el-col>
          <el-col :span="12">
@@ -45,16 +49,34 @@
              </el-select>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="厚度(mm):" prop="thickness">
              <el-input v-model="form.thickness" placeholder="请输入" disabled/>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="30">
          <el-col :span="12">
            <el-form-item label="单位:" prop="unit">
              <el-input v-model="form.unit" placeholder="请输入" clearable/>
              <el-input v-model="form.unit" placeholder="请输入" disabled/>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="数量:" prop="quantity">
              <el-input-number :step="0.01" :min="0" style="width: 100%" v-model="form.quantity" placeholder="请输入" clearable :precision="2"/>
            <el-form-item label="总数量:" prop="quantity">
              <el-input-number :step="0.01" :min="0" style="width: 100%" v-model="form.quantity" placeholder="请输入" clearable :precision="2" :disabled="quantityDisabled"
                               @change="onTotalQuantityChange"/>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="30">
          <el-col :span="12">
            <el-form-item label="合格数量:" prop="qualifiedQuantity">
              <el-input-number :step="0.01" :min="0" style="width: 100%" v-model="form.qualifiedQuantity" placeholder="请输入" clearable :precision="2" @change="onQualifiedQuantityChange"/>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="不合格数量:" prop="unqualifiedQuantity">
              <el-input-number :step="0.01" :min="0" style="width: 100%" v-model="form.unqualifiedQuantity" placeholder="请输入" clearable :precision="2" @change="onUnqualifiedQuantityChange"/>
            </el-form-item>
          </el-col>
        </el-row>
@@ -65,16 +87,6 @@
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="检测结果:" prop="checkResult">
              <el-select v-model="form.checkResult">
                <el-option label="合格" value="合格" />
                <el-option label="不合格" value="不合格" />
              </el-select>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="30">
          <el-col :span="12">
            <el-form-item label="检验员:" prop="checkName">
                     <el-select v-model="form.checkName" placeholder="请选择" clearable>
                        <el-option v-for="item in userList" :key="item.nickName" :label="item.nickName"
@@ -82,6 +94,8 @@
                     </el-select>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="30">
          <el-col :span="12">
            <el-form-item label="检测日期:" prop="checkTime">
              <el-date-picker
@@ -119,9 +133,9 @@
</template>
<script setup>
import {ref, reactive, toRefs, getCurrentInstance, nextTick} from "vue";
import {ref, reactive, toRefs, computed, getCurrentInstance, nextTick} from "vue";
import {getOptions} from "@/api/procurementManagement/procurementLedger.js";
import {productTreeList} from "@/api/basicData/product.js";
import {modelList, productTreeList} from "@/api/basicData/product.js";
import {qualityInspectAdd, qualityInspectUpdate} from "@/api/qualityManagement/rawMaterialInspection.js";
import {userListNoPage} from "@/api/system/user.js";
import {qualityInspectDetailByProductId, getQualityTestStandardParamByTestStandardId} from "@/api/qualityManagement/metricMaintenance.js";
@@ -138,27 +152,143 @@
    checkName: "",
    productName: "",
    productId: "",
    productModelId: "",
    model: "",
    testStandardId: "",
    unit: "",
    quantity: "",
    qualifiedQuantity: null,
    unqualifiedQuantity: null,
    checkCompany: "",
    checkResult: "",
    thickness:""
  },
  rules: {
    checkTime: [{ required: true, message: "请输入", trigger: "blur" },],
    process: [{ required: true, message: "请输入", trigger: "blur" }],
    process: [{ required: false, message: "请输入", trigger: "blur" }],
    checkName: [{ required: false, message: "请输入", trigger: "blur" }],
    productId: [{ required: true, message: "请输入", trigger: "blur" }],
    model: [{ required: false, message: "请输入", trigger: "blur" }],
    productModelId: [{ required: true, message: "请选择", trigger: "change" }],
    testStandardId: [{required: false, message: "请选择指标", trigger: "change"}],
    unit: [{ required: false, message: "请输入", trigger: "blur" }],
    quantity: [{ required: true, message: "请输入", trigger: "blur" }],
    checkCompany: [{ required: false, message: "请输入", trigger: "blur" }],
    checkResult: [{ required: true, message: "请输入", trigger: "change" }],
    qualifiedQuantity: [{ required: true, message: "请输入合格数量", trigger: "blur" }],
    unqualifiedQuantity: [{ required: true, message: "请输入不合格数量", trigger: "blur" }],
  },
});
const { form, rules } = toRefs(data);
function normalizeQuantitiesFromLegacy() {
  const qty = form.value.quantity != null ? Number(form.value.quantity) : null
  if (qty == null || Number.isNaN(qty)) return
  const hasQ = form.value.qualifiedQuantity != null && form.value.qualifiedQuantity !== ''
  const hasU = form.value.unqualifiedQuantity != null && form.value.unqualifiedQuantity !== ''
  if (hasQ && hasU) return
  if (form.value.checkResult === '不合格') {
    form.value.qualifiedQuantity = 0
    form.value.unqualifiedQuantity = qty
  } else {
    form.value.qualifiedQuantity = qty
    form.value.unqualifiedQuantity = 0
  }
}
function assertQtySplitOrError() {
  const total = Number(form.value.quantity)
  const a = form.value.qualifiedQuantity != null ? Number(form.value.qualifiedQuantity) : NaN
  const b = form.value.unqualifiedQuantity != null ? Number(form.value.unqualifiedQuantity) : NaN
  if (!Number.isFinite(total) || total < 0) {
    proxy.$modal.msgError('请先填写有效的总数量')
    return false
  }
  if (!Number.isFinite(a) || !Number.isFinite(b) || a < 0 || b < 0) {
    proxy.$modal.msgError('请填写合格数量与不合格数量')
    return false
  }
  if (a + b - total > 0.001) {
    proxy.$modal.msgError('合格数量与不合格数量之和不能超过总数量')
    return false
  }
  return true
}
function roundQty(n) {
  if (!Number.isFinite(n)) return 0
  return Math.round(n * 100) / 100
}
function parseTotalQty() {
  const t = Number(form.value.quantity)
  return Number.isFinite(t) && t >= 0 ? t : null
}
function onQualifiedQuantityChange(val) {
  const total = parseTotalQty()
  if (total == null) return
  let q = val == null || val === '' ? 0 : Number(val)
  if (!Number.isFinite(q) || q < 0) q = 0
  if (q > total) q = total
  q = roundQty(q)
  form.value.qualifiedQuantity = q
  form.value.unqualifiedQuantity = roundQty(total - q)
}
function onUnqualifiedQuantityChange(val) {
  const total = parseTotalQty()
  if (total == null) return
  let u = val == null || val === '' ? 0 : Number(val)
  if (!Number.isFinite(u) || u < 0) u = 0
  if (u > total) u = total
  u = roundQty(u)
  form.value.unqualifiedQuantity = u
  form.value.qualifiedQuantity = roundQty(total - u)
}
function onTotalQuantityChange() {
  const total = parseTotalQty()
  if (total == null) return
  const q = form.value.qualifiedQuantity != null && form.value.qualifiedQuantity !== '' ? Number(form.value.qualifiedQuantity) : NaN
  const u = form.value.unqualifiedQuantity != null && form.value.unqualifiedQuantity !== '' ? Number(form.value.unqualifiedQuantity) : NaN
  if (!Number.isFinite(q) && !Number.isFinite(u)) {
    form.value.qualifiedQuantity = roundQty(total)
    form.value.unqualifiedQuantity = 0
    return
  }
  if (Number.isFinite(q) && Number.isFinite(u)) {
    const sum = q + u
    if (sum > total + 0.001) {
      const nq = roundQty(Math.min(Math.max(0, q), total))
      form.value.qualifiedQuantity = nq
      form.value.unqualifiedQuantity = roundQty(total - nq)
    }
    return
  }
  if (Number.isFinite(q)) {
    const nq = roundQty(Math.min(Math.max(0, q), total))
    form.value.qualifiedQuantity = nq
    form.value.unqualifiedQuantity = roundQty(total - nq)
  } else if (Number.isFinite(u)) {
    const nu = roundQty(Math.min(Math.max(0, u), total))
    form.value.unqualifiedQuantity = nu
    form.value.qualifiedQuantity = roundQty(total - nu)
  }
}
function ensureQtyPairInitialized() {
  const total = parseTotalQty()
  if (total == null) return
  const qEmpty = form.value.qualifiedQuantity == null || form.value.qualifiedQuantity === ''
  const uEmpty = form.value.unqualifiedQuantity == null || form.value.unqualifiedQuantity === ''
  if (qEmpty && uEmpty) {
    form.value.qualifiedQuantity = roundQty(total)
    form.value.unqualifiedQuantity = 0
  }
}
// 编辑时:productMainId 或 purchaseLedgerId 任一有值则数量置灰
const quantityDisabled = computed(() => {
  const v = form.value || {};
  return !!(v.productMainId != null || v.purchaseLedgerId != null);
});
const supplierList = ref([]);
const productOptions = ref([]);
const tableColumn = ref([
@@ -190,79 +320,122 @@
const userList = ref([]);
const currentProductId = ref(0);
const testStandardOptions = ref([]); // 指标选择下拉框数据
const modelOptions = ref([]);
// 打开弹框
const openDialog = async (type, row) => {
  operationType.value = type;
  dialogFormVisible.value = true;
  getOptions().then((res) => {
    supplierList.value = res.data;
  });
   let userLists = await userListNoPage();
   userList.value = userLists.data;
   form.value = {}
  // 先清空表单验证状态,避免闪烁
  await nextTick();
  proxy.$refs.formRef?.clearValidate();
  // 并行加载基础数据
  const [userListsRes] = await Promise.all([
    userListNoPage(),
    getProductOptions(),
    getOptions().then((res) => {
      supplierList.value = res.data;
    })
  ]);
  userList.value = userListsRes.data;
  form.value = {}
  testStandardOptions.value = [];
  tableData.value = [];
  getProductOptions();
  if (operationType.value === 'edit') {
    // 先保存 testStandardId,避免被清空
    const savedTestStandardId = row.testStandardId;
    // 先设置表单数据,但暂时清空 testStandardId,等选项加载完成后再设置
    form.value = {...row, testStandardId: ''}
      currentProductId.value = row.productId || 0
      // 编辑模式下,先加载指标选项,然后加载参数列表
      if (currentProductId.value) {
         // 先加载指标选项
         let params = {
            productId: currentProductId.value,
            inspectType: 2
         }
         qualityInspectDetailByProductId(params).then(res => {
            testStandardOptions.value = res.data || [];
            // 使用 nextTick 和 setTimeout 确保选项已经渲染到 DOM
            nextTick(() => {
               setTimeout(() => {
                  // 如果编辑数据中有 testStandardId,则设置并加载对应的参数
                  if (savedTestStandardId) {
                     // 确保类型匹配(item.id 可能是数字或字符串)
                     const matchedOption = testStandardOptions.value.find(item =>
                        item.id == savedTestStandardId || String(item.id) === String(savedTestStandardId)
                     );
                     if (matchedOption) {
                        // 确保使用匹配项的 id(保持类型一致)
                        form.value.testStandardId = matchedOption.id;
                        // 编辑场景保留已有检验值,直接拉取原参数数据
                        getQualityInspectParamList(row.id);
                     } else {
                        // 如果找不到匹配项,尝试直接使用原值
                        console.warn('未找到匹配的指标选项,testStandardId:', savedTestStandardId, '可用选项:', testStandardOptions.value);
                        form.value.testStandardId = savedTestStandardId;
                        getQualityInspectParamList(row.id);
                     }
                  } else {
                     // 否则使用旧的逻辑
                     getQualityInspectParamList(row.id);
                  }
               }, 100);
            });
         });
      } else {
         getQualityInspectParamList(row.id);
      }
    normalizeQuantitiesFromLegacy()
    currentProductId.value = row.productId || 0
    // 清空验证状态,避免数据加载过程中的校验闪烁
    nextTick(() => {
      proxy.$refs.formRef?.clearValidate();
    });
    // 编辑模式下,并行加载规格型号和指标选项
    if (currentProductId.value) {
      // 设置产品名称
      form.value.productName = findNodeById(productOptions.value, currentProductId.value);
      // 并行加载规格型号和指标选项
      const params = {
        productId: currentProductId.value,
        inspectType: 2
      };
      Promise.all([
        modelList({ id: currentProductId.value }),
        qualityInspectDetailByProductId(params)
      ]).then(([modelRes, testStandardRes]) => {
        // 设置规格型号选项
        modelOptions.value = modelRes || [];
        // 如果表单中已有 productModelId,设置对应的 model 和 unit
        if (form.value.productModelId && modelOptions.value.length > 0) {
          const selectedModel = modelOptions.value.find(item => item.id == form.value.productModelId);
          if (selectedModel) {
            form.value.model = selectedModel.model || '';
            form.value.unit = selectedModel.unit || '';
            form.value.thickness = selectedModel.thickness || ''
          }
        }
        // 设置指标选项
        testStandardOptions.value = testStandardRes.data || [];
        // 设置 testStandardId 并加载参数列表
        nextTick(() => {
          if (savedTestStandardId) {
            // 确保类型匹配(item.id 可能是数字或字符串)
            const matchedOption = testStandardOptions.value.find(item =>
              item.id == savedTestStandardId || String(item.id) === String(savedTestStandardId)
            );
            if (matchedOption) {
              // 确保使用匹配项的 id(保持类型一致)
              form.value.testStandardId = matchedOption.id;
            } else {
              // 如果找不到匹配项,尝试直接使用原值
              console.warn('未找到匹配的指标选项,testStandardId:', savedTestStandardId, '可用选项:', testStandardOptions.value);
              form.value.testStandardId = savedTestStandardId;
            }
          }
          // 编辑场景保留已有检验值,直接拉取原参数数据
          getQualityInspectParamList(row.id);
        });
      });
    } else {
      getQualityInspectParamList(row.id);
    }
  }
}
const getProductOptions = () => {
  productTreeList().then((res) => {
  return productTreeList().then((res) => {
    productOptions.value = convertIdToValue(res);
  });
};
const getModels = (value) => {
   currentProductId.value = value
  form.value.productModelId = undefined;
  form.value.unit = undefined;
  modelOptions.value = [];
  currentProductId.value = value
  form.value.productName = findNodeById(productOptions.value, value);
   if (currentProductId.value) {
      getList();
   }
  modelList({ id: value }).then((res) => {
    modelOptions.value = res;
  })
  if (currentProductId.value) {
    getList();
  }
};
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 || '';
  form.value.thickness = modelOptions.value.find(item => item.id == value)?.thickness || '';
}
const findNodeById = (nodes, productId) => {
  for (let i = 0; i < nodes.length; i++) {
    if (nodes[i].value === productId) {
@@ -295,6 +468,10 @@
const submitForm = () => {
  proxy.$refs.formRef.validate(valid => {
    if (valid) {
      ensureQtyPairInitialized()
      if (!assertQtySplitOrError()) {
        return
      }
      form.value.inspectType = 2
         if (operationType.value === "add") {
            tableData.value.forEach((item) => {