huminmin
昨天 d99337be75724c5add989f0775e1bd188f7516f7
设备保养增加备件领用
已修改3个文件
149 ■■■■ 文件已修改
src/api/equipmentManagement/sparePartsUsage.js 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/equipmentManagement/spareParts/index.vue 32 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/equipmentManagement/upkeep/Form/MaintenanceModal.vue 115 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/equipmentManagement/sparePartsUsage.js
@@ -6,7 +6,7 @@
 */
export const getSparePartsUsagePage = (params) => {
  return request({
    url: "/sparePartsUsage/listPage",
    url: "/sparePartsRequisitionRecord/listPage",
    method: "get",
    params,
  });
src/views/equipmentManagement/spareParts/index.vue
@@ -98,12 +98,12 @@
        <div class="search_form">
          <el-form :inline="true" :model="usageQuery" class="search-form">
            <el-form-item label="备件名称">
              <el-input v-model="usageQuery.sparePartName" placeholder="请输入备件名称" clearable style="width: 240px" />
              <el-input v-model="usageQuery.sparePartsName" placeholder="请输入备件名称" clearable style="width: 240px" />
            </el-form-item>
            <el-form-item label="来源">
              <el-select v-model="usageQuery.source" placeholder="请选择" clearable style="width: 200px">
                <el-option label="维修" value="维修" />
                <el-option label="保养" value="保养" />
              <el-select v-model="usageQuery.sourceType" placeholder="请选择" clearable style="width: 200px">
                <el-option label="维修" :value="0" />
                <el-option label="保养" :value="1" />
              </el-select>
            </el-form-item>
            <el-form-item>
@@ -167,8 +167,8 @@
// 备件领用记录
const usageLoading = ref(false);
const usageQuery = reactive({
  sparePartName: "",
  source: "",
  sparePartsName: "",
  sourceType: "",
});
const usagePagination = reactive({
  current: 1,
@@ -180,10 +180,10 @@
  { label: "来源", prop: "sourceText" },
  { label: "单据/记录ID", prop: "sourceId" },
  { label: "设备名称", prop: "deviceName" },
  { label: "备件名称", prop: "sparePartName" },
  { label: "领用数量", prop: "qty" },
  { label: "备件名称", prop: "sparePartsName" },
  { label: "领用数量", prop: "quantity" },
  { label: "操作人", prop: "operator" },
  { label: "时间", prop: "time" },
  { label: "时间", prop: "createTime" },
]);
const handleTabChange = async (name) => {
@@ -340,8 +340,8 @@
    const res = await getSparePartsUsagePage({
      current: usagePagination.current,
      size: usagePagination.size,
      sparePartName: usageQuery.sparePartName || undefined,
      source: usageQuery.source || undefined,
      sparePartsName: usageQuery.sparePartsName || undefined,
      sourceType: usageQuery.sourceType || undefined,
    });
    if (res?.code === 200) {
      const records = res?.data?.records || [];
@@ -349,11 +349,7 @@
      usageTableData.value = records.map((r, idx) => ({
        rowKey: r.id ?? `${usagePagination.current}-${idx}`,
        ...r,
        sourceText:
          r.source === "维修" ? "维修" :
          r.source === "保养" ? "保养" :
          r.source === "manual" ? "手工" :
          (r.source || "-"),
        sourceText: r.sourceText === "" ? "-" : r.sourceText,
      }));
    } else {
      usagePagination.total = 0;
@@ -369,8 +365,8 @@
  fetchUsageData();
};
const resetUsageQuery = () => {
  usageQuery.sparePartName = "";
  usageQuery.source = "";
  usageQuery.sparePartsName = "";
  usageQuery.sourceType = "";
  usagePagination.current = 1;
  fetchUsageData();
};
src/views/equipmentManagement/upkeep/Form/MaintenanceModal.vue
@@ -38,6 +38,41 @@
          placeholder="请输入保养结果"
          type="text" />
      </el-form-item>
      <el-form-item label="设备备件">
        <el-select v-model="form.sparePartsIds" :loading="loadingSparePartOptions" placeholder="请选择设备备件" multiple filterable>
          <el-option
              v-for="item in sparePartOptions"
              :key="item.id"
              :label="item.name"
              :value="item.id"
          />
        </el-select>
      </el-form-item>
      <el-form-item v-if="selectedSpareParts.length" label="领用数量">
        <div style="width: 100%">
          <div
              v-for="item in selectedSpareParts"
              :key="item.id"
              style="display: flex; align-items: center; gap: 10px; margin-bottom: 10px;"
          >
            <div style="flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;">
              {{ item.name }}
              <span v-if="item.quantity !== null && item.quantity !== undefined" style="color: #909399;">
                (库存:{{ item.quantity }})
              </span>
            </div>
            <el-input-number
                v-model="sparePartQtyMap[item.id]"
                :min="1"
                :max="item.quantity !== null && item.quantity !== undefined ? Number(item.quantity) : undefined"
                :step="1"
                controls-position="right"
                style="width: 180px"
            />
          </div>
        </div>
      </el-form-item>
    </el-form>
  </FormDialog>
</template>
@@ -49,6 +84,8 @@
import dayjs from "dayjs";
import useUserStore from "@/store/modules/user";
import { ElMessage } from "element-plus";
import {computed, ref} from "vue";
import {getSparePartsList} from "@/api/equipmentManagement/spareParts.js";
defineOptions({
  name: "保养模态框",
@@ -67,6 +104,17 @@
  maintenanceActuallyTime: undefined, // 实际保养日期
  maintenanceResult: undefined, // 保养结果
  status: 0, // 保养状态
  sparePartsIds: [],
});
const sparePartOptions = ref([])
const loadingSparePartOptions = ref(true)
const sparePartQtyMap = ref({})
const selectedSpareParts = computed(() => {
  const ids = Array.isArray(form.sparePartsIds) ? form.sparePartsIds : [];
  const set = new Set(ids.map((i) => String(i)));
  return (sparePartOptions.value || []).filter((p) => set.has(String(p.id)));
});
const setForm = (data) => {
@@ -78,6 +126,19 @@
      : dayjs().format("YYYY-MM-DD HH:mm:ss");
  form.maintenanceResult = data.maintenanceResult;
  form.status = 1; // 默认状态为完结
  // multiple 选择器要求数组;后端常返回 "1,2,3"
  if (Array.isArray(data?.sparePartsIds)) {
    form.sparePartsIds = data.sparePartsIds.map((v) => Number(v)).filter((v) => Number.isFinite(v));
  } else if (typeof data?.sparePartsIds === "string") {
    form.sparePartsIds = data.sparePartsIds
        .split(",")
        .map((s) => Number(String(s).trim()))
        .filter((v) => Number.isFinite(v));
  } else if (typeof data?.sparePartsIds === "number") {
    form.sparePartsIds = [data.sparePartsIds];
  } else {
    form.sparePartsIds = [];
  }
};
/**
@@ -86,11 +147,41 @@
const sendForm = async () => {
  loading.value = true;
  try {
    const { code } = await addMaintenance({ id: planId.value, ...form });
    // 领用数量校验
    if (Array.isArray(form.sparePartsIds) && form.sparePartsIds.length > 0) {
      for (const partId of form.sparePartsIds) {
        const qty = Number(sparePartQtyMap.value?.[partId]);
        if (!Number.isFinite(qty) || qty <= 0) {
          proxy?.$modal?.msgError?.("请填写备件领用数量");
          return;
        }
        const part = sparePartOptions.value.find((p) => String(p.id) === String(partId));
        const stock = part?.quantity;
        if (stock !== null && stock !== undefined && Number.isFinite(Number(stock))) {
          if (qty > Number(stock)) {
            proxy?.$modal?.msgError?.(`备件「${part?.name || ""}」领用数量不能超过库存(${stock})`);
            return;
          }
        }
      }
    }
    const data = {
      id: planId.value,
      ...form,
      sparePartsIds: form.sparePartsIds ? form.sparePartsIds.join(",") : "",
      sparePartsQty: form.sparePartsIds
          ? form.sparePartsIds.map((id) => sparePartQtyMap.value?.[id] ?? 1).join(",")
          : "",
      sparePartsUseList: form.sparePartsIds
          ? form.sparePartsIds.map((id) => ({ id, quantity: sparePartQtyMap.value?.[id] ?? 1 }))
          : [],
    }
    const { code } = await addMaintenance(data);
    if (code == 200) {
      ElMessage.success("保养成功");
      emits("ok");
      resetForm();
      sparePartQtyMap.value = {};
      visible.value = false;
    }
  } finally {
@@ -98,13 +189,34 @@
  }
};
const fetchSparePartOptions = () => {
  loadingSparePartOptions.value = true;
  // 和备件管理页一致:/spareParts/listPage → res.data.records
  getSparePartsList({ current: 1, size: 1000 })
      .then((res) => {
        if (res.code === 200) {
          sparePartOptions.value = res?.data?.records || [];
        } else {
          sparePartOptions.value = [];
        }
      })
      .catch(() => {
        sparePartOptions.value = [];
      })
      .finally(() => {
        loadingSparePartOptions.value = false;
      });
}
const handleCancel = () => {
  resetForm();
  sparePartQtyMap.value = {};
  visible.value = false;
};
const handleClose = () => {
  resetForm();
  sparePartQtyMap.value = {};
  visible.value = false;
};
@@ -112,6 +224,7 @@
  planId.value = id; // 保存计划保养记录的id
  visible.value = true;
  await nextTick();
  fetchSparePartOptions()
  setForm(row);
};