feat: 邮箱账单自动拉取
- 新增邮箱配置、发件人规则、待处理账单三张表(SQLite/MySQL 双脚本)及 CRUD 接口 - 按邮件发件人匹配账单类型,未命中忽略;发件人规则可配置解压密码与默认分类/标签 - 支持 IMAP IDLE 实时监听、定时兜底与手动立即检查;拉取范围可配置(仅新邮件/最近 N 天/最近 N 封) - 附件保存至本地 data/email-bill,解析预览后手动导入,复用账单解析与规则引擎 - 立即检查通过 SSE 实时推送执行进度 - 前端新增「邮箱账单」页(邮箱配置/发件人规则/待处理账单三 Tab),支持子路由与 Tab 偏好记忆,配置弹窗提供常用 IMAP 服务器候选项 - 新用户注册自动初始化默认发件人规则(支付宝/微信/美团/招商银行/交通银行) - 抽取共用账单预览与结果组件,供上传导入与邮箱账单复用 同时包含: - 统计新增口径筛选(仅计入/全部/仅不计入),支付方式改为后端动态获取 - 统一实体 createdAt/updatedAt 位置至 id 之后,调整部分日志级别
This commit is contained in:
@@ -0,0 +1,191 @@
|
||||
// 邮箱账单相关 API:IMAP 配置、发件人规则与待处理账单的解析导入
|
||||
import request from './request'
|
||||
import type { BillType, ParsedBillRow, BillImportItem } from './transaction'
|
||||
|
||||
/** 邮箱配置 */
|
||||
export interface EmailBillConfig {
|
||||
id: number
|
||||
name: string
|
||||
host: string
|
||||
port: number
|
||||
ssl: boolean
|
||||
username: string
|
||||
hasPassword: boolean
|
||||
folder: string
|
||||
enabled: boolean
|
||||
status: string
|
||||
lastError: string | null
|
||||
lastConnectedAt: string | null
|
||||
lastUid: number | null
|
||||
expenseCategoryId: number | null
|
||||
incomeCategoryId: number | null
|
||||
tagIds: number[]
|
||||
fetchScope: string
|
||||
fetchLimit: number | null
|
||||
createdAt: string
|
||||
updatedAt: string
|
||||
}
|
||||
|
||||
/** 发件人识别规则 */
|
||||
export interface EmailBillSenderRule {
|
||||
id: number
|
||||
name: string
|
||||
enabled: boolean
|
||||
sortOrder: number
|
||||
senderPatterns: string[]
|
||||
billType: BillType
|
||||
archivePassword: string | null
|
||||
expenseCategoryId: number | null
|
||||
incomeCategoryId: number | null
|
||||
tagIds: number[]
|
||||
createdAt: string
|
||||
updatedAt: string
|
||||
}
|
||||
|
||||
/** 待处理账单消息 */
|
||||
export interface EmailBillMessage {
|
||||
id: number
|
||||
configId: number
|
||||
uid: number
|
||||
subject: string | null
|
||||
fromAddress: string | null
|
||||
receivedAt: string | null
|
||||
attachmentName: string | null
|
||||
billType: BillType | null
|
||||
status: string
|
||||
error: string | null
|
||||
createdAt: string
|
||||
}
|
||||
|
||||
/** 邮箱配置保存请求 */
|
||||
export interface EmailBillConfigPayload {
|
||||
name: string
|
||||
host: string
|
||||
port: number
|
||||
ssl: boolean
|
||||
username: string
|
||||
password?: string
|
||||
folder: string
|
||||
enabled: boolean
|
||||
expenseCategoryId?: number | null
|
||||
incomeCategoryId?: number | null
|
||||
tagIds?: number[]
|
||||
fetchScope?: string
|
||||
fetchLimit?: number | null
|
||||
}
|
||||
|
||||
/** 发件人规则保存请求 */
|
||||
export interface EmailBillSenderRulePayload {
|
||||
name: string
|
||||
enabled: boolean
|
||||
sortOrder: number
|
||||
senderPatterns: string[]
|
||||
billType: BillType
|
||||
archivePassword?: string | null
|
||||
expenseCategoryId?: number | null
|
||||
incomeCategoryId?: number | null
|
||||
tagIds?: number[]
|
||||
}
|
||||
|
||||
/** 解析结果 */
|
||||
export interface EmailBillParseResult {
|
||||
billType: string
|
||||
total: number
|
||||
rows: ParsedBillRow[]
|
||||
}
|
||||
|
||||
/** 查询邮箱配置列表 */
|
||||
export function listEmailBillConfigs() {
|
||||
return request.get('/email-bill/configs')
|
||||
}
|
||||
|
||||
/** 新增邮箱配置 */
|
||||
export function createEmailBillConfig(data: EmailBillConfigPayload) {
|
||||
return request.post('/email-bill/configs', data)
|
||||
}
|
||||
|
||||
/** 更新邮箱配置,授权码留空表示不修改 */
|
||||
export function updateEmailBillConfig(id: number, data: EmailBillConfigPayload) {
|
||||
return request.put(`/email-bill/configs/${id}`, data)
|
||||
}
|
||||
|
||||
/** 删除邮箱配置 */
|
||||
export function deleteEmailBillConfig(id: number) {
|
||||
return request.delete(`/email-bill/configs/${id}`)
|
||||
}
|
||||
|
||||
/** 启用或停用邮箱配置 */
|
||||
export function toggleEmailBillConfig(id: number, enabled: boolean) {
|
||||
return request.put(`/email-bill/configs/${id}/enabled`, { enabled })
|
||||
}
|
||||
|
||||
/** 测试邮箱连接 */
|
||||
export function testEmailBillConfig(id: number) {
|
||||
return request.post(`/email-bill/configs/${id}/test`, {}, { timeout: 60000 })
|
||||
}
|
||||
|
||||
/** 立即检查邮箱并增量拉取 */
|
||||
export function checkEmailBillConfig(id: number) {
|
||||
return request.post(`/email-bill/configs/${id}/check`, {}, { timeout: 120000 })
|
||||
}
|
||||
|
||||
/** 查询发件人规则列表 */
|
||||
export function listEmailBillSenderRules() {
|
||||
return request.get('/email-bill/sender-rules')
|
||||
}
|
||||
|
||||
/** 新增发件人规则 */
|
||||
export function createEmailBillSenderRule(data: EmailBillSenderRulePayload) {
|
||||
return request.post('/email-bill/sender-rules', data)
|
||||
}
|
||||
|
||||
/** 更新发件人规则 */
|
||||
export function updateEmailBillSenderRule(id: number, data: EmailBillSenderRulePayload) {
|
||||
return request.put(`/email-bill/sender-rules/${id}`, data)
|
||||
}
|
||||
|
||||
/** 删除发件人规则 */
|
||||
export function deleteEmailBillSenderRule(id: number) {
|
||||
return request.delete(`/email-bill/sender-rules/${id}`)
|
||||
}
|
||||
|
||||
/** 启用或停用发件人规则 */
|
||||
export function toggleEmailBillSenderRule(id: number, enabled: boolean) {
|
||||
return request.put(`/email-bill/sender-rules/${id}/enabled`, { enabled })
|
||||
}
|
||||
|
||||
/** 分页查询账单消息 */
|
||||
export function pageEmailBillMessages(params: {
|
||||
status?: string
|
||||
configId?: number
|
||||
page?: number
|
||||
size?: number
|
||||
}) {
|
||||
return request.get('/email-bill/messages', { params })
|
||||
}
|
||||
|
||||
/** 解析账单附件(不落库),可覆盖账单类型与解压密码 */
|
||||
export function parseEmailBillMessage(id: number, data: { billType?: string; password?: string }) {
|
||||
return request.post(`/email-bill/messages/${id}/parse`, data, { timeout: 120000 })
|
||||
}
|
||||
|
||||
/** 确认导入勾选的账单行 */
|
||||
export function importEmailBillMessage(id: number, data: {
|
||||
billType: BillType
|
||||
expenseCategoryId?: number | null
|
||||
incomeCategoryId?: number | null
|
||||
tagIds?: number[]
|
||||
items: BillImportItem[]
|
||||
}) {
|
||||
return request.post(`/email-bill/messages/${id}/import`, data, { timeout: 120000 })
|
||||
}
|
||||
|
||||
/** 忽略账单消息 */
|
||||
export function ignoreEmailBillMessage(id: number) {
|
||||
return request.put(`/email-bill/messages/${id}/ignore`)
|
||||
}
|
||||
|
||||
/** 删除账单消息 */
|
||||
export function deleteEmailBillMessage(id: number) {
|
||||
return request.delete(`/email-bill/messages/${id}`)
|
||||
}
|
||||
@@ -27,6 +27,8 @@ export interface StatisticsFilterParams {
|
||||
minAmount?: number
|
||||
maxAmount?: number
|
||||
remark?: string
|
||||
/** 统计口径:INCLUDED-仅计入(默认)、ALL-全部、EXCLUDED-仅不计入 */
|
||||
statsScope?: 'INCLUDED' | 'ALL' | 'EXCLUDED'
|
||||
}
|
||||
|
||||
/** 获取指定时间范围的统计概览(收支汇总、日均、最大单笔、平均每笔) */
|
||||
|
||||
Reference in New Issue
Block a user