spring
2026-05-25 0c4429a719f5c95a7690fae51efaaa799ef4e77d
src/views/productionManagement/workOrder/components/CopperPrintingForm.vue
@@ -1,7 +1,8 @@
<script setup lang="ts">
import {computed, onMounted, reactive, ref} from "vue";
import {computed, onMounted, reactive, ref, watch} from "vue";
import dayjs from "dayjs";
import {userListNoPageByTenantId} from "@/api/system/user.js";
import {getDeviceLedger} from "@/api/equipmentManagement/ledger.js";
import {ElMessage} from "element-plus";
import {addProductMain} from "@/api/productionManagement/workOrder.js";
@@ -18,14 +19,15 @@
    type: Boolean,
    default: false
  },
  detailData: {
    type: Object,
    default: () => ({}),
  },
  row: {
    type: Object,
    default: () => ({}),
  }
  },
  /** 工单 BOM 投入重量,回显到「投入重量/数量」 */
  bomInputQty: {
    type: Number,
    default: null,
  },
});
const emits = defineEmits(["update:isShow", "refreshData"]);
@@ -35,6 +37,21 @@
  set: (value: boolean) => emits("update:isShow", value),
});
/** 工序展示名:工单为 processName,报工列表为 process,缺省与旧版一致为「印铜」 */
const processTitlePrefix = computed(() => {
  const row = props.row as Record<string, unknown> | null | undefined;
  if (!row) return "印铜";
  const name = row.processName ?? row.process;
  if (name != null && String(name).trim() !== "") {
    return String(name).trim();
  }
  return "印铜";
});
const dialogTitle = computed(() =>
  props.isEdit ? `${processTitlePrefix.value}报工` : `${processTitlePrefix.value}详情`
);
const formData = reactive({
  productProcessRouteItemId: undefined,
  workOrderId: undefined,
@@ -42,6 +59,7 @@
  reportWork: undefined,
  productMainId: undefined,
  quantity: undefined, // 烧铜产出激
  scrapQty: undefined, // 报废数量
  userId: undefined, // 作业员
  userName: undefined, // 作业员
  otherData: {
@@ -70,6 +88,7 @@
    copperFiringTime: undefined, // 烧铜进炉时间
    steelFiringTime: undefined, // 烧钢出炉时间
    weight: undefined, // 重量(kg/pos)
    inputWeight: undefined, // 投入重量/数量(KG)
    copperSmeltingTemperatureProfile: undefined, // 烧铜温度曲线
    remark: undefined, // 备注
  }
@@ -86,6 +105,17 @@
      .catch(err => {
        console.error("获取用户列表失败", err);
      });
};
const deviceOptions = ref<any[]>([]);
const getDeviceList = async () => {
  try {
    const {data} = await getDeviceLedger();
    deviceOptions.value = data || [];
  } catch (err) {
    console.error("获取设备列表失败", err);
    deviceOptions.value = [];
  }
};
// 用户选择变化时更新 userName
const handleUserChange = (userId: any, reportType: string) => {
@@ -126,11 +156,22 @@
    ElMessage.error('请输入生产数量')
    return;
  }
  const scrapQty =
    formData.scrapQty === null ||
    formData.scrapQty === undefined ||
    formData.scrapQty === ""
      ? 0
      : Number(formData.scrapQty);
  if (isNaN(scrapQty) || !Number.isInteger(scrapQty) || scrapQty < 0) {
    ElMessage.error('报废数量必须大于等于0');
    return;
  }
  formData.userId = formData.otherData.surfaceCopperPasteUserId || formData.otherData.underlyingCopperPasteUserId;
  const otherData = JSON.stringify(formData.otherData);
  const submitData = {
    ...formData,
    scrapQty,
    otherData: otherData
  };
@@ -148,10 +189,30 @@
  });
};
const resolveBomInputQty = () => {
  const bom = props.bomInputQty ?? props.row?.bomInputQty;
  if (bom === null || bom === undefined || bom === "") {
    return null;
  }
  const n = Number(bom);
  return Number.isFinite(n) ? n : null;
};
const applyBomInputWeight = () => {
  const n = resolveBomInputQty();
  if (n !== null) {
    formData.otherData.inputWeight = n;
  }
};
const initData = () => {
  if (!props.isEdit) {
    formData.otherData = JSON.parse(props.detailData.otherData || '{}');
    formData.quantity = props.detailData.quantity;
    formData.otherData = JSON.parse(props.row.otherData || '{}');
    formData.quantity = props.row.quantity;
    formData.scrapQty = props.row.scrapQty;
    if (formData.otherData.inputWeight === undefined || formData.otherData.inputWeight === null || formData.otherData.inputWeight === "") {
      applyBomInputWeight();
    }
  } else {
    const row = props.row;
    formData.planQuantity = row.planQuantity
@@ -159,35 +220,66 @@
    formData.workOrderId = row.id
    formData.reportWork = row.reportWork
    formData.productMainId = row.productMainId
    applyBomInputWeight();
  }
}
watch(
  () => props.isShow,
  (show) => {
    if (show) {
      initData();
    }
  }
);
watch(
  () => [props.bomInputQty, props.row?.bomInputQty],
  () => {
    if (!props.isShow) return;
    if (props.isEdit) {
      applyBomInputWeight();
      return;
    }
    if (formData.otherData.inputWeight === undefined || formData.otherData.inputWeight === null || formData.otherData.inputWeight === "") {
      applyBomInputWeight();
    }
  }
);
const displayValue = (value: any) => {
  return value === undefined || value === null || value === "" ? "-" : value;
};
/** 表格统一 21 列栅格,每行 colspan 之和须等于该值 */
const GRID_COLS = 21;
onMounted(() => {
  getUserList();
  initData()
})
  getDeviceList();
  initData();
});
</script>
<template>
  <el-dialog v-model="visible"
             title="印铜报工"
             :title="dialogTitle"
             width="90%">
    <el-form :model="formData">
      <table class="report-table">
        <colgroup>
          <col v-for="n in GRID_COLS" :key="n" />
        </colgroup>
        <tbody>
        <tr>
          <td class="tip" colspan="4">瓷片清洗后放置时间超过72H,重新烘片后才能印刷并填写本栏</td>
          <td class="label" colspan="3">烘干温度</td>
          <td colspan="2">
          <td colspan="2" class="cell-field">
            <el-input v-if="props.isEdit" v-model="formData.otherData.dryingTemperature" placeholder="请输入"/>
            <span v-else class="view-value">{{ displayValue(formData.otherData.dryingTemperature) }}</span>
          </td>
          <td class="label">开始时间</td>
          <td colspan="2">
          <td colspan="2" class="cell-field">
            <el-date-picker
                v-if="props.isEdit"
                v-model="formData.otherData.startTime"
