feat: 招商银行 PDF 账单导入、跨格式去重与导入性能优化
- 新增招商银行「交易流水」PDF 解析(PDFBox 坐标还原,支持多页与折行),CSV/PDF 去重标识统一,支持跨格式去重 - 账单导入改为批量插入,MyBatis 日志改 Slf4j,导入接口超时放宽至 120s - 交易导出 Excel 增加样式、冻结表头与自动筛选,导出前二次确认 - 交易列表展示不计入统计金额,导入预览支持设置「计入统计」
This commit is contained in:
@@ -76,6 +76,18 @@ const pageSummary = computed(() => {
|
||||
}
|
||||
return { income, expense, balance: income - expense }
|
||||
})
|
||||
// 当前页不计入统计的金额汇总(仅统计 includeInStats=false 的记录)
|
||||
const pageExcludedSummary = computed(() => {
|
||||
let income = 0
|
||||
let expense = 0
|
||||
for (const t of transactions.value) {
|
||||
if (t.includeInStats) continue
|
||||
const amount = Number(t.amount) || 0
|
||||
if (t.type === 'INCOME') income += amount
|
||||
else expense += amount
|
||||
}
|
||||
return { income, expense }
|
||||
})
|
||||
const loading = ref(false) // 列表加载状态
|
||||
const showModal = ref(false) // 新增/编辑弹窗显示状态
|
||||
const showImportModal = ref(false) // 账单导入弹窗显示状态
|
||||
@@ -1555,8 +1567,23 @@ async function handleBatchSubmit() {
|
||||
}
|
||||
}
|
||||
|
||||
/** 导出交易记录为 Excel 文件 */
|
||||
async function handleExport() {
|
||||
/** 导出中状态,防止重复点击 */
|
||||
const exporting = ref(false)
|
||||
|
||||
/** 导出交易记录:弹出二次确认,确认后执行导出 */
|
||||
function handleExport() {
|
||||
dialog.warning({
|
||||
title: t('transaction.exportConfirmTitle'),
|
||||
content: t('transaction.exportConfirm'),
|
||||
positiveText: t('common.confirm'),
|
||||
negativeText: t('common.cancel'),
|
||||
onPositiveClick: () => doExport(),
|
||||
})
|
||||
}
|
||||
|
||||
/** 实际执行导出交易记录为 Excel 文件 */
|
||||
async function doExport() {
|
||||
exporting.value = true
|
||||
try {
|
||||
const res = await exportTransaction({
|
||||
types: filterType.value.length > 0 ? filterType.value : undefined,
|
||||
@@ -1584,6 +1611,8 @@ async function handleExport() {
|
||||
message.success(t('transaction.exportSuccess'))
|
||||
} catch (e: any) {
|
||||
message.error(e.message || t('transaction.exportFailed'))
|
||||
} finally {
|
||||
exporting.value = false
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1614,7 +1643,7 @@ onMounted(() => {
|
||||
{{ t('transaction.batchDelete') }}
|
||||
</NButton>
|
||||
<NButton @click="showImportModal = true">{{ t('transaction.importBill') }}</NButton>
|
||||
<NButton @click="handleExport">{{ t('transaction.exportExcel') }}</NButton>
|
||||
<NButton :loading="exporting" @click="handleExport">{{ t('transaction.exportExcel') }}</NButton>
|
||||
<NButton v-if="aiEnabled" @click="handleAiRecordOpen">
|
||||
<template #icon>
|
||||
<NIcon :component="SparklesOutline" />
|
||||
@@ -1802,6 +1831,9 @@ onMounted(() => {
|
||||
{{ t('transaction.pageExpense') }} <span style="color: #d03050;">{{ pageSummary.expense.toFixed(2) }}</span>
|
||||
· {{ t('transaction.pageIncome') }} <span style="color: #18a058;">{{ pageSummary.income.toFixed(2) }}</span>
|
||||
· {{ t('transaction.pageBalance') }} <span :style="{ color: pageSummary.balance < 0 ? '#d03050' : '#18a058' }">{{ pageSummary.balance.toFixed(2) }}</span>
|
||||
<span style="margin-left: 8px;">
|
||||
{{ t('transaction.pageExcluded', { expense: pageExcludedSummary.expense.toFixed(2), income: pageExcludedSummary.income.toFixed(2) }) }}
|
||||
</span>
|
||||
</span>
|
||||
</NSpace>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user