Files
ledgerly/frontend/src/api/transaction.ts
T
rosercode 2976b85967 feat: 交易渠道重命名、账单来源统计默认值、AI 规则生成与统计搜索,AI 改用 openai-java SDK
- 交易记录「支付方式」全链路重命名为「交易渠道」(channel):DB 列、实体/DTO/VO、接口 /api/transaction/channels、统计维度 CHANNEL、AI 提示词与 JSON 字段、前端与中英日文案;新增 SchemaMigrator 在启动/切换数据源时幂等迁移列名(MySQL 用 information_schema、SQLite 用 PRAGMA)
- 按账单来源设置「计入统计」默认值:AppConfig 持久化 + GET/PUT /api/app/bill-source-include-in-stats,导入解析按「解析器判定 && 来源默认」应用并覆盖上传与邮箱两条路径,设置页新增面板
- AI 生成规则:基于所选已打标签记录归纳分类/标签规则(POST /api/ai/rule/suggest、/api/ai/rule/apply),规则页两步弹窗(选择记录→预览创建),支持候选记录分页/搜索/筛选;按「类型+关键词+分类+标签」签名与已有规则去重,重复项标记「已存在」并禁止导入
- 规则列表新增分页与搜索:GET /api/rule/page(名称/关键词、启用状态、收支类型)
- 统计面板 AI 搜索:POST /api/ai/statistics 将自然语言解析为时间/类型/分类/标签/渠道/金额/统计口径/趋势粒度并回填;交互对齐账单列表 AI 查询(弹窗 + 历史 + 示例 + 空条件守卫);统计后端补充标签筛选,仪表盘新增标签筛选与 AI 搜索
- AI 客户端改用 OpenAI 官方 Java SDK(com.openai:openai-java),自定义 baseUrl 指向 DeepSeek,保留 chat 签名与 DeepSeekResponse
- AI 数据外发收敛:分类/标签建议与规则生成不再发送 rawData 与金额,仅发送类型/备注/渠道/分类/标签;新增 AiCallType.RULE / STATISTICS
- 收支记录页新增「刷新」按钮
2026-09-20 17:13:24 +08:00

187 lines
5.1 KiB
TypeScript

// 收支记录相关 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',
})
}