增加财务模块
This commit is contained in:
+96
-11
@@ -1473,6 +1473,10 @@ const InventoryView = {
|
||||
const state = reactive({
|
||||
activeTab: 'dashboard',
|
||||
dashboard: null,
|
||||
financeSummary: null,
|
||||
financeTransactions: [],
|
||||
receivables: [],
|
||||
payables: [],
|
||||
products: [],
|
||||
suppliers: [],
|
||||
customers: [],
|
||||
@@ -1552,6 +1556,26 @@ const InventoryView = {
|
||||
}
|
||||
};
|
||||
|
||||
const loadFinance = async () => {
|
||||
state.loading = true;
|
||||
try {
|
||||
const [summary, transactions, receivables, payables] = await Promise.all([
|
||||
apiRequest('/api/finance/summary'),
|
||||
apiRequest('/api/finance/transactions?status=confirmed&limit=20'),
|
||||
apiRequest('/api/finance/receivables?limit=20'),
|
||||
apiRequest('/api/finance/payables?limit=20')
|
||||
]);
|
||||
state.financeSummary = summary;
|
||||
state.financeTransactions = transactions;
|
||||
state.receivables = receivables;
|
||||
state.payables = payables;
|
||||
} catch (e) {
|
||||
handleApiError(e, '加载财务数据');
|
||||
} finally {
|
||||
state.loading = false;
|
||||
}
|
||||
};
|
||||
|
||||
const switchTab = (tab) => {
|
||||
state.activeTab = tab;
|
||||
switch (tab) {
|
||||
@@ -1561,6 +1585,7 @@ const InventoryView = {
|
||||
case 'customers': loadCustomers(); break;
|
||||
case 'inventory': loadInventory(); break;
|
||||
case 'movements': loadMovements(); break;
|
||||
case 'finance': loadFinance(); break;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1589,13 +1614,13 @@ const InventoryView = {
|
||||
method: 'PUT',
|
||||
body: JSON.stringify(state.form)
|
||||
});
|
||||
showNotification('产品更新成功', 'success');
|
||||
addNotification('产品更新成功', 'success');
|
||||
} else {
|
||||
await apiRequest('/api/products', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(state.form)
|
||||
});
|
||||
showNotification('产品创建成功', 'success');
|
||||
addNotification('产品创建成功', 'success');
|
||||
}
|
||||
closeModal();
|
||||
loadProducts();
|
||||
@@ -1608,7 +1633,7 @@ const InventoryView = {
|
||||
if (!confirm('确定要删除这个产品吗?')) return;
|
||||
try {
|
||||
await apiRequest(`/api/products/${id}`, { method: 'DELETE' });
|
||||
showNotification('产品已删除', 'success');
|
||||
addNotification('产品已删除', 'success');
|
||||
loadProducts();
|
||||
} catch (e) {
|
||||
handleApiError(e, '删除产品');
|
||||
@@ -1622,13 +1647,13 @@ const InventoryView = {
|
||||
method: 'PUT',
|
||||
body: JSON.stringify(state.form)
|
||||
});
|
||||
showNotification('供应商更新成功', 'success');
|
||||
addNotification('供应商更新成功', 'success');
|
||||
} else {
|
||||
await apiRequest('/api/suppliers', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(state.form)
|
||||
});
|
||||
showNotification('供应商创建成功', 'success');
|
||||
addNotification('供应商创建成功', 'success');
|
||||
}
|
||||
closeModal();
|
||||
loadSuppliers();
|
||||
@@ -1641,7 +1666,7 @@ const InventoryView = {
|
||||
if (!confirm('确定要删除这个供应商吗?')) return;
|
||||
try {
|
||||
await apiRequest(`/api/suppliers/${id}`, { method: 'DELETE' });
|
||||
showNotification('供应商已删除', 'success');
|
||||
addNotification('供应商已删除', 'success');
|
||||
loadSuppliers();
|
||||
} catch (e) {
|
||||
handleApiError(e, '删除供应商');
|
||||
@@ -1655,13 +1680,13 @@ const InventoryView = {
|
||||
method: 'PUT',
|
||||
body: JSON.stringify(state.form)
|
||||
});
|
||||
showNotification('客户更新成功', 'success');
|
||||
addNotification('客户更新成功', 'success');
|
||||
} else {
|
||||
await apiRequest('/api/customers', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(state.form)
|
||||
});
|
||||
showNotification('客户创建成功', 'success');
|
||||
addNotification('客户创建成功', 'success');
|
||||
}
|
||||
closeModal();
|
||||
loadCustomers();
|
||||
@@ -1674,7 +1699,7 @@ const InventoryView = {
|
||||
if (!confirm('确定要删除这个客户吗?')) return;
|
||||
try {
|
||||
await apiRequest(`/api/customers/${id}`, { method: 'DELETE' });
|
||||
showNotification('客户已删除', 'success');
|
||||
addNotification('客户已删除', 'success');
|
||||
loadCustomers();
|
||||
} catch (e) {
|
||||
handleApiError(e, '删除客户');
|
||||
@@ -1687,7 +1712,7 @@ const InventoryView = {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({ ...state.form, movement_type: 'in' })
|
||||
});
|
||||
showNotification('入库成功', 'success');
|
||||
addNotification('入库成功', 'success');
|
||||
closeModal();
|
||||
loadInventory();
|
||||
loadMovements();
|
||||
@@ -1702,7 +1727,7 @@ const InventoryView = {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({ ...state.form, movement_type: 'out' })
|
||||
});
|
||||
showNotification('出库成功', 'success');
|
||||
addNotification('出库成功', 'success');
|
||||
closeModal();
|
||||
loadInventory();
|
||||
loadMovements();
|
||||
@@ -1751,6 +1776,7 @@ const InventoryView = {
|
||||
<button :class="['tab', { active: state.activeTab === 'suppliers' }]" @click="switchTab('suppliers')">供应商</button>
|
||||
<button :class="['tab', { active: state.activeTab === 'customers' }]" @click="switchTab('customers')">客户</button>
|
||||
<button :class="['tab', { active: state.activeTab === 'movements' }]" @click="switchTab('movements')">变动记录</button>
|
||||
<button :class="['tab', { active: state.activeTab === 'finance' }]" @click="switchTab('finance')">财务</button>
|
||||
</div>
|
||||
|
||||
<div v-if="state.loading" class="loading-state">
|
||||
@@ -1940,6 +1966,65 @@ const InventoryView = {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-else-if="state.activeTab === 'finance'">
|
||||
<div class="dashboard-grid">
|
||||
<div class="stat-card">
|
||||
<div class="stat-icon">🧾</div>
|
||||
<div class="stat-content">
|
||||
<div class="stat-value">{{ formatCurrency(state.financeSummary?.receivable_total || 0) }}</div>
|
||||
<div class="stat-label">应收总额</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="stat-card">
|
||||
<div class="stat-icon">💸</div>
|
||||
<div class="stat-content">
|
||||
<div class="stat-value">{{ formatCurrency(state.financeSummary?.payable_total || 0) }}</div>
|
||||
<div class="stat-label">应付总额</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="stat-card">
|
||||
<div class="stat-icon">💵</div>
|
||||
<div class="stat-content">
|
||||
<div class="stat-value">{{ formatCurrency(state.financeSummary?.monthly_receipt_total || 0) }}</div>
|
||||
<div class="stat-label">本月收款</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="stat-card">
|
||||
<div class="stat-icon">🏦</div>
|
||||
<div class="stat-content">
|
||||
<div class="stat-value">{{ formatCurrency(state.financeSummary?.monthly_payment_total || 0) }}</div>
|
||||
<div class="stat-label">本月付款</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="table-container" style="margin-top: 16px;">
|
||||
<h3 style="margin-bottom: 12px;">最近财务流水</h3>
|
||||
<table class="data-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>单号</th>
|
||||
<th>类型</th>
|
||||
<th>往来方</th>
|
||||
<th>金额</th>
|
||||
<th>状态</th>
|
||||
<th>日期</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr v-for="txn in state.financeTransactions" :key="txn.id">
|
||||
<td>{{ txn.txn_no }}</td>
|
||||
<td>{{ txn.txn_type === 'receipt' ? '收款' : '付款' }}</td>
|
||||
<td>{{ txn.partner_type === 'customer' ? '客户' : '供应商' }}#{{ txn.partner_id }}</td>
|
||||
<td>{{ formatCurrency(txn.amount) }}</td>
|
||||
<td>{{ txn.status === 'confirmed' ? '已确认' : '已作废' }}</td>
|
||||
<td>{{ formatDateTime(txn.txn_date) }}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-else-if="state.activeTab === 'movements'" class="table-container">
|
||||
<table class="data-table">
|
||||
<thead>
|
||||
|
||||
Reference in New Issue
Block a user