@@ -195,12 +287,11 @@
                value-format="YYYY-MM-DD HH:mm:ss"
                format="YYYY-MM-DD HH:mm:ss"
                placeholder="请选择"
                style="width: 100%"
            />
            <span v-else class="view-value">{{ displayValue(formData.otherData.startTime) }}</span>
          </td>
          <td class="label"  colspan="3">结束时间</td>
          <td colspan="2">
          <td class="label" colspan="3">结束时间</td>
          <td colspan="2" class="cell-field">
            <el-date-picker
                v-if="props.isEdit"
                v-model="formData.otherData.endTime"
@@ -208,12 +299,11 @@
                value-format="YYYY-MM-DD HH:mm:ss"
                format="YYYY-MM-DD HH:mm:ss"
                placeholder="请选择"
                style="width: 100%"
            />
            <span v-else class="view-value">{{ displayValue(formData.otherData.endTime) }}</span>
          </td>
          <td class="label" colspan="2">作业员</td>
          <td  colspan="2">
          <td colspan="2" class="cell-field">
            <el-select v-model="formData.otherData.userId"
                       v-if="props.isEdit"
                       style="width: 100%"
@@ -229,37 +319,55 @@
            <span v-else class="view-value">{{ displayValue(formData.otherData.userName || formData.otherData.userId) }}</span>
          </td>
        </tr>
        <!-- 底层铜浆 -->
        <tr>
          <td class="label" colspan="2">底层铜浆</td>
          <td>
          <td class="label label--section" colspan="21">底层铜浆</td>
        </tr>
        <tr class="report-row report-row--triple">
          <td class="label" colspan="2">铜浆</td>
          <td colspan="5" class="cell-field">
            <el-input v-if="props.isEdit" v-model="formData.otherData.underlyingCopperPaste" placeholder="请输入"/>
            <span v-else class="view-value">{{ displayValue(formData.otherData.underlyingCopperPaste) }}</span>
          </td>
          <td class="label">印刷次数</td>
          <td colspan="2">
          <td class="label" colspan="2">印刷次数</td>
          <td colspan="5" class="cell-field">
            <el-input v-if="props.isEdit" v-model="formData.otherData.underlyingCopperPastePrintingQuantity" placeholder="请输入"/>
            <span v-else class="view-value">{{ displayValue(formData.otherData.underlyingCopperPastePrintingQuantity) }}</span>
          </td>
          <td class="label">机台号</td>
          <td>
            <el-input v-if="props.isEdit" v-model="formData.otherData.underlyingCopperPasteMachineNumber" placeholder="请输入"/>
          <td class="label" colspan="2">机台号</td>
          <td colspan="5" class="cell-field cell-field--machine">
            <el-select
                v-if="props.isEdit"
                v-model="formData.otherData.underlyingCopperPasteMachineNumber"
                placeholder="请选择设备"
                clearable
                filterable
            >
              <el-option
                  v-for="device in deviceOptions"
                  :key="device.id ?? device.deviceName"
                  :label="device.deviceName"
                  :value="device.deviceName"
              />
            </el-select>
            <span v-else class="view-value">{{ displayValue(formData.otherData.underlyingCopperPasteMachineNumber) }}</span>
          </td>
          <td class="label">丝网族号</td>
          <td colspan="2">
        </tr>
        <tr class="report-row report-row--triple">
          <td class="label" colspan="2">丝网族号</td>
          <td colspan="5" class="cell-field">
            <el-input v-if="props.isEdit" v-model="formData.otherData.underlyingCopperPasteSilkScreenFamilyNumber" placeholder="请输入"/>
            <span v-else class="view-value">{{ displayValue(formData.otherData.underlyingCopperPasteSilkScreenFamilyNumber) }}</span>
          </td>
          <td class="label">目数</td>
          <td colspan="2">
          <td class="label" colspan="2">目数</td>
          <td colspan="5" class="cell-field">
            <el-input v-if="props.isEdit" v-model="formData.otherData.underlyingCopperPasteNumberOfEyes" placeholder="请输入"/>
            <span v-else class="view-value">{{ displayValue(formData.otherData.underlyingCopperPasteNumberOfEyes) }}</span>
          </td>
          <td class="label">作业员</td>
          <td colspan="2">
          <td class="label" colspan="2">作业员</td>
          <td colspan="5" class="cell-field">
            <el-select v-model="formData.otherData.underlyingCopperPasteUserId"
                       v-if="props.isEdit"
                       style="width: 100%"
                       placeholder="请选择作业员"
                       clearable
                       filterable
