From 261f2ed00235d47df3754291a4fdca9ba5cb8e7a Mon Sep 17 00:00:00 2001
From: spring <2396852758@qq.com>
Date: 星期四, 21 五月 2026 17:16:09 +0800
Subject: [PATCH] fix: 合并财务数据
---
src/views/financialManagement/payable/reconciliation.vue | 613 +++++++++++++++++++++++++++++++++++++++++--------------
1 files changed, 455 insertions(+), 158 deletions(-)
diff --git a/src/views/financialManagement/payable/reconciliation.vue b/src/views/financialManagement/payable/reconciliation.vue
index 3aa23cd..e749e56 100644
--- a/src/views/financialManagement/payable/reconciliation.vue
+++ b/src/views/financialManagement/payable/reconciliation.vue
@@ -2,8 +2,13 @@
<div class="app-container">
<el-form :model="filters" :inline="true">
<el-form-item label="渚涘簲鍟�:">
- <el-select v-model="filters.supplierId" placeholder="璇烽�夋嫨渚涘簲鍟�" clearable style="width: 200px;">
- <el-option v-for="item in supplierList" :key="item.id" :label="item.name" :value="item.id" />
+ <el-select v-model="filters.supplierId" placeholder="璇烽�夋嫨渚涘簲鍟�" clearable filterable style="width: 200px;">
+ <el-option
+ v-for="item in supplierList"
+ :key="item.id"
+ :label="item.supplierName"
+ :value="item.id"
+ />
</el-select>
</el-form-item>
<el-form-item label="瀵硅处鏈熼棿:">
@@ -12,7 +17,7 @@
<el-date-picker v-model="filters.endMonth" type="month" placeholder="缁撴潫鏈堜唤" value-format="YYYY-MM" style="width: 140px;" />
</el-form-item>
<el-form-item>
- <el-button type="primary" @click="getTableData">鎼滅储</el-button>
+ <el-button type="primary" @click="onSearch">鎼滅储</el-button>
<el-button @click="resetFilters">閲嶇疆</el-button>
</el-form-item>
</el-form>
@@ -29,6 +34,7 @@
rowKey="id"
:column="columns"
:tableData="dataList"
+ :tableLoading="tableLoading"
:page="{
current: pagination.currentPage,
size: pagination.pageSize,
@@ -36,21 +42,21 @@
}"
@pagination="changePage"
>
- <template #beginBalance="{ row }">
- <span :class="row.beginBalance >= 0 ? 'text-success' : 'text-danger'">楼{{ formatMoney(row.beginBalance) }}</span>
+ <template #openingBalance="{ row }">
+ <span :class="row.openingBalance >= 0 ? 'text-success' : 'text-danger'">楼{{ formatMoney(row.openingBalance) }}</span>
</template>
- <template #currentPayable="{ row }">
- <span class="text-danger">楼{{ formatMoney(row.currentPayable) }}</span>
+ <template #currentPlan="{ row }">
+ <span class="text-danger">楼{{ formatMoney(row.currentPlan) }}</span>
</template>
- <template #currentPayment="{ row }">
- <span class="text-success">楼{{ formatMoney(row.currentPayment) }}</span>
+ <template #currentActually="{ row }">
+ <span class="text-success">楼{{ formatMoney(row.currentActually) }}</span>
</template>
- <template #endBalance="{ row }">
- <span :class="row.endBalance >= 0 ? 'text-success' : 'text-danger'">楼{{ formatMoney(row.endBalance) }}</span>
+ <template #closingBalance="{ row }">
+ <span :class="row.closingBalance >= 0 ? 'text-success' : 'text-danger'">楼{{ formatMoney(row.closingBalance) }}</span>
</template>
<template #operation="{ row }">
<el-button type="primary" link @click="viewDetail(row)">鏌ョ湅鏄庣粏</el-button>
- <el-button type="primary" link @click="printStatement(row)">鎵撳嵃</el-button>
+ <el-button type="danger" link @click="handleDelete(row)">鍒犻櫎</el-button>
</template>
</PIMTable>
</div>
@@ -60,7 +66,7 @@
<h3>{{ currentSupplier }} 搴斾粯瀵硅处鍗�</h3>
<p>瀵硅处鏈熼棿: {{ currentPeriod }}</p>
</div>
- <el-table :data="detailData" border style="width: 100%">
+ <el-table :data="detailData" border style="width: 100%" v-loading="detailLoading">
<el-table-column prop="date" label="鏃ユ湡" width="120" />
<el-table-column prop="type" label="绫诲瀷" width="100">
<template #default="{ row }">
@@ -77,6 +83,7 @@
<el-table-column prop="credit" label="璐锋柟(搴斾粯)" width="120">
<template #default="{ row }">
<span v-if="row.credit > 0" class="text-danger">楼{{ formatMoney(row.credit) }}</span>
+ <span v-else-if="row.credit < 0" class="text-success">楼{{ formatMoney(Math.abs(row.credit)) }}</span>
<span v-else>-</span>
</template>
</el-table-column>
@@ -98,52 +105,80 @@
<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
+ v-model="generateForm.supplierId"
+ placeholder="璇烽�夋嫨渚涘簲鍟�"
+ style="width: 100%;"
+ filterable
+ @change="onSupplierChange"
+ >
+ <el-option
+ v-for="item in supplierList"
+ :key="item.id"
+ :label="item.supplierName"
+ :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 label="瀵硅处鏈堜唤" prop="statementMonth">
+ <el-date-picker
+ v-model="generateForm.statementMonth"
+ type="month"
+ placeholder="閫夋嫨鏈堜唤"
+ value-format="YYYY-MM"
+ style="width: 100%;"
+ @change="onStatementMonthChange"
+ />
</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">
+ <div v-if="statementDetailLoaded" class="purchase-section">
+ <div v-if="purchaseData.length > 0" class="section-title">鏈湀閲囪喘鏁版嵁</div>
+ <el-table
+ v-if="purchaseData.length > 0"
+ ref="purchaseTableRef"
+ :data="purchaseData"
+ border
+ row-key="id"
+ 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="occurrenceDate" label="鏃ユ湡" width="120" />
+ <el-table-column prop="receiptNumber" 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>
+ <el-tag :type="getDetailTypeTagType(row.type)">{{ row.typeLabel }}</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>
+ <span :class="getDetailAmountClass(row.type)">楼{{ formatMoney(row.amount) }}</span>
</template>
</el-table-column>
<el-table-column prop="remark" label="澶囨敞" />
</el-table>
+ <el-empty v-else description="璇ヤ緵搴斿晢鏈湀鏆傛棤鏄庣粏鏁版嵁" :image-size="80" />
<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>
+ <span>鏈熷垵浣欓: <strong class="text-primary">楼{{ formatMoney(generateForm.openingBalance) }}</strong></span>
+ <span>鏈湡搴斾粯: <strong class="text-danger">楼{{ formatMoney(generateForm.currentPlan) }}</strong></span>
+ <span>鏈湡浠樻: <strong class="text-success">楼{{ formatMoney(generateForm.currentActually) }}</strong></span>
+ <span>鏈熸湯浣欓: <strong :class="displayClosingBalance >= 0 ? 'text-success' : 'text-danger'">楼{{ formatMoney(displayClosingBalance) }}</strong></span>
</div>
</div>
- <div v-else-if="generateForm.supplierId && !purchaseLoading" class="empty-tip">
+ <div v-else-if="generateForm.supplierId && generateForm.statementMonth && !purchaseLoading" class="empty-tip">
<el-empty description="璇ヤ緵搴斿晢鏈湀鏆傛棤閲囪喘鏁版嵁" />
</div>
<template #footer>
- <el-button type="primary" @click="confirmGenerate" :disabled="!canGenerate">纭鐢熸垚</el-button>
+ <el-button type="primary" @click="confirmGenerate" :disabled="!canGenerate" :loading="submitLoading">纭鐢熸垚</el-button>
<el-button @click="generateDialogVisible = false">鍙栨秷</el-button>
</template>
</FormDialog>
@@ -151,9 +186,20 @@
</template>
<script setup>
-import { ref, reactive, onMounted, computed } from "vue";
-import { ElMessage } from "element-plus";
+import { ref, reactive, onMounted, computed, nextTick, getCurrentInstance } from "vue";
+import { ElMessage, ElMessageBox } from "element-plus";
import FormDialog from "@/components/Dialog/FormDialog.vue";
+import { getOptions } from "@/api/procurementManagement/procurementLedger.js";
+import {
+ getAccountStatementDetailsByMonth,
+ addAccountStatement,
+ listPageAccountStatement,
+ deleteAccountStatement,
+} from "@/api/financialManagement/accountStatement.js";
+
+const ACCOUNT_TYPE_PAYABLE = 2;
+
+const { proxy } = getCurrentInstance();
defineOptions({
name: "搴斾粯瀵硅处",
@@ -172,56 +218,192 @@
});
const columns = [
- { label: "瀵硅处鍗曞彿", prop: "statementCode", width: "150" },
+ { label: "瀵硅处鍗曞彿", prop: "statementNumber", width: "150" },
{ label: "渚涘簲鍟�", prop: "supplierName", width: "180" },
- { label: "瀵硅处鏈熼棿", prop: "period", width: "150" },
- { label: "鏈熷垵浣欓", prop: "beginBalance", slot: "beginBalance" },
- { label: "鏈湡搴斾粯", prop: "currentPayable", slot: "currentPayable" },
- { label: "鏈湡浠樻", prop: "currentPayment", slot: "currentPayment" },
- { label: "鏈熸湯浣欓", prop: "endBalance", slot: "endBalance" },
- { label: "鎿嶄綔", prop: "operation", slot: "operation", width: "150", fixed: "right" },
+ { label: "瀵硅处鏈熼棿", prop: "statementMonth", width: "150" },
+ { label: "鏈熷垵浣欓", prop: "openingBalance", dataType: "slot", slot: "openingBalance" },
+ { label: "鏈湡搴斾粯", prop: "currentPlan", dataType: "slot", slot: "currentPlan" },
+ { label: "鏈湡浠樻", prop: "currentActually", dataType: "slot", slot: "currentActually" },
+ { label: "鏈熸湯浣欓", prop: "closingBalance", dataType: "slot", slot: "closingBalance" },
+ { label: "鎿嶄綔", prop: "operation", dataType: "slot", slot: "operation", width: "200", fixed: "right" },
];
const dataList = ref([]);
+const tableLoading = ref(false);
+const submitLoading = ref(false);
const detailDialogVisible = ref(false);
const currentSupplier = ref("");
const currentPeriod = ref("");
const detailData = ref([]);
+const detailLoading = ref(false);
const generateDialogVisible = ref(false);
const purchaseLoading = ref(false);
+const statementDetailLoaded = ref(false);
const purchaseData = ref([]);
const selectedPurchases = ref([]);
+const purchaseTableRef = ref(null);
+const supplierList = ref([]);
+
+/** 鏄庣粏 type锛�1鍑哄簱 2鍏ュ簱 3鏀舵 4浠樻 5閫�璐� */
+const STATEMENT_DETAIL_TYPE_MAP = {
+ 1: "鍑哄簱",
+ 2: "鍏ュ簱",
+ 3: "鏀舵",
+ 4: "浠樻",
+ 5: "閫�璐�",
+};
+
+const calculateEndBalance = (openingBalance, currentPlan, currentActually) => {
+ return openingBalance + currentPlan - currentActually;
+};
+
+const getDetailTypeLabel = (type) => STATEMENT_DETAIL_TYPE_MAP[Number(type)] ?? "";
+
+const getDetailTypeTagType = (type) => {
+ const t = Number(type);
+ if (t === 2) return "success";
+ if (t === 4) return "primary";
+ if (t === 5) return "danger";
+ return "info";
+};
+
+const getDetailAmountClass = (type) => {
+ const t = Number(type);
+ if (t === 2) return "text-danger";
+ if (t === 4) return "text-success";
+ return "text-danger";
+};
const generateForm = reactive({
supplierId: "",
supplierName: "",
- period: "",
- beginBalance: 0,
- currentPayable: 0,
- currentPayment: 0,
+ statementMonth: "",
+ openingBalance: 0,
+ currentPlan: 0,
+ currentActually: 0,
+ closingBalance: 0,
});
-const canGenerate = computed(() => {
- return generateForm.supplierId && generateForm.period && selectedPurchases.value.length > 0;
-});
+const displayClosingBalance = computed(() =>
+ calculateEndBalance(
+ generateForm.openingBalance,
+ generateForm.currentPlan,
+ generateForm.currentActually
+ )
+);
-const supplierList = [
- { id: 1, name: "鍖椾含鍘熸潗鏂欎緵搴斿晢" },
- { id: 2, name: "涓婃捣鐢靛瓙鍏冨櫒浠跺叕鍙�" },
- { id: 3, name: "骞垮窞鍖呰鏉愭枡鍘�" },
- { id: 4, name: "娣卞湷浜旈噾閰嶄欢鍏徃" },
-];
+const canGenerate = computed(
+ () => generateForm.supplierId && generateForm.statementMonth && selectedPurchases.value.length > 0
+);
-const mockData = [
- { id: 1, statementCode: "DZ202401001", supplierId: 1, supplierName: "鍖椾含鍘熸潗鏂欎緵搴斿晢", period: "2024-01", beginBalance: 20000, currentPayable: 15000, currentPayment: 10000, endBalance: 25000 },
- { 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 applyStatementSummary = (data) => {
+ generateForm.openingBalance = Number(data.openingBalance ?? 0);
+ generateForm.currentPlan = Number(data.currentPlan ?? 0);
+ generateForm.currentActually = Number(data.currentActually ?? 0);
+ generateForm.closingBalance = Number(
+ data.closingBalance ??
+ calculateEndBalance(
+ generateForm.openingBalance,
+ generateForm.currentPlan,
+ generateForm.currentActually
+ )
+ );
};
+
+const getSupplierList = () => {
+ getOptions().then((res) => {
+ if (res.code === 200) {
+ supplierList.value = res.data ?? [];
+ }
+ });
+};
+
+const normalizePurchaseRows = (list) => {
+ const rows = Array.isArray(list) ? list : [];
+ return rows.map((item, index) => {
+ const type = Number(item.type);
+ return {
+ id: item.id ?? `detail-${index}`,
+ accountStatementId: item.accountStatementId,
+ occurrenceDate: item.occurrenceDate ?? "",
+ receiptNumber: item.receiptNumber ?? "",
+ type,
+ typeLabel: getDetailTypeLabel(type),
+ amount: Math.abs(Number(item.amount ?? 0)),
+ remark: item.remark ?? "",
+ };
+ });
+};
+
+const selectAllPurchaseRows = (keepApiSummary = false) => {
+ nextTick(() => {
+ const table = purchaseTableRef.value;
+ if (!table) return;
+ table.clearSelection();
+ purchaseData.value.forEach((row) => table.toggleRowSelection(row, true));
+ selectedPurchases.value = [...purchaseData.value];
+ if (!keepApiSummary) {
+ calculateSummary();
+ }
+ });
+};
+
+const isNumericId = (id) => id !== undefined && id !== null && id !== "" && /^\d+$/.test(String(id));
+
+const buildFilterParams = (params = {}) => {
+ const result = { ...params, accountType: ACCOUNT_TYPE_PAYABLE };
+ if (filters.supplierId) {
+ result.customerId = filters.supplierId;
+ }
+ if (filters.startMonth && filters.endMonth && filters.startMonth === filters.endMonth) {
+ result.statementMonth = filters.startMonth;
+ } else if (filters.startMonth) {
+ result.startMonth = filters.startMonth;
+ }
+ if (filters.endMonth && filters.startMonth !== filters.endMonth) {
+ result.endMonth = filters.endMonth;
+ }
+ return result;
+};
+
+const buildListParams = () =>
+ buildFilterParams({
+ current: pagination.currentPage,
+ size: pagination.pageSize,
+ });
+
+const buildExportParams = () => buildFilterParams({});
+
+const buildDetailSubmitItem = (row) => {
+ const item = {
+ occurrenceDate: row.occurrenceDate,
+ receiptNumber: row.receiptNumber,
+ type: row.type,
+ amount: row.amount,
+ remark: row.remark ?? "",
+ };
+ if (isNumericId(row.id)) {
+ item.id = Number(row.id);
+ }
+ if (row.accountStatementId) {
+ item.accountStatementId = row.accountStatementId;
+ }
+ return item;
+};
+
+const buildAddPayload = () => ({
+ customerId: generateForm.supplierId,
+ customerName: generateForm.supplierName,
+ statementMonth: generateForm.statementMonth,
+ accountType: ACCOUNT_TYPE_PAYABLE,
+ statementNumber: "",
+ openingBalance: generateForm.openingBalance,
+ currentPlan: generateForm.currentPlan,
+ currentActually: generateForm.currentActually,
+ closingBalance: generateForm.closingBalance,
+ accountStatementDetails: selectedPurchases.value.map(buildDetailSubmitItem),
+});
const formatMoney = (value) => {
if (value === undefined || value === null) return "0.00";
@@ -229,15 +411,35 @@
};
const getTableData = () => {
- let result = [...mockData];
- if (filters.supplierId) {
- result = result.filter(item => item.supplierId === filters.supplierId);
- }
- if (filters.startMonth && filters.endMonth) {
- result = result.filter(item => item.period >= filters.startMonth && item.period <= filters.endMonth);
- }
- pagination.total = result.length;
- dataList.value = result.slice((pagination.currentPage - 1) * pagination.pageSize, pagination.currentPage * pagination.pageSize);
+ tableLoading.value = true;
+ listPageAccountStatement(buildListParams())
+ .then((res) => {
+ const ok = res.code === 200 || res.code === 0;
+ if (ok && res.data) {
+ pagination.total = res.data.total ?? 0;
+ dataList.value = (res.data.records ?? []).map((row) => ({
+ ...row,
+ supplierName: row.supplierName ?? row.customerName,
+ }));
+ } else {
+ ElMessage.error(res.msg || "鏌ヨ澶辫触");
+ dataList.value = [];
+ pagination.total = 0;
+ }
+ })
+ .catch(() => {
+ dataList.value = [];
+ pagination.total = 0;
+ ElMessage.error("鏌ヨ澶辫触");
+ })
+ .finally(() => {
+ tableLoading.value = false;
+ });
+};
+
+const onSearch = () => {
+ pagination.currentPage = 1;
+ getTableData();
};
const resetFilters = () => {
@@ -248,92 +450,106 @@
getTableData();
};
-const changePage = ({ current, size }) => {
- pagination.currentPage = current;
- pagination.pageSize = size;
+const changePage = ({ page, limit }) => {
+ pagination.currentPage = page;
+ pagination.pageSize = limit;
getTableData();
};
const generateStatement = () => {
generateForm.supplierId = "";
generateForm.supplierName = "";
- generateForm.period = "";
- generateForm.beginBalance = 0;
- generateForm.currentPayable = 0;
- generateForm.currentPayment = 0;
+ generateForm.statementMonth = "";
+ generateForm.openingBalance = 0;
+ generateForm.currentPlan = 0;
+ generateForm.currentActually = 0;
+ generateForm.closingBalance = 0;
+ statementDetailLoaded.value = false;
purchaseData.value = [];
selectedPurchases.value = [];
generateDialogVisible.value = true;
};
const onSupplierChange = (supplierId) => {
- const supplier = supplierList.find(item => item.id === supplierId);
- if (supplier) {
- generateForm.supplierName = supplier.name;
- }
+ const supplier = supplierList.value.find((item) => item.id === supplierId);
+ generateForm.supplierName = supplier?.supplierName ?? "";
loadPurchaseData();
};
-const onPeriodChange = () => {
+const onStatementMonthChange = () => {
loadPurchaseData();
};
const loadPurchaseData = () => {
- if (!generateForm.supplierId || !generateForm.period) {
+ if (!generateForm.supplierId || !generateForm.statementMonth) {
purchaseData.value = [];
+ selectedPurchases.value = [];
+ statementDetailLoaded.value = false;
+ generateForm.openingBalance = 0;
+ generateForm.currentPlan = 0;
+ generateForm.currentActually = 0;
+ generateForm.closingBalance = 0;
return;
}
purchaseLoading.value = true;
+ selectedPurchases.value = [];
+ statementDetailLoaded.value = false;
- 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: "鏀粯璐ф" },
- ];
+ getAccountStatementDetailsByMonth({
+ accountType: ACCOUNT_TYPE_PAYABLE,
+ customerId: generateForm.supplierId,
+ statementMonth: generateForm.statementMonth,
+ })
+ .then((res) => {
+ if (res.code === 200) {
+ const data = res.data ?? {};
+ const details = data.accountStatementDetails;
+ const list = Array.isArray(details) ? details : [];
+ purchaseData.value = normalizePurchaseRows(list);
+ applyStatementSummary(data);
+ statementDetailLoaded.value = true;
- 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")}`;
+ if (purchaseData.value.length > 0) {
+ selectAllPurchaseRows(true);
+ }
+ } else {
+ purchaseData.value = [];
+ statementDetailLoaded.value = false;
+ ElMessage.error(res.msg || "鏌ヨ瀵硅处鏄庣粏澶辫触");
+ }
+ })
+ .catch(() => {
+ purchaseData.value = [];
+ statementDetailLoaded.value = false;
+ ElMessage.error("鏌ヨ瀵硅处鏄庣粏澶辫触");
+ })
+ .finally(() => {
+ purchaseLoading.value = false;
+ });
};
const calculateSummary = () => {
let payable = 0;
let payment = 0;
- selectedPurchases.value.forEach(item => {
- if (item.type === "鍏ュ簱") {
+ selectedPurchases.value.forEach((item) => {
+ if (item.type === 2) {
payable += item.amount;
- } else if (item.type === "閫�璐�") {
+ } else if (item.type === 5) {
payable -= item.amount;
- } else if (item.type === "浠樻") {
+ } else if (item.type === 4) {
payment += item.amount;
}
});
- generateForm.currentPayable = payable;
- generateForm.currentPayment = payment;
+ generateForm.currentPlan = payable;
+ generateForm.currentActually = payment;
+ generateForm.closingBalance = calculateEndBalance(
+ generateForm.openingBalance,
+ generateForm.currentPlan,
+ generateForm.currentActually
+ );
};
const handlePurchaseSelectionChange = (selection) => {
@@ -342,51 +558,127 @@
};
const confirmGenerate = () => {
- const newId = mockData.length > 0 ? Math.max(...mockData.map(item => item.id)) + 1 : 1;
- const endBalance = calculateEndBalance(generateForm.beginBalance, generateForm.currentPayable, generateForm.currentPayment);
+ if (!canGenerate.value) return;
+ submitLoading.value = true;
+ addAccountStatement(buildAddPayload())
+ .then((res) => {
+ if (res.code === 200) {
+ generateDialogVisible.value = false;
+ ElMessage.success("瀵硅处鍗曠敓鎴愭垚鍔�");
+ pagination.currentPage = 1;
+ getTableData();
+ } else {
+ ElMessage.error(res.msg || "鐢熸垚澶辫触");
+ }
+ })
+ .catch(() => {
+ ElMessage.error("鐢熸垚澶辫触");
+ })
+ .finally(() => {
+ submitLoading.value = false;
+ });
+};
- mockData.unshift({
- id: newId,
- statementCode: "DZ" + Date.now(),
- supplierId: generateForm.supplierId,
- supplierName: generateForm.supplierName,
- period: generateForm.period,
- beginBalance: generateForm.beginBalance,
- currentPayable: generateForm.currentPayable,
- currentPayment: generateForm.currentPayment,
- endBalance,
+const handleDelete = (row) => {
+ ElMessageBox.confirm(`纭鍒犻櫎瀵硅处鍗曘��${row.statementNumber || row.id}銆嶅悧锛焋, "鎻愮ず", {
+ confirmButtonText: "纭畾",
+ cancelButtonText: "鍙栨秷",
+ type: "warning",
+ }).then(() => {
+ deleteAccountStatement([row.id])
+ .then((res) => {
+ if (res.code === 200) {
+ ElMessage.success("鍒犻櫎鎴愬姛");
+ getTableData();
+ } else {
+ ElMessage.error(res.msg || "鍒犻櫎澶辫触");
+ }
+ })
+ .catch(() => {
+ ElMessage.error("鍒犻櫎澶辫触");
+ });
+ });
+};
+
+const buildDetailTableFromApi = (data, statementMonth) => {
+ const details = Array.isArray(data.accountStatementDetails) ? data.accountStatementDetails : [];
+ let runningBalance = Number(data.openingBalance ?? 0);
+ const rows = [
+ {
+ date: statementMonth ?? "",
+ type: "鏈熷垵",
+ code: "-",
+ debit: 0,
+ credit: 0,
+ balance: runningBalance,
+ remark: "鏈熷垵浣欓",
+ },
+ ];
+
+ details.forEach((item) => {
+ const amount = Math.abs(Number(item.amount ?? 0));
+ const type = Number(item.type);
+ let debit = 0;
+ let credit = 0;
+
+ if (type === 2) {
+ credit = amount;
+ runningBalance += amount;
+ } else if (type === 4) {
+ debit = amount;
+ runningBalance -= amount;
+ } else if (type === 5) {
+ credit = -amount;
+ runningBalance -= amount;
+ }
+
+ rows.push({
+ date: item.occurrenceDate ?? "",
+ type: getDetailTypeLabel(type),
+ code: item.receiptNumber ?? "",
+ debit,
+ credit,
+ balance: runningBalance,
+ remark: item.remark ?? "",
+ });
});
- generateDialogVisible.value = false;
- ElMessage.success("瀵硅处鍗曠敓鎴愭垚鍔�");
- getTableData();
+ return rows;
};
const viewDetail = (row) => {
- currentSupplier.value = row.supplierName;
- currentPeriod.value = row.period;
+ const partnerId = row.customerId ?? row.supplierId;
+ if (!partnerId || !row.statementMonth) {
+ ElMessage.warning("缂哄皯渚涘簲鍟嗘垨瀵硅处鏈堜唤锛屾棤娉曟煡璇㈡槑缁�");
+ return;
+ }
- 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: 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: "鏀粯璐ф" },
- ];
-
+ currentSupplier.value = row.supplierName ?? row.customerName ?? "";
+ currentPeriod.value = row.statementMonth ?? "";
+ detailData.value = [];
detailDialogVisible.value = true;
-};
+ detailLoading.value = true;
-const printStatement = (row) => {
- ElMessage.info(`鎵撳嵃瀵硅处鍗�: ${row.statementCode}`);
+ getAccountStatementDetailsByMonth({
+ accountType: ACCOUNT_TYPE_PAYABLE,
+ customerId: partnerId,
+ statementMonth: row.statementMonth,
+ })
+ .then((res) => {
+ if (res.code === 200) {
+ detailData.value = buildDetailTableFromApi(res.data ?? {}, row.statementMonth);
+ } else {
+ ElMessage.error(res.msg || "鏌ヨ鏄庣粏澶辫触");
+ detailDialogVisible.value = false;
+ }
+ })
+ .catch(() => {
+ ElMessage.error("鏌ヨ鏄庣粏澶辫触");
+ detailDialogVisible.value = false;
+ })
+ .finally(() => {
+ detailLoading.value = false;
+ });
};
const printDetail = () => {
@@ -394,10 +686,15 @@
};
const handleOut = () => {
- ElMessage.success("瀵煎嚭鎴愬姛");
+ proxy.download(
+ "/accountStatement/exportAccountStatement",
+ buildExportParams(),
+ `搴斾粯瀵硅处鍗昣${Date.now()}.xlsx`
+ );
};
onMounted(() => {
+ getSupplierList();
getTableData();
});
</script>
@@ -415,6 +712,10 @@
.text-danger {
color: #f56c6c;
+}
+
+.text-primary {
+ color: #409eff;
}
.statement-header {
@@ -461,9 +762,5 @@
.empty-tip {
margin-top: 30px;
-}
-
-.text-primary {
- color: #409eff;
}
</style>
--
Gitblit v1.9.3