// 收支记录相关 API 接口:交易记录的增删改查(分页) import request from './request' /** 获取系统支持的交易渠道编码列表(含账单导入来源与人工交易渠道) */ export function getChannels() { return request.get('/transaction/channels') } /** 分页获取交易记录列表,支持按类型、分类、交易渠道、时间范围、计入统计、金额区间多选筛选 */ export function getTransactionPage(params: { page?: number size?: number types?: string[] categoryIds?: number[] uncategorized?: boolean channels?: string[] startTime?: string endTime?: string includeInStats?: boolean minAmount?: number maxAmount?: number remark?: string sortField?: string sortOrder?: string tagIds?: number[] untagged?: boolean tagged?: boolean }) { return request.get('/transaction/page', { params }) } /** 创建新的交易记录 */ export function createTransaction(data: { categoryId: number type: string amount: number channel?: 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 channel?: 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 channels?: string[] startTime?: string endTime?: string includeInStats?: boolean minAmount?: number maxAmount?: number remark?: string sortField?: string sortOrder?: string tagIds?: number[] untagged?: boolean }) { return request.get('/transaction/export', { params, paramsSerializer: { indexes: null, }, responseType: 'blob', }) }