@@ -271,43 +379,64 @@
            </el-select>
            <span v-else class="view-value">{{ displayValue(formData.otherData.underlyingCopperPasteUserName || formData.otherData.underlyingCopperPasteUserId) }}</span>
          </td>
        </tr>
        <tr class="report-row report-row--triple">
          <td class="label" colspan="2">烘干温度</td>
          <td colspan="2">
          <td colspan="5" class="cell-field">
            <el-input v-if="props.isEdit" v-model="formData.otherData.underlyingCopperPasteDryingTemperature" placeholder="请输入"/>
            <span v-else class="view-value">{{ displayValue(formData.otherData.underlyingCopperPasteDryingTemperature) }}</span>
          </td>
          <td colspan="14"></td>
        </tr>
        <!-- 表层铜浆 -->
        <tr>
          <td class="label" colspan="2">表层铜浆</td>
          <td>
          <td class="label label--section" colspan="21">表层铜浆</td>
        </tr>
        <tr class="report-row report-row--triple">
          <td class="label" colspan="2">铜浆</td>
          <td colspan="5" class="cell-field">
            <el-input v-if="props.isEdit" v-model="formData.otherData.surfaceCopperPaste" placeholder="请输入"/>
            <span v-else class="view-value">{{ displayValue(formData.otherData.surfaceCopperPaste) }}</span>
          </td>
          <td class="label">印刷次数</td>
          <td colspan="2">
          <td class="label" colspan="2">印刷次数</td>
          <td colspan="5" class="cell-field">
            <el-input v-if="props.isEdit" v-model="formData.otherData.surfaceCopperPastePrintingQuantity" placeholder="请输入"/>
            <span v-else class="view-value">{{ displayValue(formData.otherData.surfaceCopperPastePrintingQuantity) }}</span>
          </td>
          <td class="label">机台号</td>
          <td>
            <el-input v-if="props.isEdit" v-model="formData.otherData.surfaceCopperPasteMachineNumber" placeholder="请输入"/>
          <td class="label" colspan="2">机台号</td>
          <td colspan="5" class="cell-field cell-field--machine">
            <el-select
                v-if="props.isEdit"
                v-model="formData.otherData.surfaceCopperPasteMachineNumber"
                placeholder="请选择设备"
                clearable
                filterable
            >
              <el-option
                  v-for="device in deviceOptions"
                  :key="device.id ?? device.deviceName"
                  :label="device.deviceName"
                  :value="device.deviceName"
              />
            </el-select>
            <span v-else class="view-value">{{ displayValue(formData.otherData.surfaceCopperPasteMachineNumber) }}</span>
          </td>
          <td class="label">丝网族号</td>
          <td colspan="2">
        </tr>
        <tr class="report-row report-row--triple">
          <td class="label" colspan="2">丝网族号</td>
          <td colspan="5" class="cell-field">
            <el-input v-if="props.isEdit" v-model="formData.otherData.surfaceCopperPasteSilkScreenFamilyNumber" placeholder="请输入"/>
            <span v-else class="view-value">{{ displayValue(formData.otherData.surfaceCopperPasteSilkScreenFamilyNumber) }}</span>
          </td>
          <td class="label">目数</td>
          <td colspan="2">
          <td class="label" colspan="2">目数</td>
          <td colspan="5" class="cell-field">
            <el-input v-if="props.isEdit" v-model="formData.otherData.surfaceCopperPasteNumberOfEyes" placeholder="请输入"/>
            <span v-else class="view-value">{{ displayValue(formData.otherData.surfaceCopperPasteNumberOfEyes) }}</span>
          </td>
          <td class="label">作业员</td>
          <td colspan="2">
          <td class="label" colspan="2">作业员</td>
          <td colspan="5" class="cell-field">
            <el-select v-model="formData.otherData.surfaceCopperPasteUserId"
                       v-if="props.isEdit"
                       style="width: 100%"
                       placeholder="请选择作业员"
                       clearable
                       filterable
