- 新增招商银行「交易流水」PDF 解析(PDFBox 坐标还原,支持多页与折行),CSV/PDF 去重标识统一,支持跨格式去重 - 账单导入改为批量插入,MyBatis 日志改 Slf4j,导入接口超时放宽至 120s - 交易导出 Excel 增加样式、冻结表头与自动筛选,导出前二次确认 - 交易列表展示不计入统计金额,导入预览支持设置「计入统计」
190 lines
5.2 KiB
TypeScript
190 lines
5.2 KiB
TypeScript
// 收支记录相关 API 接口:交易记录的增删改查(分页)
|
|
import request from './request'
|
|
import axios from 'axios'
|
|
import { useUserStore } from '../store/user'
|
|
|
|
/** 获取系统支持的支付方式编码列表(含账单导入来源与人工支付方式) */
|
|
export function getPaymentMethods() {
|
|
return request.get('/transaction/payment-methods')
|
|
}
|
|
|
|
/** 分页获取交易记录列表,支持按类型、分类、支付方式、时间范围、计入统计、金额区间多选筛选 */
|
|
export function getTransactionPage(params: {
|
|
page?: number
|
|
size?: number
|
|
types?: string[]
|
|
categoryIds?: number[]
|
|
uncategorized?: boolean
|
|
paymentMethods?: string[]
|
|
startTime?: string
|
|
endTime?: string
|
|
includeInStats?: boolean
|
|
minAmount?: number
|
|
maxAmount?: number
|
|
remark?: string
|
|
sortField?: string
|
|
sortOrder?: string
|
|
tagIds?: number[]
|
|
}) {
|
|
return request.get('/transaction/page', { params })
|
|
}
|
|
|
|
/** 创建新的交易记录 */
|
|
export function createTransaction(data: {
|
|
categoryId: number
|
|
type: string
|
|
amount: number
|
|
paymentMethod?: string
|
|
remark?: string
|
|
transactionTime: string
|
|
includeInStats?: boolean
|
|
tagIds?: number[]
|
|
}) {
|
|
return request.post('/transaction', data)
|
|
}
|
|
|
|
/** 更新指定交易记录(categoryId 为空表示不设置分类) */
|
|
export function updateTransaction(id: number, data: {
|
|
categoryId: number | null
|
|
type: string
|
|
amount: number
|
|
paymentMethod?: string
|
|
remark?: string
|
|
transactionTime: string
|
|
includeInStats?: boolean
|
|
tagIds?: number[]
|
|
}) {
|
|
return request.put(`/transaction/${id}`, data)
|
|
}
|
|
|
|
/** 删除指定交易记录 */
|
|
export function deleteTransaction(id: number) {
|
|
return request.delete(`/transaction/${id}`)
|
|
}
|
|
|
|
/** 批量删除交易记录,返回实际删除数量 */
|
|
export function batchDeleteTransactions(ids: number[]) {
|
|
return request.delete('/transaction/batch', { data: { ids } })
|
|
}
|
|
|
|
/** 切换指定交易记录的"计入统计"标记 */
|
|
export function toggleTransactionStats(id: number, includeInStats: boolean) {
|
|
return request.put(`/transaction/${id}/stats`, { includeInStats })
|
|
}
|
|
|
|
/** 切换指定交易记录的备注隐藏标记 */
|
|
export function toggleRemarkHidden(id: number, remarkHidden: boolean) {
|
|
return request.put(`/transaction/${id}/remark-hidden`, { remarkHidden })
|
|
}
|
|
|
|
/** 支持的账单类型,当前支持支付宝、微信、美团、招商银行与交通银行 */
|
|
export type BillType = 'ALIPAY' | 'WECHAT' | 'MEITUAN' | 'CMB' | 'BOCOM'
|
|
|
|
/** 账单解析结果行 */
|
|
export interface ParsedBillRow {
|
|
rowNo: number
|
|
externalNo: string
|
|
transactionTime: string
|
|
type: string
|
|
amount: number
|
|
counterparty: string
|
|
product: string
|
|
tradeStatus: string
|
|
direction: string
|
|
includeInStats: boolean
|
|
importable: boolean
|
|
selected: boolean
|
|
duplicate: boolean
|
|
matchedRuleNames: string[] | null
|
|
suggestedCategoryId: number | null
|
|
suggestedCategoryName: string | null
|
|
suggestedCategoryIcon: string | null
|
|
suggestedTags: { id: number; name: string; color?: string }[] | null
|
|
rawData: string | null
|
|
error: string | null
|
|
}
|
|
|
|
/** 待导入账单行 */
|
|
export interface BillImportItem {
|
|
externalNo: string
|
|
transactionTime: string
|
|
type: string
|
|
amount: number
|
|
counterparty: string
|
|
product: string
|
|
includeInStats: boolean
|
|
rawData: string | null
|
|
}
|
|
|
|
/** 解析账单文件(不落库),返回预览数据;支持 zip 压缩包,加密时需传解压密码 */
|
|
export function parseBill(file: File, billType: BillType, password?: string) {
|
|
const formData = new FormData()
|
|
formData.append('file', file)
|
|
formData.append('billType', billType)
|
|
if (password) {
|
|
formData.append('password', password)
|
|
}
|
|
// 大账单解析耗时较长,单独放宽超时
|
|
return request.post('/transaction/import/parse', formData, { timeout: 120000 })
|
|
}
|
|
|
|
/** 确认导入用户勾选的账单行 */
|
|
export function confirmImport(data: {
|
|
billType: BillType
|
|
expenseCategoryId?: number | null
|
|
incomeCategoryId?: number | null
|
|
tagIds?: number[]
|
|
items: BillImportItem[]
|
|
}) {
|
|
// 大批量导入耗时较长,单独放宽超时
|
|
return request.post('/transaction/import/confirm', data, { timeout: 120000 })
|
|
}
|
|
|
|
/** 批量设置交易记录的分类(按类型分别应用支出/收入分类) */
|
|
export function batchUpdateCategory(data: {
|
|
ids: number[]
|
|
expenseCategoryId?: number | null
|
|
incomeCategoryId?: number | null
|
|
includeInStats?: boolean | null
|
|
}) {
|
|
return request.put('/transaction/batch-category', data)
|
|
}
|
|
|
|
/** 批量给交易记录添加/移除标签 */
|
|
export function batchTags(data: {
|
|
ids: number[]
|
|
addTagIds?: number[]
|
|
removeTagIds?: number[]
|
|
}) {
|
|
return request.put('/transaction/batch-tags', data)
|
|
}
|
|
|
|
/** 导出交易记录为 Excel 文件,支持按条件筛选 */
|
|
export function exportTransaction(params: {
|
|
types?: string[]
|
|
categoryIds?: number[]
|
|
uncategorized?: boolean
|
|
paymentMethods?: string[]
|
|
startTime?: string
|
|
endTime?: string
|
|
includeInStats?: boolean
|
|
minAmount?: number
|
|
maxAmount?: number
|
|
remark?: string
|
|
sortField?: string
|
|
sortOrder?: string
|
|
tagIds?: number[]
|
|
}) {
|
|
const userStore = useUserStore()
|
|
return axios.get('/api/transaction/export', {
|
|
params,
|
|
paramsSerializer: {
|
|
indexes: null,
|
|
},
|
|
responseType: 'blob',
|
|
headers: {
|
|
Authorization: `Bearer ${userStore.token}`,
|
|
},
|
|
})
|
|
}
|