zhang_nuo
2026-08-11 1be6a8fc84764d7e816737b365f9e1c8869db9a7
src/views/equipmentManagement/spareParts/index.vue
@@ -1,26 +1,26 @@
<template>
   <div class="spare-part-category">
      <el-tabs v-model="activeTab" @tab-change="handleTabChange">
         <el-tab-pane label="备件列表" name="list">
            <div class="search_form">
               <el-form :inline="true" :model="queryParams" class="search-form">
                  <el-form-item label="备件名称">
                     <el-input
                        v-model="queryParams.name"
                        placeholder="请输入备件名称"
                        clearable
                        style="width: 240px"
                     />
                  </el-form-item>
                  <el-form-item>
                     <el-button type="primary" @click="handleQuery">查询</el-button>
                     <el-button @click="resetQuery">重置</el-button>
                  </el-form-item>
               </el-form>
               <div>
                  <el-button type="primary" @click="addCategory">新增</el-button>
               </div>
            </div>
  <div class="spare-part-category">
    <el-tabs v-model="activeTab" @tab-change="handleTabChange">
      <el-tab-pane label="备件列表" name="list">
        <div class="search_form">
          <el-form :inline="true" :model="queryParams" class="search-form">
            <el-form-item label="备件名称">
              <el-input
                v-model="queryParams.name"
                placeholder="请输入备件名称"
                clearable
                style="width: 240px"
              />
            </el-form-item>
            <el-form-item>
              <el-button type="primary" @click="handleQuery">查询</el-button>
              <el-button @click="resetQuery">重置</el-button>
            </el-form-item>
          </el-form>
          <div>
            <el-button type="primary" @click="addCategory">新增</el-button>
          </div>
        </div>
            <div class="table_list">
               <PIMTable
                  rowKey="id"
