feat: AI 图片记账、自定义交易渠道与淘宝/京东账单导入

- AI 图片记账:多图上传由视觉模型识别,SSE 实时推送进度,提取 rawData,按「类型+金额+时间」检测重复,支持缩略图与来源图片查看
- 自定义交易渠道:新增 t_channel 与渠道管理页,支持新建/改名/删除,并接入统计、导出与 AI 查询/记账/建议提示词
- AI 建议:单条建议新增交易渠道推荐(推荐已有渠道 / AI 新建渠道)
- 账单导入:新增淘宝(xlsx)、京东(CSV)解析器
- 交易:新增批量创建接口,导入时按去重键兜底跳过重复
- 运行目录统一经 AppHome 解析,图片与数据文件落盘规范化
- 前端:AI 记账方式偏好记忆、AI 按钮与输入框对齐、来源图片弹窗支持加载原图
This commit is contained in:
2026-09-21 16:21:58 +08:00
parent 96130d269e
commit 2ade60da42
73 changed files with 5024 additions and 354 deletions
+41
View File
@@ -76,6 +76,7 @@ CREATE TABLE IF NOT EXISTS t_ai_config (
api_key VARCHAR(255) COMMENT 'DeepSeek API Key(明文存储)',
base_url VARCHAR(255) NOT NULL DEFAULT 'https://api.deepseek.com' COMMENT 'API 基础地址',
model VARCHAR(50) NOT NULL DEFAULT 'deepseek-chat' COMMENT '使用的模型名称',
vision_model VARCHAR(50) NOT NULL DEFAULT 'deepseek-flash' COMMENT '图片记账使用的视觉模型名称',
UNIQUE INDEX uk_user_id (user_id) COMMENT '用户ID唯一索引,每个用户一条配置'
);
@@ -97,6 +98,32 @@ CREATE TABLE IF NOT EXISTS t_ai_usage (
INDEX idx_user_created (user_id, created_at) COMMENT '用户ID+创建时间联合索引'
);
-- AI 记账图片表:保存用户上传的账单/支付截图及其解析结果摘要
CREATE TABLE IF NOT EXISTS t_ai_image (
id BIGINT AUTO_INCREMENT PRIMARY KEY COMMENT '图片ID,主键自增',
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
user_id BIGINT NOT NULL COMMENT '所属用户ID',
file_path VARCHAR(500) NOT NULL COMMENT '图片本地存储相对路径',
mime_type VARCHAR(50) COMMENT '图片 MIME 类型,如 image/jpeg',
file_size BIGINT NOT NULL DEFAULT 0 COMMENT '图片文件大小(字节)',
width INT COMMENT '图片宽度(像素)',
height INT COMMENT '图片高度(像素)',
model VARCHAR(50) COMMENT '解析使用的视觉模型名称',
summary VARCHAR(500) COMMENT '解析结果摘要',
record_count INT NOT NULL DEFAULT 0 COMMENT '解析出的交易记录条数',
INDEX idx_ai_image_user_created (user_id, created_at) COMMENT '用户ID+创建时间联合索引'
);
-- AI 记账图片与交易记录关联表:记录每张图片解析生成的交易记录
CREATE TABLE IF NOT EXISTS t_ai_image_transaction (
id BIGINT AUTO_INCREMENT PRIMARY KEY COMMENT '关联ID,主键自增',
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
image_id BIGINT NOT NULL COMMENT 'AI 记账图片ID',
transaction_id BIGINT NOT NULL COMMENT '交易记录ID',
UNIQUE INDEX uk_ai_image_transaction (image_id, transaction_id) COMMENT '图片+交易唯一索引',
INDEX idx_ai_image_transaction_transaction_id (transaction_id) COMMENT '交易记录ID索引'
);
-- 通知配置表:存储每个用户的账单导入提醒设置
CREATE TABLE IF NOT EXISTS t_notification_config (
id BIGINT AUTO_INCREMENT PRIMARY KEY COMMENT '配置ID,主键自增',
@@ -271,3 +298,17 @@ CREATE TABLE IF NOT EXISTS t_user_preference (
pref_value TEXT COMMENT '偏好值,标量字符串或 JSON',
UNIQUE INDEX uk_user_pref (user_id, pref_key) COMMENT '用户+偏好键唯一索引'
);
-- 用户自定义交易渠道表:仅存放用户自建渠道,内置渠道由枚举维护
CREATE TABLE IF NOT EXISTS t_channel (
id BIGINT AUTO_INCREMENT PRIMARY KEY COMMENT '渠道ID,主键自增',
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
user_id BIGINT NOT NULL COMMENT '所属用户ID',
code VARCHAR(30) NOT NULL COMMENT '渠道编码,后端生成且稳定不变,交易记录按此关联',
name VARCHAR(50) NOT NULL COMMENT '渠道名称,用户可修改',
sort_order INT NOT NULL DEFAULT 0 COMMENT '排序序号,数值越小越靠前',
UNIQUE INDEX uk_channel_user_code (user_id, code) COMMENT '用户+渠道编码唯一索引',
UNIQUE INDEX uk_channel_user_name (user_id, name) COMMENT '用户+渠道名称唯一索引',
INDEX idx_channel_user_id (user_id) COMMENT '用户ID索引'
);
+50 -1
View File
@@ -78,7 +78,8 @@ CREATE TABLE IF NOT EXISTS t_ai_config (
enabled INTEGER NOT NULL DEFAULT 0,
api_key VARCHAR(255),
base_url VARCHAR(255) NOT NULL DEFAULT 'https://api.deepseek.com',
model VARCHAR(50) NOT NULL DEFAULT 'deepseek-chat'
model VARCHAR(50) NOT NULL DEFAULT 'deepseek-chat',
vision_model VARCHAR(50) NOT NULL DEFAULT 'deepseek-flash'
);;
CREATE UNIQUE INDEX IF NOT EXISTS uk_ai_config_user_id ON t_ai_config (user_id);;
@@ -99,6 +100,32 @@ CREATE TABLE IF NOT EXISTS t_ai_usage (
);;
CREATE INDEX IF NOT EXISTS idx_ai_usage_user_created ON t_ai_usage (user_id, created_at);;
-- AI 记账图片表:保存用户上传的账单/支付截图及其解析结果摘要
CREATE TABLE IF NOT EXISTS t_ai_image (
id INTEGER PRIMARY KEY AUTOINCREMENT,
created_at DATETIME NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%S', 'now', 'localtime')),
user_id INTEGER NOT NULL,
file_path VARCHAR(500) NOT NULL,
mime_type VARCHAR(50),
file_size INTEGER NOT NULL DEFAULT 0,
width INTEGER,
height INTEGER,
model VARCHAR(50),
summary VARCHAR(500),
record_count INTEGER NOT NULL DEFAULT 0
);;
CREATE INDEX IF NOT EXISTS idx_ai_image_user_created ON t_ai_image (user_id, created_at);;
-- AI 记账图片与交易记录关联表:记录每张图片解析生成的交易记录
CREATE TABLE IF NOT EXISTS t_ai_image_transaction (
id INTEGER PRIMARY KEY AUTOINCREMENT,
created_at DATETIME NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%S', 'now', 'localtime')),
image_id INTEGER NOT NULL,
transaction_id INTEGER NOT NULL
);;
CREATE UNIQUE INDEX IF NOT EXISTS uk_ai_image_transaction ON t_ai_image_transaction (image_id, transaction_id);;
CREATE INDEX IF NOT EXISTS idx_ai_image_transaction_transaction_id ON t_ai_image_transaction (transaction_id);;
-- 兜底触发器:当应用层未显式更新 updated_at 时,自动刷新为本地时间
CREATE TRIGGER IF NOT EXISTS trg_user_updated_at
AFTER UPDATE ON t_user
@@ -343,3 +370,25 @@ WHEN NEW.updated_at = OLD.updated_at
BEGIN
UPDATE t_user_preference SET updated_at = strftime('%Y-%m-%dT%H:%M:%S', 'now', 'localtime') WHERE id = OLD.id;
END;;
-- 用户自定义交易渠道表:仅存放用户自建渠道,内置渠道由枚举维护
CREATE TABLE IF NOT EXISTS t_channel (
id INTEGER PRIMARY KEY AUTOINCREMENT,
created_at DATETIME NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%S', 'now', 'localtime')),
updated_at DATETIME NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%S', 'now', 'localtime')),
user_id INTEGER NOT NULL,
code VARCHAR(30) NOT NULL,
name VARCHAR(50) NOT NULL,
sort_order INTEGER NOT NULL DEFAULT 0
);;
CREATE UNIQUE INDEX IF NOT EXISTS uk_channel_user_code ON t_channel (user_id, code);;
CREATE UNIQUE INDEX IF NOT EXISTS uk_channel_user_name ON t_channel (user_id, name);;
CREATE INDEX IF NOT EXISTS idx_channel_user_id ON t_channel (user_id);;
CREATE TRIGGER IF NOT EXISTS trg_channel_updated_at
AFTER UPDATE ON t_channel
FOR EACH ROW
WHEN NEW.updated_at = OLD.updated_at
BEGIN
UPDATE t_channel SET updated_at = strftime('%Y-%m-%dT%H:%M:%S', 'now', 'localtime') WHERE id = OLD.id;
END;;