@@ -319,15 +448,18 @@
            </el-select>
            <span v-else class="view-value">{{ displayValue(formData.otherData.surfaceCopperPasteUserName || formData.otherData.surfaceCopperPasteUserId) }}</span>
          </td>
        </tr>
        <tr class="report-row report-row--triple">
          <td class="label" colspan="2">烘干温度</td>
          <td colspan="2">
          <td colspan="5" class="cell-field">
            <el-input v-if="props.isEdit" v-model="formData.otherData.surfaceCopperPasteDryingTemperature" placeholder="请输入"/>
            <span v-else class="view-value">{{ displayValue(formData.otherData.surfaceCopperPasteDryingTemperature) }}</span>
          </td>
          <td colspan="14"></td>
        </tr>
        <tr>
          <td class="label" colspan="2">烧钢日期</td>
          <td colspan="2">
        <tr class="report-row report-row--triple">
          <td class="label" colspan="2">烧铜日期</td>
          <td colspan="5" class="cell-field">
            <el-date-picker
                v-if="props.isEdit"
                v-model="formData.otherData.steelBurningDate"
@@ -335,12 +467,11 @@
                value-format="YYYY-MM-DD"
                format="YYYY-MM-DD"
                placeholder="请选择"
                style="width: 100%"
            />
            <span v-else class="view-value">{{ displayValue(formData.otherData.steelBurningDate) }}</span>
          </td>
          <td class="label" colspan="3">烧铜进炉时间</td>
          <td colspan="2">
          <td class="label label--compact" colspan="2">烧铜进炉时间</td>
          <td colspan="5" class="cell-field">
            <el-date-picker
                v-if="props.isEdit"
                v-model="formData.otherData.copperFiringTime"
@@ -348,12 +479,11 @@
                value-format="YYYY-MM-DD HH:mm:ss"
                format="YYYY-MM-DD HH:mm:ss"
                placeholder="请选择"
                style="width: 100%"
            />
            <span v-else class="view-value">{{ displayValue(formData.otherData.copperFiringTime) }}</span>
          </td>
          <td class="label">烧钢出炉时间</td>
          <td colspan="2">
          <td class="label label--compact" colspan="2">烧铜出炉时间</td>
          <td colspan="5" class="cell-field">
            <el-date-picker
                v-if="props.isEdit"
                v-model="formData.otherData.steelFiringTime"
