<template> 
 | 
  <div class="app-container"> 
 | 
    <div class="search_form"> 
 | 
      <div> 
 | 
        <span class="search_title">供应商名称:</span> 
 | 
        <el-input v-model="searchForm.supplierName" style="width: 240px" placeholder="请输入" @change="handleQuery" 
 | 
          clearable prefix-icon="Search" /> 
 | 
        <el-button type="primary" @click="handleQuery" style="margin-left: 10px">搜索</el-button> 
 | 
      </div> 
 | 
      <div> 
 | 
        <el-button type="primary" @click="openForm('add')">新增入库</el-button> 
 | 
        <el-button @click="handleOut">导出</el-button> 
 | 
        <el-button type="danger" plain @click="handleDelete">删除</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 => row.id" show-summary style="width: 100%" 
 | 
        :summary-method="summarizeMainTable" height="calc(100vh - 18.5em)" stripe> 
 | 
        <el-table-column align="center" type="selection" width="55" /> 
 | 
        <el-table-column align="center" label="序号" type="index" width="60" /> 
 | 
        <el-table-column label="入库时间" prop="createTime" width="100" show-overflow-tooltip /> 
 | 
        <el-table-column label="入库批次" prop="inboundBatches" width="160" show-overflow-tooltip /> 
 | 
        <el-table-column label="供应商名称" prop="supplierName" width="240" show-overflow-tooltip /> 
 | 
        <el-table-column label="产品大类" prop="productCategory" width="100" show-overflow-tooltip /> 
 | 
        <el-table-column label="规格型号" prop="specificationModel" width="200" show-overflow-tooltip /> 
 | 
        <el-table-column label="单位" prop="unit" width="70" show-overflow-tooltip /> 
 | 
        <el-table-column label="入库数量" prop="inboundNum" width="90" show-overflow-tooltip /> 
 | 
        <el-table-column label="含税单价" prop="taxInclusiveUnitPrice" width="100" show-overflow-tooltip /> 
 | 
        <el-table-column label="含税总价" prop="taxInclusiveTotalPrice" width="100" show-overflow-tooltip /> 
 | 
        <el-table-column label="税率(%)" prop="taxRate" width="80" show-overflow-tooltip /> 
 | 
        <el-table-column label="不含税总价" prop="taxExclusiveTotalPrice" width="100" show-overflow-tooltip /> 
 | 
        <el-table-column label="入库人" prop="createBy" width="80" show-overflow-tooltip /> 
 | 
        <el-table-column fixed="right" label="操作" min-width="60" align="center"> 
 | 
          <template #default="scope"> 
 | 
            <el-button link type="primary" size="small" @click="openForm('edit', scope.row);" :disabled="scope.row.createUser !== userStore.id">编辑</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" /> 
 | 
    </div> 
 | 
  
 | 
    <el-dialog v-model="dialogFormVisible" :title="operationType === 'add' ? '新增入库' : '编辑入库'" width="70%" 
 | 
      @close="closeDia"> 
 | 
      <el-form :model="form" label-width="140px" label-position="top" :rules="rules" ref="formRef"> 
 | 
        <el-form-item label="采购订单号" prop="salesContractNo"> 
 | 
              <el-input 
 | 
                  v-model="form.purchaseContractNumber" 
 | 
                  placeholder="请输入合同号" 
 | 
                  clearable 
 | 
                  @change="searchByContractNo" 
 | 
                  :disabled="operationType === 'edit'" 
 | 
              > 
 | 
                <template #append> 
 | 
                  <el-button 
 | 
                      icon="Search" 
 | 
                      @click="searchByContractNo" 
 | 
                      :loading="loadingProducts" 
 | 
                  /> 
 | 
                </template> 
 | 
              </el-input> 
 | 
            </el-form-item> 
 | 
        <el-table 
 | 
          :data="productList" 
 | 
          border 
 | 
          v-loading="loadingProducts" 
 | 
          @selection-change="handleSelectionChange" 
 | 
          stripe 
 | 
        > 
 | 
          <el-table-column align="center" type="selection" width="55" /> 
 | 
          <el-table-column 
 | 
            align="center" 
 | 
            label="序号" 
 | 
            type="index" 
 | 
            width="60" 
 | 
          /> 
 | 
          <el-table-column label="产品大类" prop="productCategory" /> 
 | 
          <el-table-column label="规格型号" prop="specificationModel" /> 
 | 
          <el-table-column label="单位" prop="unit" width="70" /> 
 | 
          <el-table-column label="供应商" prop="supplierName" width="100" /> 
 | 
          <el-table-column label="采购数量" prop="quantity" width="100" /> 
 | 
          <el-table-column label="待入库数量" prop="quantity0" width="100" /> 
 | 
          <el-table-column label="本次入库数量" prop="quantityStock" width="150"> 
 | 
            <template #default="scope"> 
 | 
              <el-input-number :step="0.01" :min="0" style="width: 100%" v-model="scope.row.quantityStock" :max="scope.row.quantity0" /> 
 | 
            </template> 
 | 
          </el-table-column> 
 | 
          <el-table-column label="税率(%)" prop="taxRate" width="120" /> 
 | 
          <el-table-column 
 | 
            label="含税单价(元)" 
 | 
            prop="taxInclusiveUnitPrice" 
 | 
            :formatter="formattedNumber" 
 | 
            width="150" 
 | 
          /> 
 | 
          <el-table-column 
 | 
            label="含税总价(元)" 
 | 
            prop="taxInclusiveTotalPrice" 
 | 
            :formatter="formattedNumber" 
 | 
            width="150" 
 | 
          /> 
 | 
          <el-table-column 
 | 
            label="不含税总价(元)" 
 | 
            prop="taxExclusiveTotalPrice" 
 | 
            :formatter="formattedNumber" 
 | 
            width="150" 
 | 
          /> 
 | 
        </el-table> 
 | 
      </el-form> 
 | 
      <template #footer> 
 | 
        <div class="dialog-footer"> 
 | 
          <el-button type="primary" @click="submitForm">确认</el-button> 
 | 
          <el-button @click="closeDia">取消</el-button> 
 | 
        </div> 
 | 
      </template> 
 | 
    </el-dialog> 
 | 
  </div> 
 | 