@@ -36,87 +36,83 @@
                  </template>
               </PIMTable>
            </div>
            <el-dialog title="分类管理" v-model="dialogVisible" width="60%">
               <el-form :model="form" :rules="rules" ref="formRef" label-width="100px">
                  <el-form-item label="设备" prop="deviceLedgerIds">
                     <el-select
                        v-model="form.deviceLedgerIds"
                        placeholder="请选择设备"
                        filterable
                        default-first-option
                        :reserve-keyword="false"
                        multiple
                        style="width: 100%"
                     >
                        <el-option
                           v-for="(item, index) in deviceOptions"
                           :key="index"
                           :label="item.deviceName"
                           :value="item.id"
                        ></el-option>
                     </el-select>
                  </el-form-item>
                  <el-form-item label="备件名称" prop="name">
                     <el-input v-model="form.name"></el-input>
                  </el-form-item>
                  <el-form-item label="备件编号" prop="sparePartsNo">
                     <el-input v-model="form.sparePartsNo"></el-input>
                  </el-form-item>
                  <el-form-item label="数量" prop="quantity">
                     <el-input type="number" v-model="form.quantity"></el-input>
                  </el-form-item>
                  <el-form-item label="状态" prop="status">
                     <el-select v-model="form.status" placeholder="请选择状态">
                        <el-option label="正常" value="正常"></el-option>
                        <el-option label="禁用" value="禁用"></el-option>
                     </el-select>
                  </el-form-item>
                  <el-form-item label="描述" prop="description">
                     <el-input v-model="form.description"></el-input>
                  </el-form-item>
                  <el-form-item label="价格" prop="price">
                     <el-input-number
                        v-model="form.price"
                        placeholder="请输入价格"
                        :min="0"
                        :step="0.01"
                        :precision="2"
                        style="width: 100%"
                     ></el-input-number>
                  </el-form-item>
               </el-form>
               <template #footer>
        <el-dialog title="分类管理" v-model="dialogVisible" width="60%">
          <el-form :model="form" :rules="rules" ref="formRef" label-width="100px">
            <el-form-item label="设备" prop="deviceLedgerIds">
              <el-select
                v-model="form.deviceLedgerIds"
                placeholder="请选择设备"
                filterable
                default-first-option
                :reserve-keyword="false"
                multiple
                style="width: 100%"
              >
                <el-option
                  v-for="(item, index) in deviceOptions"
                  :key="index"
                  :label="item.deviceName"
                  :value="item.id"
                ></el-option>
              </el-select>
            </el-form-item>
            <el-form-item label="备件名称" prop="name">
              <el-input v-model="form.name"></el-input>
            </el-form-item>
            <el-form-item label="备件编号" prop="sparePartsNo">
              <el-input v-model="form.sparePartsNo"></el-input>
            </el-form-item>
            <el-form-item label="数量" prop="quantity">
              <el-input type="number" v-model="form.quantity"></el-input>
            </el-form-item>
            <el-form-item label="状态" prop="status">
              <el-select v-model="form.status" placeholder="请选择状态">
                <el-option label="正常" value="正常"></el-option>
                <el-option label="禁用" value="禁用"></el-option>
              </el-select>
            </el-form-item>
            <el-form-item label="描述" prop="description">
              <el-input v-model="form.description"></el-input>
            </el-form-item>
            <el-form-item label="价格" prop="price">
              <el-input-number
                v-model="form.price"
                placeholder="请输入价格"
                :min="0"
                :step="0.01"
                :precision="2"
                style="width: 100%"
              ></el-input-number>
            </el-form-item>
          </el-form>
          <template #footer>
            <span class="dialog-footer">
              <el-button type="primary" @click="submitForm" :loading="formLoading">确定</el-button>
              <el-button @click="dialogVisible = false" :disabled="formLoading">取消</el-button>
            </span>
               </template>
            </el-dialog>
         </el-tab-pane>
         <el-tab-pane label="备件领用记录" name="usage">
            <div class="search_form">
               <el-form :inline="true" :model="usageQuery" class="search-form">
                  <el-form-item label="备件名称">
                     <el-input v-model="usageQuery.sparePartsName" placeholder="请输入备件名称" clearable style="width: 240px" />
                  </el-form-item>
                  <el-form-item label="来源">
                     <el-select v-model="usageQuery.sourceType" placeholder="请选择" clearable style="width: 200px">
                        <el-option label="维修" :value="0" />
                        <el-option label="保养" :value="1" />
                        <el-option label="直接出库" :value="2" />
                     </el-select>
                  </el-form-item>
                  <el-form-item>
                     <el-button type="primary" @click="handleUsageQuery">查询</el-button>
                     <el-button @click="resetUsageQuery">重置</el-button>
                  </el-form-item>
               </el-form>
               <div>
                  <el-button type="primary" @click="openRequisitionDialog">直接出库</el-button>
               </div>
            </div>
          </template>
        </el-dialog>
      </el-tab-pane>
      <el-tab-pane label="备件领用记录" name="usage">
        <div class="search_form">
          <el-form :inline="true" :model="usageQuery" class="search-form">
            <el-form-item label="备件名称">
              <el-input v-model="usageQuery.sparePartsName" placeholder="请输入备件名称" clearable style="width: 240px" />
            </el-form-item>
            <el-form-item label="来源">
              <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>
              <el-button type="primary" @click="handleUsageQuery">查询</el-button>
              <el-button @click="resetUsageQuery">重置</el-button>
            </el-form-item>
          </el-form>
        </div>
            <div class="table_list">
               <PIMTable
                  rowKey="rowKey"
@@ -128,63 +124,9 @@
                  @pagination="handleUsagePageChange"
               />
            </div>
         </el-tab-pane>
      </el-tabs>
      <!-- 直接出库弹窗 -->
      <el-dialog title="直接出库" v-model="requisitionDialogVisible" width="500px">
         <el-form :model="requisitionForm" :rules="requisitionRules" ref="requisitionFormRef" label-width="100px">
            <el-form-item label="设备选择" prop="deviceLedgerId">
               <el-select
                  v-model="requisitionForm.deviceLedgerId"
                  placeholder="请选择设备"
                  filterable
                  clearable
                  style="width: 100%"
               >
                  <el-option
                     v-for="item in requisitionDeviceOptions"
                     :key="item.id"
                     :label="item.deviceName"
                     :value="item.id"
                  />
               </el-select>
            </el-form-item>
            <el-form-item label="备件选择" prop="sparePartsId">
               <el-select
                  v-model="requisitionForm.sparePartsId"
                  placeholder="请选择备件"
                  filterable
                  clearable
                  style="width: 100%"
                  @change="onRequisitionSparePartChange"
               >
                  <el-option
                     v-for="item in requisitionSparePartsOptions"
                     :key="item.id"
                     :label="`${item.name}(库存: ${item.quantity})`"
                     :value="item.id"
                  />
               </el-select>
            </el-form-item>
            <el-form-item label="领用数量" prop="quantity">
               <el-input-number
                  v-model="requisitionForm.quantity"
                  :min="1"
                  :max="selectedSparePartMaxQty"
                  style="width: 100%"
               />
            </el-form-item>
            <el-form-item label="备注" prop="remark">
               <el-input v-model="requisitionForm.remark" placeholder="请输入备注" />
            </el-form-item>
         </el-form>
         <template #footer>
            <el-button type="primary" @click="submitRequisition" :loading="requisitionLoading">确定</el-button>
            <el-button @click="requisitionDialogVisible = false">取消</el-button>
         </template>
      </el-dialog>
   </div>
      </el-tab-pane>
    </el-tabs>
  </div>