@@ -361,24 +491,50 @@
                value-format="YYYY-MM-DD HH:mm:ss"
                format="YYYY-MM-DD HH:mm:ss"
                placeholder="请选择"
                style="width: 100%"
            />
            <span v-else class="view-value">{{ displayValue(formData.otherData.steelFiringTime) }}</span>
          </td>
          <td class="label" colspan="3">烧铜产出激</td>
          <td colspan="2">
        </tr>
        <tr class="report-row report-row--double">
          <td class="label" colspan="2">投入重量(KG)/数量</td>
          <td colspan="19" class="cell-field">
            <el-input-number
                v-if="props.isEdit"
                v-model="formData.otherData.inputWeight"
                :controls="false"
                style="width: 100%"
                placeholder="请输入"
            />
            <span v-else class="view-value">{{ displayValue(formData.otherData.inputWeight) }}</span>
          </td>
        </tr>
        <tr class="report-row report-row--triple">
          <td class="label" colspan="2">烧铜产出</td>
          <td colspan="5" class="cell-field">
            <el-input v-if="props.isEdit" v-model="formData.quantity" placeholder="请输入"/>
            <span v-else class="view-value">{{ displayValue(formData.quantity) }}</span>
          </td>
          <td class="label" colspan="2">重量(kg/pos)</td>
          <td colspan="2">
          <td class="label" colspan="2">报废数量</td>
          <td colspan="5" class="cell-field">
            <el-input
                v-if="props.isEdit"
                v-model.number="formData.scrapQty"
                type="number"
                min="0"
                step="1"
                placeholder="请输入"
            />
            <span v-else class="view-value">{{ displayValue(formData.scrapQty) }}</span>
          </td>
          <td class="label label--compact" colspan="2">重量(kg/pos)</td>
          <td colspan="5" class="cell-field">
            <el-input v-if="props.isEdit" v-model="formData.otherData.weight" placeholder="请输入"/>
            <span v-else class="view-value">{{ displayValue(formData.otherData.weight) }}</span>
          </td>
        </tr>
        <tr>
        <tr class="report-row report-row--double">
          <td class="label" colspan="2">烧铜温度曲线</td>
          <td colspan="7">
          <td colspan="9" class="cell-field">
            <el-input
                v-if="props.isEdit"
                v-model="formData.otherData.copperSmeltingTemperatureProfile"
@@ -388,8 +544,8 @@
            />
            <span v-else class="view-value">{{ displayValue(formData.otherData.copperSmeltingTemperatureProfile) }}</span>
          </td>
          <td class="label">备注</td>
          <td colspan="11">
          <td class="label" colspan="2">备注</td>
          <td colspan="8" class="cell-field">
            <el-input v-if="props.isEdit" v-model="formData.otherData.remark" type="textarea" :rows="3" placeholder="请输入"/>
            <span v-else class="view-value">{{ displayValue(formData.otherData.remark) }}</span>
          </td>
@@ -415,17 +571,36 @@
  font-size: 13px;
}
.report-table col {
  width: calc(100% / 21);
}
.report-table td {
  border: 1px solid #dcdfe6;
  padding: 6px;
  padding: 6px 8px;
  vertical-align: middle;
  overflow: hidden;
}
.report-table .label {
  width: 90px;
  background: #f5f7fa;
  text-align: center;
  font-weight: 500;
  white-space: nowrap;
}
.report-table .label--compact {
  font-size: 12px;
  line-height: 1.35;
  white-space: normal;
  word-break: keep-all;
}
.report-table .label--section {
  text-align: left;
  padding-left: 12px;
  font-weight: 600;
  background: #eef1f6;
}
.report-table .tip {
@@ -435,9 +610,49 @@
  background: #fafafa;
}
.report-table .cell-field {
  min-width: 0;
}
.report-table .cell-field :deep(.el-input),
.report-table .cell-field :deep(.el-date-editor),
.report-table .cell-field :deep(.el-select) {
  width: 100%;
}
.report-table .cell-field :deep(.el-textarea) {
  width: 100%;
}
.report-table .cell-field--machine :deep(.el-select) {
  width: 100%;
}
.report-table .cell-field--machine :deep(.el-select .el-select__wrapper) {
  min-height: 32px;
}
.report-table .cell-field :deep(.el-input__wrapper) {
  box-sizing: border-box;
}
/* 隐藏 number 输入框上下箭头,与其他文本框视觉一致 */
.report-table .cell-field :deep(input[type="number"]::-webkit-outer-spin-button),
.report-table .cell-field :deep(input[type="number"]::-webkit-inner-spin-button) {
  -webkit-appearance: none;
  margin: 0;
}
.report-table .cell-field :deep(input[type="number"]) {
  -moz-appearance: textfield;
  appearance: textfield;
}
.view-value {
  display: inline-block;
  width: 100%;
  min-height: 32px;
  line-height: 32px;
  word-break: break-all;
}
</style>