liding
2026-06-08 db80aba09d2aa09c4e0e091d0b7ebeccb57973fa
src/views/inventoryManagement/stockManagement/Record.vue
@@ -1,222 +1,359 @@
<template>
  <div class="app-container">
    <div class="search_form">
  <div>
    <div class="search_form mb10">
      <el-form ref="searchFormRef"
               :model="searchForm"
               class="demo-form-inline">
        <el-row :gutter="20">
          <el-col :span="4">
            <el-form-item label="产品大类"
                          prop="productName">
              <el-input v-model="searchForm.productName"
                        style="width: 240px"
                        placeholder="请输入"
                        clearable />
            </el-form-item>
          </el-col>
          <el-col :span="4">
            <el-form-item label="规格型号"
                          prop="model">
              <el-input v-model="searchForm.model"
                        style="width: 240px"
                        placeholder="请输入"
                        clearable />
            </el-form-item>
          </el-col>
          <el-col :span="4">
            <el-form-item label="批号"
                          prop="batchNo">
              <el-input v-model="searchForm.batchNo"
                        style="width: 240px"
                        placeholder="请输入"
                        clearable />
            </el-form-item>
          </el-col>
          <!-- 按钮 -->
          <el-col :span="4">
            <el-form-item>
              <el-button type="primary"
                         @click="getList">
                搜索
              </el-button>
              <el-button @click="resetSearch">
                重置
              </el-button>
            </el-form-item>
          </el-col>
        </el-row>
      </el-form>
      <div>
        <span class="search_title ml10">产品大类:</span>
        <el-input v-model="searchForm.productName"
                  style="width: 240px"
                  placeholder="请输入"
                  clearable/>
        <el-button type="primary" @click="handleQuery" style="margin-left: 10px">搜索</el-button>
      </div>
      <div>
         <el-button type="primary" @click="isShowNewModal = true">新增库存</el-button>
        <el-button type="info" plain icon="Upload" @click="isShowImportModal = true">
        <el-button type="primary"
                   @click="isShowNewModal = true">新增库存</el-button>
        <el-button type="info"
                   plain
                   icon="Upload"
                   @click="isShowImportModal = true">
          导入库存
        </el-button>
        <el-button @click="handleOut">导出</el-button>
      </div>
    </div>
    <div class="table_list">
      <el-table :data="tableData" border v-loading="tableLoading" @selection-change="handleSelectionChange"
        :expand-row-keys="expandedRowKeys" :row-key="(row, index) => index" style="width: 100%"
        :row-class-name="tableRowClassName" height="calc(100vh - 18.5em)">
        <el-table-column align="center" type="selection" width="55" />
        <el-table-column align="center" label="序号" type="index" width="60" />
        <el-table-column label="产品大类" prop="productName" show-overflow-tooltip />
        <el-table-column label="规格型号" prop="model" show-overflow-tooltip />
        <el-table-column label="单位" prop="unit" show-overflow-tooltip />
        <el-table-column label="合格库存数量" prop="qualifiedQuantity" show-overflow-tooltip />
        <el-table-column label="不合格库存数量" prop="unQualifiedQuantity" show-overflow-tooltip />
        <el-table-column label="合格冻结数量" prop="qualifiedLockedQuantity" show-overflow-tooltip />
        <el-table-column label="不合格冻结数量" prop="unQualifiedLockedQuantity" show-overflow-tooltip />
        <el-table-column label="库存预警数量" prop="warnNum"  show-overflow-tooltip />
        <el-table-column label="备注" prop="remark"  show-overflow-tooltip />
        <el-table-column label="最近更新时间" prop="updateTime" show-overflow-tooltip />
        <el-table-column fixed="right" label="操作" min-width="90" align="center">
      <el-table :data="tableData"
                border
                v-loading="tableLoading"
                @selection-change="handleSelectionChange"
                :expand-row-keys="expandedRowKeys"
                :row-key="(row, index) => index"
                style="width: 100%"
                :row-class-name="tableRowClassName"
                height="calc(100vh - 18.5em)">
        <el-table-column align="center"
                         type="selection"
                         width="55" />
        <el-table-column align="center"
                         label="序号"
                         type="index"
                         width="60" />
        <el-table-column label="产品名称"
                         prop="productName"
                         show-overflow-tooltip />
        <el-table-column label="规格型号"
                         prop="model"
                         show-overflow-tooltip />
        <el-table-column label="单位"
                         prop="unit"
                         show-overflow-tooltip />
        <el-table-column label="批号"
                         prop="batchNo"
                         show-overflow-tooltip />
        <el-table-column label="合格库存数量"
                         prop="qualifiedQuantity"
                         show-overflow-tooltip />
        <el-table-column label="不合格库存数量"
                         prop="unQualifiedQuantity"
                         show-overflow-tooltip />
        <el-table-column label="合格冻结数量"
                         prop="qualifiedLockedQuantity"
                         show-overflow-tooltip />
        <el-table-column label="不合格冻结数量"
                         prop="unQualifiedLockedQuantity"
                         show-overflow-tooltip />
        <el-table-column label="库存预警数量"
                         prop="warnNum"
                         show-overflow-tooltip />
        <el-table-column label="备注"
                         prop="remark"
                         show-overflow-tooltip />
        <el-table-column label="最近更新时间"
                         prop="updateTime"
                         show-overflow-tooltip />
        <el-table-column fixed="right"
                         label="操作"
                         min-width="80"
                         align="center">
          <template #default="scope">
            <el-button link type="primary" @click="showSubtractModal(scope.row)" :disabled="scope.row.unQualifiedUnLockedQuantity === 0 && scope.row.qualifiedUnLockedQuantity === 0">领用</el-button>
            <el-button link type="primary" v-if="scope.row.unQualifiedUnLockedQuantity > 0 || scope.row.qualifiedUnLockedQuantity > 0" @click="showFrozenModal(scope.row)">冻结</el-button>
            <el-button link type="primary" v-if="scope.row.qualifiedLockedQuantity > 0 || scope.row.unQualifiedLockedQuantity > 0" @click="showThawModal(scope.row)">解冻</el-button>
            <el-button link
                       type="primary"
                       @click="showDetailModal(scope.row)">详情</el-button>
          </template>
        </el-table-column>
      </el-table>
      <pagination v-show="total > 0" :total="total" layout="total, sizes, prev, pager, next, jumper"
        :page="page.current" :limit="page.size" @pagination="paginationChange" />
      <pagination v-show="total > 0"
                  :total="total"
                  layout="total, sizes, prev, pager, next, jumper"
                  :page="page.current"
                  :limit="page.size"
                  @pagination="paginationChange" />
    </div>
    <batch-no-qty-detail v-if="isShowDetailModal"
                         v-model:visible="isShowDetailModal"
                         :record="record"
                         @subtract="handleDetailSubtract"
                         @frozen="handleDetailFrozen"
                         @thaw="handleDetailThaw" />
    <new-stock-inventory v-if="isShowNewModal"
                 v-model:visible="isShowNewModal"
                 :top-product-parent-id="props.productId"
                 @completed="handleQuery" />
                         v-model:visible="isShowNewModal"
                         :top-product-parent-id="props.productId"
                         @completed="handleQuery" />
    <subtract-stock-inventory v-if="isShowSubtractModal"
                 v-model:visible="isShowSubtractModal"
                 :record="record"
                 :type="record.stockType"
                 @completed="handleQuery" />
                              v-model:visible="isShowSubtractModal"
                              :record="record"
                              :type="record.stockType"
                              @completed="handleQuery" />
    <!-- 导入库存-->
    <import-stock-inventory v-if="isShowImportModal"
                 v-model:visible="isShowImportModal"
                 type="qualified"
                 @uploadSuccess="handleQuery" />
                            v-model:visible="isShowImportModal"
                            type="qualified"
                            @uploadSuccess="handleQuery" />
    <!-- 冻结/解冻库存-->
    <frozen-and-thaw-stock-inventory v-if="isShowFrozenAndThawModal"
                 v-model:visible="isShowFrozenAndThawModal"
                 :record="record"
                 :operation-type="operationType"
                 :type="record.stockType"
                 @completed="handleQuery" />
                                     v-model:visible="isShowFrozenAndThawModal"
                                     :record="record"
                                     :operation-type="operationType"
                                     :type="record.stockType"
                                     @completed="handleQuery" />
  </div>