</template>
<script setup>
@@ -193,7 +135,7 @@
import { getSparePartsList, addSparePart, editSparePart, delSparePart } from "@/api/equipmentManagement/spareParts";
import { getDeviceLedger } from "@/api/equipmentManagement/ledger";
import PIMTable from "@/components/PIMTable/PIMTable.vue";
import { getSparePartsUsagePage, outboundSpareParts } from "@/api/equipmentManagement/sparePartsUsage";
import { getSparePartsUsagePage } from "@/api/equipmentManagement/sparePartsUsage";
// 加载状态
const loading = ref(false);
@@ -215,456 +157,376 @@
const formRef = ref(null);
// 查询参数
const queryParams = reactive({
   name: ''
  name: ''
});
// 分页参数
const pagination = reactive({
   current: 1,
   size: 10,
   total: 0
  current: 1,
  size: 10,
  total: 0
});
// 备件领用记录
const usageLoading = ref(false);
const usageQuery = reactive({
   sparePartsName: "",
   sourceType: "",
  sparePartsName: "",
  sourceType: "",
});
const usagePagination = reactive({
   current: 1,
   size: 10,
   total: 0,
  current: 1,
  size: 10,
  total: 0,
});
const usageTableData = ref([]);
const usageColumns = ref([
   { label: "来源", prop: "sourceText" },
   { label: "单据/记录ID", prop: "sourceId" },
   { label: "设备名称", prop: "deviceName" },
   { label: "备件名称", prop: "sparePartsName" },
   { label: "领用数量", prop: "quantity" },
   { label: "操作人", prop: "operator" },
   { label: "时间", prop: "createTime" },
  { label: "来源", prop: "sourceText" },
  { label: "单据/记录ID", prop: "sourceId" },
  { label: "设备名称", prop: "deviceName" },
  { label: "备件名称", prop: "sparePartsName" },
  { label: "领用数量", prop: "quantity" },
  { label: "操作人", prop: "operator" },
  { label: "时间", prop: "createTime",dataType: "date"},
]);
const handleTabChange = async (name) => {
   if (name === "usage") {
      usagePagination.current = 1;
      await fetchUsageData();
   }
  if (name === "usage") {
    usagePagination.current = 1;
    await fetchUsageData();
  }
};
const columns = ref([
   {
      label: "设备名称",
      prop: "deviceNameStr",
   },
   {
      label: "备件名称",
      prop: "name",
   },
   {
      label: "备件编号",
      prop: "sparePartsNo",
   },
   {
      label: "状态",
      prop: "status",
      slot: "status",
      dataType: "slot",
   },
   {
      label: "价格",
      prop: "price",
   },
   {
      label: "数量",
      prop: "quantity",
   },
   {
      label: "描述",
      prop: "description",
   },
   {
      label: "操作",
      prop: "operation",
      width: 150,
      fixed: 'right',
      align: "center",
      dataType: "action",
      operation: [
         {
            name: "编辑",
            clickFun: (row) => {
               editCategory(row)
            },
         },
         {
            name: "删除",
            clickFun: (row) => {
               deleteCategory(row.id)
            },
         },
      ],
   },
  {
    label: "设备名称",
    prop: "deviceNameStr",
  },
  {
    label: "备件名称",
    prop: "name",
  },
  {
    label: "备件编号",
    prop: "sparePartsNo",
  },
  {
    label: "状态",
    prop: "status",
    slot: "status",
    dataType: "slot",
  },
  {
    label: "价格",
    prop: "price",
  },
  {
    label: "数量",
    prop: "quantity",
  },
  {
    label: "描述",
    prop: "description",
  },
  {
    label: "操作",
    prop: "operation",
    width: 150,
    fixed: 'right',
    align: "center",
    dataType: "action",
    operation: [
      {
        name: "编辑",
        clickFun: (row) => {
          editCategory(row)
        },
      },
      {
        name: "删除",
        clickFun: (row) => {
          deleteCategory(row.id)
        },
      },
    ],
  },
]);
// 表单数据
const form = reactive({
   id:'',
   name: '',
   sparePartsNo: '',
   status: '',
   description: '',
   deviceLedgerIds: [],
   price: null
  id:'',
  name: '',
  sparePartsNo: '',
  status: '',
  description: '',
  deviceLedgerIds: [],
  price: null
});
// 表单验证规则
const rules = reactive({
   name: [
      { required: true, message: '请输入备件名称', trigger: 'blur' }
   ],
   sparePartsNo: [
      { required: true, message: '请输入备件编号', trigger: 'blur' }
   ],
   quantity:[
      { required: true, message: '请输入数量', trigger: 'blur' }
   ],
   status: [
      { required: true, message: '请选择状态', trigger: 'change' }
   ],
   deviceLedgerIds: [
      {
         required: true,
         message: '请选择设备',
         trigger: 'change',
         validator: (rule, value, callback) => {
            if (operationType.value === 'add' && (!value || value.length === 0)) {
               callback(new Error('请选择设备'));
            } else {
               callback();
            }
         }
      }
   ]
  name: [
    { required: true, message: '请输入备件名称', trigger: 'blur' }
  ],
  sparePartsNo: [
    { required: true, message: '请输入备件编号', trigger: 'blur' }
  ],
  quantity:[
    { required: true, message: '请输入数量', trigger: 'blur' }
  ],
  status: [
    { required: true, message: '请选择状态', trigger: 'change' }
  ],
  deviceLedgerIds: [
    {
      required: true,
      message: '请选择设备',
      trigger: 'change',
      validator: (rule, value, callback) => {
        if (operationType.value === 'add' && (!value || value.length === 0)) {
          callback(new Error('请选择设备'));
        } else {
          callback();
        }
      }
    }
  ]
});
// 获取缩进量
const getIndentation = (row) => {
   // 这里简单返回 20,可根据实际需求实现层级缩进逻辑
   return 20;
  // 这里简单返回 20,可根据实际需求实现层级缩进逻辑
  return 20;
};
// 定义 buildTree 函数
const buildTree = (flatData) => {
   const map = {};
   const result = [];
   if(flatData){
      return result;
   }
   flatData.forEach(item => {
      map[item.id] = { ...item, children: [] };
   });
   flatData.forEach(item => {
      if (item.parentId === null || !map[item.parentId]) {
         result.push(map[item.id]);
      } else {
         map[item.parentId].children.push(map[item.id]);
      }
   });
   return result;
  const map = {};
  const result = [];
  if(flatData){
    return result;
  }
  flatData.forEach(item => {
    map[item.id] = { ...item, children: [] };
  });
  flatData.forEach(item => {
    if (item.parentId === null || !map[item.parentId]) {
      result.push(map[item.id]);
    } else {
      map[item.parentId].children.push(map[item.id]);
    }
  });
  return result;
};
// 获取列表数据
const fetchListData = async () => {
   loading.value = true;
   try {
      const params = {
         current: pagination.current,
         size: pagination.size
      };
      if (queryParams.name) {
         params.name = queryParams.name;
      }
      const res = await getSparePartsList(params);
      if (res.code === 200) {
         renderTableData.value = res.data.records || [];
         categories.value = res.data.records || [];
         pagination.total = res.data.total || 0;
      }
   } catch (error) {
  loading.value = true;
  try {
    const params = {
      current: pagination.current,
      size: pagination.size
    };
    if (queryParams.name) {
      params.name = queryParams.name;
    }
    const res = await getSparePartsList(params);
    if (res.code === 200) {
      renderTableData.value = res.data.records || [];
      categories.value = res.data.records || [];
      pagination.total = res.data.total || 0;
    }
  } catch (error) {
      loading.value = false;
   } finally {
      loading.value = false;
   }
  } finally {
    loading.value = false;
  }
}
const fetchUsageData = async () => {
   usageLoading.value = true;
   try {
      const res = await getSparePartsUsagePage({
         current: usagePagination.current,
         size: usagePagination.size,
         sparePartsName: usageQuery.sparePartsName || undefined,
         sourceType: usageQuery.sourceType || undefined,
      });
      if (res?.code === 200) {
         const records = res?.data?.records || [];
         usagePagination.total = res?.data?.total || 0;
         usageTableData.value = records.map((r, idx) => ({
            rowKey: r.id ?? `${usagePagination.current}-${idx}`,
            ...r,
            sourceText: r.sourceText === "" ? "-" : r.sourceText,
         }));
      } else {
         usagePagination.total = 0;
         usageTableData.value = [];
      }
   } finally {
      usageLoading.value = false;
   }
  usageLoading.value = true;
  try {
    const res = await getSparePartsUsagePage({
      current: usagePagination.current,
      size: usagePagination.size,
      sparePartsName: usageQuery.sparePartsName || undefined,
      sourceType: usageQuery.sourceType || undefined,
    });
    if (res?.code === 200) {
      const records = res?.data?.records || [];
      usagePagination.total = res?.data?.total || 0;
      usageTableData.value = records.map((r, idx) => ({
        rowKey: r.id ?? `${usagePagination.current}-${idx}`,
        ...r,
        sourceText: r.sourceText === "" ? "-" : r.sourceText,
      }));
    } else {
      usagePagination.total = 0;
      usageTableData.value = [];
    }
  } finally {
    usageLoading.value = false;
  }
};
const handleUsageQuery = () => {
   usagePagination.current = 1;
   fetchUsageData();
  usagePagination.current = 1;
  fetchUsageData();
};
const resetUsageQuery = () => {
   usageQuery.sparePartsName = "";
   usageQuery.sourceType = "";
   usagePagination.current = 1;
   fetchUsageData();
  usageQuery.sparePartsName = "";
  usageQuery.sourceType = "";
  usagePagination.current = 1;
  fetchUsageData();
};
const handleUsagePageChange = (obj) => {
   usagePagination.current = obj.page;
   usagePagination.size = obj.limit;
   fetchUsageData();
  usagePagination.current = obj.page;
  usagePagination.size = obj.limit;
  fetchUsageData();
};
// 查询
const handleQuery = () => {
   pagination.current = 1;
   fetchListData();
  pagination.current = 1;
  fetchListData();
}
// 重置查询
const resetQuery = () => {
   queryParams.name = '';
   pagination.current = 1;
   fetchListData();
  queryParams.name = '';
  pagination.current = 1;
  pagination.size = 10;
  fetchListData();
}
// 分页变化
// 分页大小改变
const handleSizeChange = ({ page, limit }) => {
   pagination.current = page;
   pagination.size = limit;
   fetchListData();
  pagination.current = page;
  pagination.size = limit;
  fetchListData();
}
// 当前页改变
const handleCurrentChange = (current) => {
  pagination.current = current;
  fetchListData();
}
// 加载设备列表(在打开弹框时调用)
const loadDeviceName = async () => {
   try {
      const { data } = await getDeviceLedger();
      deviceOptions.value = data || [];
   } catch (error) {
      ElMessage.error('获取设备列表失败');
   }
  try {
    const { data } = await getDeviceLedger();
    deviceOptions.value = data || [];
  } catch (error) {
    ElMessage.error('获取设备列表失败');
  }
};
// 新增分类
const addCategory = async () => {
   await loadDeviceName();
   form.id = '';
   form.name = '';
   form.sparePartsNo = '';
   form.status = '';
   form.description = '';
   form.deviceLedgerIds = [];
   form.quantity = undefined;
   form.price = null;
   operationType.value = 'add'
   dialogVisible.value = true;
  await loadDeviceName();
  form.id = '';
  form.name = '';
  form.sparePartsNo = '';
  form.status = '';
  form.description = '';
  form.deviceLedgerIds = [];
  form.quantity = undefined;
  form.price = null;
  operationType.value = 'add'
  dialogVisible.value = true;
};
// 编辑分类
const editCategory = async (row) => {
   await loadDeviceName();
   Object.assign(form, row);
   // 如果后端返回的是 deviceIds 字符串,需要转换为数组
   if (row.deviceIds && typeof row.deviceIds === 'string') {
      // 确保ID类型与设备选项中的ID类型一致
      const deviceIdsArray = row.deviceIds.split(',').map(id => id.trim()).filter(id => id);
      // 如果设备选项中的ID是数字类型,则转换为数字
      if (deviceOptions.value.length > 0 && typeof deviceOptions.value[0].id === 'number') {
         form.deviceLedgerIds = deviceIdsArray.map(id => Number(id)).filter(id => !isNaN(id));
      } else {
         form.deviceLedgerIds = deviceIdsArray;
      }
   } else if (row.deviceIds && Array.isArray(row.deviceIds)) {
      form.deviceLedgerIds = row.deviceIds;
   } else {
      form.deviceLedgerIds = [];
   }
   operationType.value = 'edit'
   dialogVisible.value = true;
  await loadDeviceName();
  Object.assign(form, row);
  // 如果后端返回的是 deviceIds 字符串,需要转换为数组
  if (row.deviceIds && typeof row.deviceIds === 'string') {
    // 确保ID类型与设备选项中的ID类型一致
    const deviceIdsArray = row.deviceIds.split(',').map(id => id.trim()).filter(id => id);
    // 如果设备选项中的ID是数字类型,则转换为数字
    if (deviceOptions.value.length > 0 && typeof deviceOptions.value[0].id === 'number') {
      form.deviceLedgerIds = deviceIdsArray.map(id => Number(id)).filter(id => !isNaN(id));
    } else {
      form.deviceLedgerIds = deviceIdsArray;
    }
  } else if (row.deviceIds && Array.isArray(row.deviceIds)) {
    form.deviceLedgerIds = row.deviceIds;
  } else {
    form.deviceLedgerIds = [];
  }
  operationType.value = 'edit'
  dialogVisible.value = true;
};
// 删除分类
const deleteCategory = async (id) => {
   try {
      await ElMessageBox.confirm('此操作将永久删除该分类,是否继续?', '提示', {
         confirmButtonText: '确定',
         cancelButtonText: '取消',
         type: 'warning'
      });
      loading.value = true;
      const res = await delSparePart(id);
      if (res.code === 200) {
         ElMessage.success('删除成功');
         fetchListData();
      } else {
         ElMessage.error(res.message || '删除失败');
      }
   } catch (error) {
      if (error !== 'cancel') {
         ElMessage.error('删除失败');
      }
   } finally {
      loading.value = false;
   }
  try {
    await ElMessageBox.confirm('此操作将永久删除该分类,是否继续?', '提示', {
      confirmButtonText: '确定',
      cancelButtonText: '取消',
      type: 'warning'
    });
    loading.value = true;
    const res = await delSparePart(id);
    if (res.code === 200) {
      ElMessage.success('删除成功');
      fetchListData();
    } else {
      ElMessage.error(res.message || '删除失败');
    }
  } catch (error) {
    if (error !== 'cancel') {
      ElMessage.error('删除失败');
    }
  } finally {
    loading.value = false;
  }
};
// 提交表单
const submitForm = async () => {
   if (!formRef.value) return;
   try {
      await formRef.value.validate();
      formLoading.value = true;
      // 构建提交数据
      const submitData = {
         ...form,
         deviceIds: form.deviceLedgerIds && form.deviceLedgerIds.length > 0
            ? form.deviceLedgerIds.join(',')
            : ''
      };
      // 删除不需要的字段
      delete submitData.deviceLedgerIds;
      if (operationType.value === 'edit') {
         let res = await editSparePart(submitData);
         if (res.code === 200) {
            ElMessage.success('编辑成功');
            dialogVisible.value = false;
            fetchListData();
         }
      } else {
         let res = await addSparePart(submitData);
         if (res.code === 200) {
            ElMessage.success('新增成功');
            dialogVisible.value = false;
            fetchListData();
         }
      }
   } catch (error) {
      ElMessage.error('请填写完整表单信息');
   } finally {
      formLoading.value = false;
   }
};
// 直接出库
const requisitionDialogVisible = ref(false);
const requisitionLoading = ref(false);
const requisitionFormRef = ref(null);
const requisitionDeviceOptions = ref([]);
const requisitionSparePartsOptions = ref([]);
const selectedSparePartMaxQty = ref(1);
const requisitionForm = reactive({
   deviceLedgerId: null,
   sparePartsId: null,
   quantity: 1,
   remark: '',
});
const requisitionRules = {
   sparePartsId: [{ required: true, message: '请选择备件', trigger: 'change' }],
   quantity: [{ required: true, message: '请输入领用数量', trigger: 'blur' }],
};
const loadRequisitionOptions = async () => {
   try {
      const [deviceRes, spareRes] = await Promise.all([
         getDeviceLedger(),
         getSparePartsList({ current: 1, size: 9999 }),
      ]);
      requisitionDeviceOptions.value = deviceRes.data || [];
      requisitionSparePartsOptions.value = spareRes.data?.records || [];
   } catch (e) {
      ElMessage.error('加载选项失败');
   }
};
const openRequisitionDialog = async () => {
   requisitionForm.deviceLedgerId = null;
   requisitionForm.sparePartsId = null;
   requisitionForm.quantity = 1;
   requisitionForm.remark = '';
   selectedSparePartMaxQty.value = 1;
   await loadRequisitionOptions();
   requisitionDialogVisible.value = true;
};
const onRequisitionSparePartChange = (val) => {
   const selected = requisitionSparePartsOptions.value.find(item => item.id === val);
   selectedSparePartMaxQty.value = selected ? selected.quantity : 1;
   if (requisitionForm.quantity > selectedSparePartMaxQty.value) {
      requisitionForm.quantity = selectedSparePartMaxQty.value;
   }
};
const submitRequisition = async () => {
   if (!requisitionFormRef.value) return;
   try {
      await requisitionFormRef.value.validate();
   } catch {
      return;
   }
   if (requisitionForm.quantity <= 0) {
      ElMessage.warning('领用数量必须大于0');
      return;
   }
   const selected = requisitionSparePartsOptions.value.find(item => item.id === requisitionForm.sparePartsId);
   if (selected && requisitionForm.quantity > selected.quantity) {
      ElMessage.warning(`库存不足,当前库存为 ${selected.quantity}`);
      return;
   }
   requisitionLoading.value = true;
   try {
      const res = await outboundSpareParts({
         deviceLedgerId: requisitionForm.deviceLedgerId || undefined,
         sparePartsId: requisitionForm.sparePartsId,
         quantity: requisitionForm.quantity,
         remark: requisitionForm.remark || undefined,
      });
      if (res.code === 200) {
         ElMessage.success('领用成功');
         requisitionDialogVisible.value = false;
         fetchUsageData();
      } else {
         ElMessage.error(res.msg || '领用失败');
      }
   } catch {
      ElMessage.error('领用失败');
   } finally {
      requisitionLoading.value = false;
   }
  if (!formRef.value) return;
  try {
    await formRef.value.validate();
    formLoading.value = true;
    // 构建提交数据
    const submitData = {
      ...form,
      deviceIds: form.deviceLedgerIds && form.deviceLedgerIds.length > 0
        ? form.deviceLedgerIds.join(',')
        : ''
    };
    // 删除不需要的字段
    delete submitData.deviceLedgerIds;
    if (operationType.value === 'edit') {
      let res = await editSparePart(submitData);
      if (res.code === 200) {
        ElMessage.success('编辑成功');
        dialogVisible.value = false;
        fetchListData();
      }
    } else {
      let res = await addSparePart(submitData);
      if (res.code === 200) {
        ElMessage.success('新增成功');
        dialogVisible.value = false;
        fetchListData();
      }
    }
  } catch (error) {
    ElMessage.error('请填写完整表单信息');
  } finally {
    formLoading.value = false;
  }
};
// 组件挂载时获取列表数据
onMounted(() => {
   fetchListData();
  fetchListData();
});
</script>
<style scoped>
.spare-part-category {
   padding: 20px;
  padding: 20px;
}
.search_form {
   display: flex;
@@ -672,38 +534,38 @@
   justify-content: space-between;
}
.table_list {
   margin-top: unset;
  margin-top: unset;
}
.pagination-container {
   margin-top: 20px;
   display: flex;
   justify-content: flex-end;
  margin-top: 20px;
  display: flex;
  justify-content: flex-end;
}
.el-table__header-wrapper th {
   background-color: #f5f7fa;
   font-weight: 600;
  background-color: #f5f7fa;
  font-weight: 600;
}
.el-table__row:hover > td {
   background-color: #fafafa;
  background-color: #fafafa;
}
/* 按钮组样式 */
.actions > div {
   display: flex;
   gap: 10px;
  display: flex;
  gap: 10px;
}
/* 确保表格中的操作按钮不会被截断 */
.el-table-column--fixed-right .el-button {
   margin: 0 2px;
  margin: 0 2px;
}
/* 树形节点内容样式 */
.nested-tree .el-tree-node__expand-icon {
   font-size: 12px;
   margin-right: 4px;
  font-size: 12px;
  margin-right: 4px;
}
</style>