</template> 
 | 
  
 | 
<script setup> 
 | 
import pagination from '@/components/PIMTable/Pagination.vue' 
 | 
import { ref } from 'vue' 
 | 
import { ElMessageBox } from "element-plus"; 
 | 
import useUserStore from '@/store/modules/user' 
 | 
import { 
 | 
  getStockInPage, 
 | 
  updateStockIn, 
 | 
  addSutockIn, 
 | 
  delStockIn, 
 | 
  selectProductRecordListByPuechaserId 
 | 
} from "@/api/inventoryManagement/stockIn.js"; 
 | 
  
 | 
const userStore = useUserStore() 
 | 
const { proxy } = getCurrentInstance() 
 | 
  
 | 
const tableData = ref([]) 
 | 
const selectedRows = ref([]) 
 | 
const userList = ref([]) 
 | 
  
 | 
  
 | 
const loading = ref(false); 
 | 
const tableLoading = ref(false) 
 | 
  
 | 
const page = reactive({ 
 | 
  current: 1, 
 | 
  size: 100, 
 | 
}) 
 | 
const total = ref(0) 
 | 
  
 | 
// 用户信息表单弹框数据 
 | 
const operationType = ref('')// 操作类型: 'add' 或 'edit' 
 | 
const dialogFormVisible = ref(false)// 弹框显示状态 
 | 
const productList = ref([]);// 产品列表数据 
 | 
const loadingProducts = ref(false);// 产品加载状态 
 | 
const productSelectedRows = ref([]) // 产品表格选中行 
 | 
