| | |
| | | </PIMTable> |
| | | </div> |
| | | |
| | | <el-dialog title="对账明细" v-model="detailDialogVisible" width="900px" append-to-body> |
| | | <FormDialog title="对账明细" v-model="detailDialogVisible" width="900px" @confirm="printDetail" @cancel="detailDialogVisible = false" operationType="detail"> |
| | | <div class="statement-header"> |
| | | <h3>{{ currentSupplier }} 应付对账单</h3> |
| | | <p>对账期间: {{ currentPeriod }}</p> |
| | |
| | | <el-table-column prop="remark" label="备注" show-overflow-tooltip /> |
| | | </el-table> |
| | | <template #footer> |
| | | <el-button @click="detailDialogVisible = false">关闭</el-button> |
| | | <el-button type="primary" @click="printDetail">打印</el-button> |
| | | <el-button @click="detailDialogVisible = false">关闭</el-button> |
| | | </template> |
| | | </el-dialog> |
| | | </FormDialog> |
| | | |
| | | <FormDialog title="生成对账单" v-model="generateDialogVisible" width="1000px" @confirm="confirmGenerate" @cancel="generateDialogVisible = false"> |
| | | <el-form :model="generateForm" label-width="100px"> |
| | | <el-row :gutter="20"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="选择供应商" prop="supplierId"> |
| | | <el-select v-model="generateForm.supplierId" placeholder="请选择供应商" style="width: 100%;" @change="onSupplierChange"> |
| | | <el-option v-for="item in supplierList" :key="item.id" :label="item.name" :value="item.id" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="对账月份" prop="period"> |
| | | <el-date-picker v-model="generateForm.period" type="month" placeholder="选择月份" value-format="YYYY-MM" style="width: 100%;" @change="onPeriodChange" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | </el-form> |
| | | |
| | | <div v-if="purchaseData.length > 0" class="purchase-section"> |
| | | <div class="section-title">本月采购数据</div> |
| | | <el-table :data="purchaseData" border style="width: 100%; margin-bottom: 15px;" v-loading="purchaseLoading" @selection-change="handlePurchaseSelectionChange"> |
| | | <el-table-column type="selection" width="55" align="center" /> |
| | | <el-table-column prop="date" label="日期" width="120" /> |
| | | <el-table-column prop="code" label="单据编号" width="150" /> |
| | | <el-table-column prop="type" label="类型" width="100"> |
| | | <template #default="{ row }"> |
| | | <el-tag :type="row.type === '入库' ? 'success' : 'danger'">{{ row.type }}</el-tag> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="amount" label="金额" width="120"> |
| | | <template #default="{ row }"> |
| | | <span :class="row.type === '入库' ? 'text-danger' : 'text-success'">¥{{ formatMoney(row.amount) }}</span> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="remark" label="备注" /> |
| | | </el-table> |
| | | |
| | | <div class="summary-row"> |
| | | <span>期初余额: <strong class="text-primary">¥{{ formatMoney(generateForm.beginBalance) }}</strong></span> |
| | | <span>本期应付: <strong class="text-danger">¥{{ formatMoney(generateForm.currentPayable) }}</strong></span> |
| | | <span>本期付款: <strong class="text-success">¥{{ formatMoney(generateForm.currentPayment) }}</strong></span> |
| | | <span>期末余额: <strong class="text-primary">¥{{ formatMoney(calculateEndBalance(generateForm.beginBalance, generateForm.currentPayable, generateForm.currentPayment)) }}</strong></span> |
| | | </div> |
| | | </div> |
| | | |
| | | <div v-else-if="generateForm.supplierId && !purchaseLoading" class="empty-tip"> |
| | | <el-empty description="该供应商本月暂无采购数据" /> |
| | | </div> |
| | | |
| | | <template #footer> |
| | | <el-button type="primary" @click="confirmGenerate" :disabled="!canGenerate">确认生成</el-button> |
| | | <el-button @click="generateDialogVisible = false">取消</el-button> |
| | | </template> |
| | | </FormDialog> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { ref, reactive, onMounted } from "vue"; |
| | | import { ref, reactive, onMounted, computed } from "vue"; |
| | | import { ElMessage } from "element-plus"; |
| | | import FormDialog from "@/components/Dialog/FormDialog.vue"; |
| | | |
| | | defineOptions({ |
| | | name: "应付对账", |
| | |
| | | const currentPeriod = ref(""); |
| | | const detailData = ref([]); |
| | | |
| | | const generateDialogVisible = ref(false); |
| | | const purchaseLoading = ref(false); |
| | | const purchaseData = ref([]); |
| | | const selectedPurchases = ref([]); |
| | | |
| | | const generateForm = reactive({ |
| | | supplierId: "", |
| | | supplierName: "", |
| | | period: "", |
| | | beginBalance: 0, |
| | | currentPayable: 0, |
| | | currentPayment: 0, |
| | | }); |
| | | |
| | | const canGenerate = computed(() => { |
| | | return generateForm.supplierId && generateForm.period && selectedPurchases.value.length > 0; |
| | | }); |
| | | |
| | | const supplierList = [ |
| | | { id: 1, name: "北京原材料供应商" }, |
| | | { id: 2, name: "上海电子元器件公司" }, |
| | |
| | | { id: 2, statementCode: "DZ202401002", supplierId: 2, supplierName: "上海电子元器件公司", period: "2024-01", beginBalance: 10000, currentPayable: 20000, currentPayment: 15000, endBalance: 15000 }, |
| | | { id: 3, statementCode: "DZ202402001", supplierId: 1, supplierName: "北京原材料供应商", period: "2024-02", beginBalance: 25000, currentPayable: 18000, currentPayment: 20000, endBalance: 23000 }, |
| | | ]; |
| | | |
| | | const calculateEndBalance = (beginBalance, currentPayable, currentPayment) => { |
| | | return beginBalance + currentPayable - currentPayment; |
| | | }; |
| | | |
| | | const formatMoney = (value) => { |
| | | if (value === undefined || value === null) return "0.00"; |
| | |
| | | }; |
| | | |
| | | const generateStatement = () => { |
| | | ElMessage.success("对账单生成成功"); |
| | | generateForm.supplierId = ""; |
| | | generateForm.supplierName = ""; |
| | | generateForm.period = ""; |
| | | generateForm.beginBalance = 0; |
| | | generateForm.currentPayable = 0; |
| | | generateForm.currentPayment = 0; |
| | | purchaseData.value = []; |
| | | selectedPurchases.value = []; |
| | | generateDialogVisible.value = true; |
| | | }; |
| | | |
| | | const onSupplierChange = (supplierId) => { |
| | | const supplier = supplierList.find(item => item.id === supplierId); |
| | | if (supplier) { |
| | | generateForm.supplierName = supplier.name; |
| | | } |
| | | loadPurchaseData(); |
| | | }; |
| | | |
| | | const onPeriodChange = () => { |
| | | loadPurchaseData(); |
| | | }; |
| | | |
| | | const loadPurchaseData = () => { |
| | | if (!generateForm.supplierId || !generateForm.period) { |
| | | purchaseData.value = []; |
| | | return; |
| | | } |
| | | |
| | | purchaseLoading.value = true; |
| | | |
| | | setTimeout(() => { |
| | | const mockPurchaseData = [ |
| | | { id: 1, date: generateForm.period + "-05", code: "RK2024001", type: "入库", amount: 8000, remark: "原材料采购" }, |
| | | { id: 2, date: generateForm.period + "-10", code: "FK2024001", type: "付款", amount: 5000, remark: "支付货款" }, |
| | | { id: 3, date: generateForm.period + "-15", code: "RK2024002", type: "入库", amount: 12000, remark: "电子元器件" }, |
| | | { id: 4, date: generateForm.period + "-18", code: "TH2024001", type: "退货", amount: 2000, remark: "质量问题退货" }, |
| | | { id: 5, date: generateForm.period + "-22", code: "RK2024003", type: "入库", amount: 6000, remark: "包装材料" }, |
| | | { id: 6, date: generateForm.period + "-25", code: "FK2024002", type: "付款", amount: 8000, remark: "支付货款" }, |
| | | ]; |
| | | |
| | | purchaseData.value = mockPurchaseData; |
| | | |
| | | const lastPeriod = getLastPeriod(generateForm.period); |
| | | const lastStatement = mockData.find(item => |
| | | item.supplierId === generateForm.supplierId && item.period === lastPeriod |
| | | ); |
| | | generateForm.beginBalance = lastStatement ? lastStatement.endBalance : 0; |
| | | |
| | | calculateSummary(); |
| | | |
| | | purchaseLoading.value = false; |
| | | }, 500); |
| | | }; |
| | | |
| | | const getLastPeriod = (period) => { |
| | | const [year, month] = period.split("-").map(Number); |
| | | if (month === 1) { |
| | | return `${year - 1}-12`; |
| | | } |
| | | return `${year}-${String(month - 1).padStart(2, "0")}`; |
| | | }; |
| | | |
| | | const calculateSummary = () => { |
| | | let payable = 0; |
| | | let payment = 0; |
| | | |
| | | selectedPurchases.value.forEach(item => { |
| | | if (item.type === "入库") { |
| | | payable += item.amount; |
| | | } else if (item.type === "退货") { |
| | | payable -= item.amount; |
| | | } else if (item.type === "付款") { |
| | | payment += item.amount; |
| | | } |
| | | }); |
| | | |
| | | generateForm.currentPayable = payable; |
| | | generateForm.currentPayment = payment; |
| | | }; |
| | | |
| | | const handlePurchaseSelectionChange = (selection) => { |
| | | selectedPurchases.value = selection; |
| | | calculateSummary(); |
| | | }; |
| | | |
| | | const confirmGenerate = () => { |
| | | const newId = mockData.length > 0 ? Math.max(...mockData.map(item => item.id)) + 1 : 1; |
| | | const supplier = supplierList[Math.floor(Math.random() * supplierList.length)]; |
| | | const endBalance = calculateEndBalance(generateForm.beginBalance, generateForm.currentPayable, generateForm.currentPayment); |
| | | |
| | | mockData.unshift({ |
| | | id: newId, |
| | | statementCode: "DZ" + Date.now(), |
| | | supplierId: supplier.id, |
| | | supplierName: supplier.name, |
| | | period: "2024-03", |
| | | beginBalance: Math.floor(Math.random() * 20000), |
| | | currentPayable: Math.floor(Math.random() * 25000), |
| | | currentPayment: Math.floor(Math.random() * 20000), |
| | | endBalance: Math.floor(Math.random() * 25000), |
| | | supplierId: generateForm.supplierId, |
| | | supplierName: generateForm.supplierName, |
| | | period: generateForm.period, |
| | | beginBalance: generateForm.beginBalance, |
| | | currentPayable: generateForm.currentPayable, |
| | | currentPayment: generateForm.currentPayment, |
| | | endBalance, |
| | | }); |
| | | |
| | | generateDialogVisible.value = false; |
| | | ElMessage.success("对账单生成成功"); |
| | | getTableData(); |
| | | }; |
| | | |
| | | const viewDetail = (row) => { |
| | | currentSupplier.value = row.supplierName; |
| | | currentPeriod.value = row.period; |
| | | |
| | | const purchaseInAmount = Math.floor(row.currentPayable * 0.7); |
| | | const returnAmount = Math.floor(row.currentPayable * 0.1); |
| | | const firstPayment = Math.floor(row.currentPayment * 0.5); |
| | | const secondPayment = row.currentPayment - firstPayment; |
| | | |
| | | let runningBalance = row.beginBalance; |
| | | |
| | | detailData.value = [ |
| | | { date: row.period + "-01", type: "期初", code: "-", debit: 0, credit: 0, balance: row.beginBalance, remark: "期初余额" }, |
| | | { date: row.period + "-05", type: "入库", code: "RK2024001", debit: 0, credit: 8000, balance: row.beginBalance + 8000, remark: "" }, |
| | | { date: row.period + "-10", type: "付款", code: "FK2024001", debit: 5000, credit: 0, balance: row.beginBalance + 3000, remark: "" }, |
| | | { date: row.period + "-15", type: "入库", code: "RK2024002", credit: 12000, balance: row.beginBalance + 15000, remark: "" }, |
| | | { date: row.period + "-20", type: "退货", code: "TH2024001", debit: 2000, credit: 0, balance: row.beginBalance + 13000, remark: "" }, |
| | | { date: row.period + "-25", type: "付款", code: "FK2024002", debit: row.currentPayment - 5000, balance: row.endBalance, remark: "" }, |
| | | { date: row.period + "-01", type: "期初", code: "-", debit: 0, credit: 0, balance: runningBalance, remark: "期初余额" }, |
| | | { date: row.period + "-05", type: "入库", code: "RK2024001", debit: 0, credit: purchaseInAmount, balance: runningBalance += purchaseInAmount, remark: "采购入库" }, |
| | | { date: row.period + "-10", type: "付款", code: "FK2024001", debit: firstPayment, credit: 0, balance: runningBalance -= firstPayment, remark: "支付货款" }, |
| | | { date: row.period + "-15", type: "入库", code: "RK2024002", debit: 0, credit: row.currentPayable - purchaseInAmount - returnAmount, balance: runningBalance += (row.currentPayable - purchaseInAmount - returnAmount), remark: "采购入库" }, |
| | | { date: row.period + "-20", type: "退货", code: "TH2024001", debit: 0, credit: -returnAmount, balance: runningBalance -= returnAmount, remark: "采购退货" }, |
| | | { date: row.period + "-25", type: "付款", code: "FK2024002", debit: secondPayment, credit: 0, balance: runningBalance -= secondPayment, remark: "支付货款" }, |
| | | ]; |
| | | |
| | | detailDialogVisible.value = true; |
| | | }; |
| | | |
| | |
| | | margin: 0; |
| | | } |
| | | } |
| | | |
| | | .purchase-section { |
| | | margin-top: 20px; |
| | | |
| | | .section-title { |
| | | font-size: 16px; |
| | | font-weight: bold; |
| | | margin-bottom: 15px; |
| | | padding-left: 10px; |
| | | border-left: 4px solid #409eff; |
| | | } |
| | | } |
| | | |
| | | .summary-row { |
| | | display: flex; |
| | | justify-content: space-around; |
| | | padding: 15px; |
| | | background-color: #f5f7fa; |
| | | border-radius: 4px; |
| | | margin-top: 15px; |
| | | |
| | | span { |
| | | font-size: 14px; |
| | | |
| | | strong { |
| | | font-size: 16px; |
| | | margin-left: 5px; |
| | | } |
| | | } |
| | | } |
| | | |
| | | .empty-tip { |
| | | margin-top: 30px; |
| | | } |
| | | |
| | | .text-primary { |
| | | color: #409eff; |
| | | } |
| | | </style> |