</template>
<script setup>
import pagination from '@/components/PIMTable/Pagination.vue'
import { ref, reactive, toRefs, onMounted, getCurrentInstance } from 'vue'
import {ElMessage, ElMessageBox} from "element-plus";
import {
  getStockInventoryListPageCombined
} from "@/api/inventoryManagement/stockInventory.js";
const props = defineProps({
  productId: {
    type: Number,
    required: true,
    default: 0
  }
});
  import pagination from "@/components/PIMTable/Pagination.vue";
  import { ref, reactive, toRefs, onMounted, getCurrentInstance } from "vue";
  import { ElMessage, ElMessageBox } from "element-plus";
  import { getStockInventoryListPageCombined } from "@/api/inventoryManagement/stockInventory.js";
  const props = defineProps({
    productId: {
      type: Number,
      required: true,
      default: 0,
    },
  });
const NewStockInventory = defineAsyncComponent(() => import("@/views/inventoryManagement/stockManagement/New.vue"));
const SubtractStockInventory = defineAsyncComponent(() => import("@/views/inventoryManagement/stockManagement/Subtract.vue"));
const ImportStockInventory = defineAsyncComponent(() => import("@/views/inventoryManagement/stockManagement/Import.vue"));
const FrozenAndThawStockInventory = defineAsyncComponent(() => import("@/views/inventoryManagement/stockManagement/FrozenAndThaw.vue"));
const { proxy } = getCurrentInstance()
const tableData = ref([])
const selectedRows = ref([])
const record = ref({})
const tableLoading = ref(false)
const page = reactive({
  current: 1,
  size: 100,
})
const total = ref(0)
// 是否显示新增弹框
const isShowNewModal = ref(false)
// 是否显示领用弹框
const isShowSubtractModal = ref(false)
// 是否显示冻结/解冻弹框
const isShowFrozenAndThawModal = ref(false)
// 操作类型
const operationType = ref('frozen')
// 是否显示导入弹框
const isShowImportModal = ref(false)
const data = reactive({
  searchForm: {
    productName: '',
    topParentProductId: props.productId,
  }
})
const { searchForm } = toRefs(data)
  const NewStockInventory = defineAsyncComponent(() =>
    import("@/views/inventoryManagement/stockManagement/New.vue")
  );
  const SubtractStockInventory = defineAsyncComponent(() =>
    import("@/views/inventoryManagement/stockManagement/Subtract.vue")
  );
  const ImportStockInventory = defineAsyncComponent(() =>
    import("@/views/inventoryManagement/stockManagement/Import.vue")
  );
  const FrozenAndThawStockInventory = defineAsyncComponent(() =>
    import("@/views/inventoryManagement/stockManagement/FrozenAndThaw.vue")
  );
  const BatchNoQtyDetail = defineAsyncComponent(() =>
    import("@/views/inventoryManagement/stockManagement/BatchNoQtyDetail.vue")
  );
  const { proxy } = getCurrentInstance();
  const tableData = ref([]);
  const selectedRows = ref([]);
  const record = ref({});
  const tableLoading = ref(false);
  const page = reactive({
    current: 1,
    size: 100,
  });
  const total = ref(0);
  // 是否显示新增弹框
  const isShowNewModal = ref(false);
  // 是否显示领用弹框
  const isShowSubtractModal = ref(false);
  // 是否显示冻结/解冻弹框
  const isShowFrozenAndThawModal = ref(false);
  // 是否显示详情弹框
  const isShowDetailModal = ref(false);
  // 操作类型
  const operationType = ref("frozen");
  // 是否显示导入弹框
  const isShowImportModal = ref(false);
  const data = reactive({
    searchForm: {
      productName: "",
      model: "",
      batchNo: "",
      topParentProductId: props.productId,
    },
  });
  const { searchForm } = toRefs(data);
  const searchFormRef = ref(null);