const data = reactive({ 
 | 
  searchForm: { 
 | 
    supplierName: '', 
 | 
  }, 
 | 
  form: { 
 | 
    id: null, 
 | 
    purchaseContractNumber: '', // 采购订单号 
 | 
    supplierId: null,       // 供应商ID 
 | 
    supplierName: '',       // 供应商名称 
 | 
    inboundTime: '',        // 入库时间 
 | 
    inboundBatch: '',       // 入库批次 
 | 
    recorderId: userStore.userId, // 录入人ID 
 | 
    recorderName: userStore.name, // 录入人姓名 
 | 
    entryDate: getCurrentDate(),  // 录入日期 
 | 
    remark: '',             // 备注 
 | 
  }, 
 | 
  rules: { 
 | 
    purchaseContractNumber: [{ required: true, message: "请输入采购合同号", trigger: "blur" }], 
 | 
    supplierId: [{ required: true, message: "请选择供应商", trigger: "change" }], 
 | 
    inboundTime: [{ required: true, message: "请选择入库时间", trigger: "change" }], 
 | 
    inboundBatch: [{ required: true, message: "请输入入库批次", trigger: "blur" }] 
 | 
  } 
 | 
}) 
 | 
const { searchForm, form, rules } = toRefs(data) 
 | 
  
 | 
// 查询列表 
 | 
/** 搜索按钮操作 */ 
 | 
const handleQuery = () => { 
 | 
  page.current = 1 
 | 
  getList() 
 | 
} 
 | 
const paginationChange = (obj) => { 
 | 
  page.current = obj.page; 
 | 
  page.size = obj.limit; 
 | 
  getList() 
 | 
} 
 | 
const getList = () => { 
 | 
  tableLoading.value = true 
 | 
  getStockInPage({ ...searchForm.value, ...page }).then(res => { 
 | 
    tableLoading.value = false 
 | 
    tableData.value = res.data.records 
 | 
    total.value = res.data.total 
 | 
    console.log('tableData:', tableData.value) 
 | 
  }).catch(() => { 
 | 
    tableLoading.value = false 
 | 
  }) 
 | 
} 
 | 
  
 | 
  
 | 
// 调用selectProductRecordListByPuechaserId这个方法根据合同查询到id,再调用getProductRecordByhetong这个方法根据id查询到产品订单记录 
 | 
// 新增根据合同号查询产品记录的方法 
 | 
const searchByContractNo = async () => 
 | 
{ 
 | 
  if (!form.value.purchaseContractNumber) { 
 | 
    proxy.$modal.msgWarning('请输入合同号') 
 | 
    return 
 | 
  } 
 | 
  try { 
 | 
    loadingProducts.value = true 
 | 
    // 根据合同查询产品记录 
 | 
    const productRes = await selectProductRecordListByPuechaserId({ 
 | 
      purchaseContractNumber: form.value.purchaseContractNumber 
 | 
    }); 
 | 
    console.log('productRes:', productRes) 
 | 
    if (!productRes.data || productRes.data.length === 0) { 
 | 
      proxy.$modal.msgWarning('该合同下没有产品记录') 
 | 
      productList.value = []; 
 | 
      return 
 | 
    } 
 | 
    // 处理产品数据,添加本次入库数量字段 
 | 
    productList.value = productRes.data.map(item => ({ 
 | 
      ...item, 
 | 
      quantityStock: 0 // 初始化本次入库数量为0 
 | 
    })) 
 | 
  } catch (error) { 
 | 
    console.error('查询产品记录失败:', error) 
 | 
    proxy.$modal.msgError('查询产品记录失败') 
 | 
    productList.value = []; 
 | 
  } finally { 
 | 
    loadingProducts.value = false 
 | 
  } 
 | 
} 
 | 
  
 | 
  
 | 
