feat: 账单关系(父子/同级)与关系图,AI 生成关系名称备注

- 新增 t_transaction_group、t_transaction_group_item 两张表(MySQL 与 SQLite 双脚本)
- 后端新增关系组实体/枚举/Mapper/DTO/VO/Service/Controller:按账单查询、创建、更新、删除;校验同类型唯一、父子角色与成员归属;删除账单时级联清理(组不足或父子组失去父账单则整组移除);分页填充 relationGroupCount
- 前端收支记录新增「关系」列与详情弹窗(基本信息、标签、账单关系、来源图片、原始数据)
- 新增关系图(自定义 SVG 渲染):圆形节点、按收支红/绿着色、父子/同级连线带箭头与「关联」标签、当前账单高亮,成员较多时自动换行
- 关系编辑弹窗支持新建/编辑/删除、分页选择关联账单、AI 生成名称与备注、关系名称历史下拉(按类型过滤、聚焦即显示)、关系类型偏好记忆(localStorage)
- 支持勾选账单批量建立关系,并新增批量选择模式(默认不显示多选列)
- 新增 AI 关系能力:AiCallType.RELATION、AiRelationService 与提示词模板 ai-relation-system(含借贷场景),接口 POST /api/ai/relation
- 新增 /api/transaction/group/* 接口与关系名称历史接口
- 补充中英日三语文案
This commit is contained in:
2026-09-21 22:23:47 +08:00
parent 06fd80d55f
commit f390246528
35 changed files with 2947 additions and 111 deletions
+15
View File
@@ -91,6 +91,21 @@ export function parseChannelByAi(text: string) {
return request.post('/ai/channel', { text }, { timeout: 60000 })
}
/** AI 生成的账单关系名称与备注建议 */
export interface AiRelationResult {
name: string
remark: string
reason: string
}
/** 根据关系类型与成员账单特征生成关系名称与备注(调用大模型,超时放宽) */
export function parseRelationByAi(data: {
type: string
members: { type: string; channel?: string; categoryName?: string; remark?: string }[]
}) {
return request.post('/ai/relation', data, { timeout: 60000 })
}
/** 根据表单当前内容生成单条分类与标签建议(调用大模型,超时放宽) */
export function suggestOneByAi(data: { type: string; amount?: number | null; channel?: string; remark?: string }) {
return request.post('/ai/suggest-one', data, { timeout: 60000 })
+86
View File
@@ -0,0 +1,86 @@
// 账单关系相关 API 接口:账单之间父子/同级关系的查询与维护
import request from './request'
/** 关系组内角色:PARENT-父账单,CHILD-子账单,MEMBER-成员 */
export type TransactionGroupRole = 'PARENT' | 'CHILD' | 'MEMBER'
/** 关系类型:PARENT_CHILD-父子,SIBLING-同级 */
export type TransactionRelationType = 'PARENT_CHILD' | 'SIBLING'
/** 关系组成员(含关联账单的展示快照) */
export interface TransactionGroupItem {
transactionId: number
role: TransactionGroupRole
sortOrder: number
type: string
amount: number
channel: string
remark: string
remarkHidden: boolean
transactionTime: string
categoryName: string
categoryIcon: string
}
/** 账单关系组 */
export interface TransactionGroup {
id: number
type: TransactionRelationType
name: string
remark: string
createdAt: string
updatedAt: string
items: TransactionGroupItem[]
}
/** 关系组成员提交项 */
export interface TransactionGroupItemPayload {
transactionId: number
role?: TransactionGroupRole
sortOrder?: number
}
/** 关系组成员草稿(前端编辑用,含账单展示快照) */
export interface RelationMemberDraft {
transactionId: number
type: string
amount: number
channel: string
remark: string
transactionTime: string
categoryName: string
categoryIcon: string
}
/** 关系组提交数据 */
export interface TransactionGroupPayload {
type: TransactionRelationType
name?: string
remark?: string
items: TransactionGroupItemPayload[]
}
/** 查询某笔账单所属的全部关系组 */
export function getGroupsByTransaction(transactionId: number) {
return request.get(`/transaction/group/by-transaction/${transactionId}`)
}
/** 查询关系名称历史(可选按关系类型过滤),返回按最近使用排序的名称列表 */
export function getGroupNames(type?: string) {
return request.get('/transaction/group/names', { params: type ? { type } : {} })
}
/** 创建账单关系组,返回新建关系组ID */
export function createTransactionGroup(data: TransactionGroupPayload) {
return request.post('/transaction/group', data)
}
/** 更新账单关系组 */
export function updateTransactionGroup(id: number, data: TransactionGroupPayload) {
return request.put(`/transaction/group/${id}`, data)
}
/** 删除账单关系组(仅解除关联,不删除账单) */
export function deleteTransactionGroup(id: number) {
return request.delete(`/transaction/group/${id}`)
}