// 查询列表
/** 搜索按钮操作 */
const handleQuery = () => {
  page.current = 1
  getList()
}
const paginationChange = (obj) => {
  page.current = obj.page;
  page.size = obj.limit;
  getList()
}
const getList = () => {
  tableLoading.value = true
  getStockInventoryListPageCombined({ ...searchForm.value, ...page }).then(res => {
    tableLoading.value = false
    tableData.value = res.data.records
    total.value = res.data.total
    // 数据加载完成后检查库存
    // checkStockAndCreatePurchase();
  }).catch(() => {
    tableLoading.value = false
  })
}
  const resetSearch = () => {
    searchFormRef.value?.resetFields();
    page.current = 1;
    getList();
  };
const handleFileSuccess = (response) => {
  const { code, msg } = response;
  if (code == 200) {
    ElMessage({ message: "导入成功", type: "success" });
    upload.open = false;
    emits("uploadSuccess");
  } else {
    ElMessage({ message: msg, type: "error" });
  }
};
  // 查询列表
  /** 搜索按钮操作 */
  const handleQuery = () => {
    page.current = 1;
    getList();
  };
  const paginationChange = obj => {
    page.current = obj.page;
    page.size = obj.limit;
    getList();
  };
  const getList = () => {
    tableLoading.value = true;
    getStockInventoryListPageCombined({ ...searchForm.value, ...page })
      .then(res => {
        tableLoading.value = false;
        tableData.value = res.data.records;
        total.value = res.data.total;
        // 数据加载完成后检查库存
        // checkStockAndCreatePurchase();
      })
      .catch(() => {
        tableLoading.value = false;
      });
  };