// 打开弹框 
 | 
  const openForm = async (type, row) => { 
 | 
    operationType.value = type 
 | 
    dialogFormVisible.value = true 
 | 
    selectedRows.value = [] 
 | 
  
 | 
    if (type === 'add') { 
 | 
      // 新增时初始化表单 
 | 
      form.value = { 
 | 
        id: null, 
 | 
        purchaseContractNumber: '', 
 | 
        supplierId: null, 
 | 
        supplierName: '', 
 | 
        inboundTime: '', 
 | 
        inboundBatch: '', 
 | 
        recorderId: userStore.userId, 
 | 
        recorderName: userStore.name, 
 | 
        entryDate: getCurrentDate(), 
 | 
        remark: '' 
 | 
      } 
 | 
      productList.value = [] // 清空产品列表 
 | 
    } else { 
 | 
      form.value = JSON.parse(JSON.stringify(row)) 
 | 
      try { 
 | 
        loadingProducts.value = true 
 | 
        // 根据合同号加载对应的产品列表(假设 getProductByContract 是可用接口) 
 | 
        const res = await selectProductRecordListByPuechaserId({ 
 | 
          purchaseContractNumber: form.value.purchaseContractNumber, 
 | 
          id: row.id 
 | 
        }); 
 | 
        productList.value = res.data.map(item => ({ 
 | 
          ...item, 
 | 
          quantityStock: row.inboundNum // 如果已有入库数量则保留 
 | 
        })) 
 | 
        selectedRows.value = productList.value 
 | 
      } catch (error) { 
 | 
        console.error('加载产品失败:', error) 
 | 
        proxy.$modal.msgError('加载产品失败') 
 | 
        productList.value = [] 
 | 
      } finally { 
 | 
        loadingProducts.value = false 
 | 
      } 
 | 
    } 
 | 
  } 
 | 
  
 | 
  const updatePro = async () => { 
 | 
    // 准备提交数据 
 | 
    // 准备提交数据 - 修改为后端需要的格式 
 | 
    const stockInData = { 
 | 
      id: selectedRows.value[0].recordId, 
 | 
      quantityStock: Number(selectedRows.value[0].quantityStock),// 使用新格式化函数 
 | 
    }; 
 | 
    await updateStockIn(stockInData) 
 | 
    proxy.$modal.msgSuccess('修改入库成功') 
 | 
    closeDia() 
 | 
    getList() // 刷新列表 
 | 
  } 
 | 
  
 | 
// 提交表单 
 | 
  const submitForm = async () => { 
 | 
    // 验证至少选择了一个产品 
 | 
    if (selectedRows.value.length === 0) { 
 | 
      proxy.$modal.msgError('请先查询并选择产品') 
 | 
      return 
 | 
    } 
 | 
    if(operationType.value !== 'add'){ 
 | 
      await updatePro() 
 | 
      return 
 | 
    } 
 | 
    try { 
 | 
      await proxy.$refs.formRef.validate() 
 | 
      // 验证入库数量 
 | 
      const invalidProducts = selectedRows.value.filter( 
 | 
          product => product.quantityStock <= 0 || product.quantityStock > product.quantity0 
 | 
      ) 
 | 
  
 | 
      if (invalidProducts.length > 0) { 
 | 
        proxy.$modal.msgError('请为所有产品输入有效的入库数量') 
 | 
        return 
 | 
      } 
 | 
  
 | 
      // 准备提交数据 
 | 
      // 准备提交数据 - 修改为后端需要的格式 
 | 
      const stockInData = { 
 | 
        // 入库单基本信息 
 | 
        ...form.value, 
 | 
        inboundTime: formatDateTime(form.value.inboundTime), 
 | 
        nickName: userStore.nickName,// 使用新格式化函数 
 | 
        details: selectedRows.value.map(product => ({ 
 | 
          id: product.id, 
 | 
          inboundQuantity: Number(product.quantityStock) 
 | 
        })), 
 | 
      }; 
 | 
      console.log('准备提交的数据:', JSON.parse(JSON.stringify(stockInData))); 
 | 
      // 调用API 
 | 
      loading.value = true 
 | 
      await addSutockIn(stockInData) 
 | 
  
 | 
      proxy.$modal.msgSuccess('新增入库成功') 
 | 
      closeDia() 
 | 
      getList() // 刷新列表 
 | 
  
 | 
    } catch (error) { 
 | 
      console.error('提交失败:', error) 
 | 
      if (!error.errors) { 
 | 
        proxy.$modal.msgError('操作失败,请重试') 
 | 
      } 
 | 
    } finally { 
 | 
      loading.value = false 
 | 
    } 
 | 
  } 
 | 
  
 | 
// 关闭弹框 
 | 
  const closeDia = () => { 
 | 
    proxy.$refs.formRef.resetFields() 
 | 
    dialogFormVisible.value = false 
 | 
  
 | 
  } 
 | 
// 表格选择数据 
 | 
  const handleSelectionChange = (selection) => { 
 | 
    // 过滤掉子数据 
 | 
    selectedRows.value = selection.filter(item => item.id); 
 | 
    console.log('selection', selectedRows.value) 
 | 
  } 
 | 
  
 | 
  const expandedRowKeys = ref([]) 
 | 
  
 | 
// 主表合计方法 
 | 
  const summarizeMainTable = (param) => { 
 | 
    return proxy.summarizeTable(param, ['contractAmount', 'taxInclusiveTotalPrice', 'taxExclusiveTotalPrice']); 
 | 
  }; 
 | 
  
 | 
// 导出 
 | 
  const handleOut = () => { 
 | 
    ElMessageBox.confirm( 
 | 
        '是否确认导出?', 
 | 
        '导出', { 
 | 
          confirmButtonText: '确认', 
 | 
          cancelButtonText: '取消', 
 | 
          type: 'warning', 
 | 
        } 
 | 
    ).then(() => { 
 | 
      proxy.download("/stockin/export", {}, '入库台账.xlsx') 
 | 
    }).catch(() => { 
 | 
      proxy.$modal.msg("已取消") 
 | 
    }) 
 | 
  } 
 | 
// 删除 
 | 
  const handleDelete = () => { 
 | 
    let ids = [] 
 | 
    if (selectedRows.value.length > 0) { 
 | 
            // 检查是否有他人维护的数据 
 | 
            const unauthorizedData = selectedRows.value.filter(item => item.createUser !== userStore.id); 
 | 
            if (unauthorizedData.length > 0) { 
 | 
                proxy.$modal.msgWarning("不可删除他人维护的数据"); 
 | 
                return; 
 | 
            } 
 | 
      ids = selectedRows.value.map(item => item.id); 
 | 
    } else { 
 | 
      proxy.$modal.msgWarning('请选择数据') 
 | 
      return 
 | 
    } 
 | 
    ElMessageBox.confirm( 
 | 
        '选中的内容将被删除,是否确认删除?', 
 | 
        '导出', { 
 | 
          confirmButtonText: '确认', 
 | 
          cancelButtonText: '取消', 
 | 
          type: 'warning', 
 | 
        } 
 | 
    ).then(() => { 
 | 
      delStockIn({ids:ids}).then(res => { 
 | 
        proxy.$modal.msgSuccess("删除成功") 
 | 
        getList() 
 | 
      }) 
 | 
    }).catch(() => { 
 | 
      proxy.$modal.msg("已取消") 
 | 
    }) 
 | 
  } 
 | 
  
 | 
// 获取当前日期并格式化为 YYYY-MM-DD 
 | 
// 修改为更通用的日期时间格式化函数 
 | 
function formatDateTime(date = new Date(), includeTime = true) { 
 | 
  const d = new Date(date); 
 | 
  const year = d.getFullYear(); 
 | 
  const month = String(d.getMonth() + 1).padStart(2, '0'); 
 | 
  const day = String(d.getDate()).padStart(2, '0'); 
 | 
  
 | 
  if (!includeTime) { 
 | 
    return `${year}-${month}-${day}`; // 保持原有 getCurrentDate 功能 
 | 
  } 
 | 
  
 | 
  // 新增时间部分格式化 
 | 
  const hours = String(d.getHours()).padStart(2, '0'); 
 | 
  const minutes = String(d.getMinutes()).padStart(2, '0'); 
 | 
  const seconds = String(d.getSeconds()).padStart(2, '0'); 
 | 
  
 | 
  return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`; 
 | 
} 
 | 
  
 | 
// 保持原有 getCurrentDate 的兼容性 
 | 
function getCurrentDate() { 
 | 
  return formatDateTime(new Date(), false); 
 | 
} 
 | 
  
 | 
  
 | 
  
 | 
  
 | 
  onMounted(() => { 
 | 
    getList() 
 | 
  }) 
 | 
</script> 
 | 
  
 | 
<style scoped lang="scss"></style> 
 |