// 点击领用
const showSubtractModal = (row) => {
  record.value = row
  isShowSubtractModal.value = true
}
  const handleFileSuccess = response => {
    const { code, msg } = response;
    if (code == 200) {
      ElMessage({ message: "导入成功", type: "success" });
      upload.open = false;
      emits("uploadSuccess");
    } else {
      ElMessage({ message: msg, type: "error" });
    }
  };
// 点击冻结
const showFrozenModal = (row) => {
  record.value = row
  isShowFrozenAndThawModal.value = true
  operationType.value = 'frozen'
}
  // 点击领用
  const showSubtractModal = row => {
    record.value = row;
    isShowSubtractModal.value = true;
  };
// 点击解冻
const showThawModal = (row) => {
  record.value = row
  isShowFrozenAndThawModal.value = true
  operationType.value = 'thaw'
}
  // 点击详情
  const showDetailModal = row => {
    if (!row?.productId || !row?.productModelId) {
      proxy.$modal.msgError("当前数据缺少产品ID或规格型号ID");
      return;
    }
    record.value = row;
    isShowDetailModal.value = true;
  };
// 表格选择数据
const handleSelectionChange = (selection) => {
  // 过滤掉子数据
  selectedRows.value = selection.filter(item => item.id);
  console.log('selection', selectedRows.value)
}
const expandedRowKeys = ref([])
  const handleDetailSubtract = row => {
    isShowDetailModal.value = false;
    showSubtractModal(row);
  };
// 表格行类名
const tableRowClassName = ({ row }) => {
  const stock = Number(row?.qualifiedUnLockedQuantity ?? 0);
  const warn = Number(row?.warnNum ?? 0);
  if (!Number.isFinite(stock) || !Number.isFinite(warn)) {
    return '';
  }
  return stock < warn ? 'row-low-stock' : '';
};
  const handleDetailFrozen = row => {
    isShowDetailModal.value = false;
    showFrozenModal(row);
  };
// 导出
const handleOut = () => {
  ElMessageBox.confirm(
    '是否确认导出?',
    '导出', {
    confirmButtonText: '确认',
    cancelButtonText: '取消',
    type: 'warning',
  }
  ).then(() => {
    proxy.download("/stockInventory/exportStockInventory", {topParentProductId: props.productId}, '库存信息.xlsx')
  }).catch(() => {
    proxy.$modal.msg("已取消")
  })
}
  const handleDetailThaw = row => {
    isShowDetailModal.value = false;
    showThawModal(row);
  };
onMounted(() => {
  getList()
})
  // 点击冻结
  const showFrozenModal = row => {
    record.value = row;
    isShowFrozenAndThawModal.value = true;
    operationType.value = "frozen";
  };
  // 点击解冻
  const showThawModal = row => {
    record.value = row;
    isShowFrozenAndThawModal.value = true;
    operationType.value = "thaw";
  };
  // 表格选择数据
  const handleSelectionChange = selection => {
    // 过滤掉子数据
    selectedRows.value = selection.filter(item => item.id);
    console.log("selection", selectedRows.value);
  };
  const expandedRowKeys = ref([]);
  // 表格行类名
  const tableRowClassName = ({ row }) => {
    const stock = Number(row?.qualifiedUnLockedQuantity ?? 0);
    const warn = Number(row?.warnNum ?? 0);
    if (!Number.isFinite(stock) || !Number.isFinite(warn)) {
      return "";
    }
    return stock < warn ? "row-low-stock" : "";
  };
  // 导出
  const handleOut = () => {
    ElMessageBox.confirm("是否确认导出?", "导出", {
      confirmButtonText: "确认",
      cancelButtonText: "取消",
      type: "warning",
    })
      .then(() => {
        proxy.download(
          "/stockInventory/exportStockInventory",
          { topParentProductId: props.productId },
          "库存信息.xlsx"
        );
      })
      .catch(() => {
        proxy.$modal.msg("已取消");
      });
  };
  onMounted(() => {
    getList();
  });
</script>
<style scoped lang="scss">
:deep(.row-low-stock td) {
  background-color: #fde2e2;
  color: #c45656;
}
  :deep(.row-low-stock td) {
    background-color: #fde2e2;
    color: #c45656;
  }
:deep(.row-low-stock:hover > td) {
  background-color: #fcd4d4;
}
  :deep(.row-low-stock:hover > td) {
    background-color: #fcd4d4;
  }
</style>