refactor: 统一用户上下文、导入顺序与日志规范
- 控制器移除 HttpServletRequest/HttpServletResponse 参数,新增 util/UserContext 统一获取当前用户 ID 与响应对象,导出接口改用 UserContext.getResponse() - 引入 Spotless 统一 Java 导入顺序(java/javax → 第三方库 → cn.rosercode),并全量重排 - 日志统一改用 Lombok @Slf4j,替换手写 LoggerFactory - 补充关键业务日志:登录/注册、交易增删改与批量操作、账单解析导入、DeepSeek 调用耗时与失败、AI 配置与连接测试、通知发送、分类/标签/规则变更 - 全局异常处理补充日志,未捕获异常由 e.printStackTrace() 改为 log.error 记录堆栈 - README 补充功能特性、技术栈与目录结构说明
This commit is contained in:
@@ -1,15 +1,66 @@
|
|||||||
# 收支管理系统
|
# 收支管理系统
|
||||||
|
|
||||||
个人收支管理系统,支持收入/支出记录管理、分类管理、月度统计与图表展示。
|
个人收支管理系统,支持收入/支出记录管理、分类与标签管理、多来源账单导入、自定义归类规则、AI 智能记账、月度统计与图表展示,并提供定时账单导入提醒与系统日志查看。
|
||||||
|
|
||||||
|
## 功能特性
|
||||||
|
|
||||||
|
### 收支记录
|
||||||
|
- 收支记录的增删改查、分页与多条件筛选
|
||||||
|
- 批量设置分类、批量设置标签、批量删除
|
||||||
|
- 单条记录的「计入统计」开关与「备注隐藏」开关
|
||||||
|
- 按当前筛选条件导出 Excel
|
||||||
|
|
||||||
|
### 分类与标签
|
||||||
|
- 分类、标签的增删改查,新注册用户自动获得一套默认数据
|
||||||
|
- 分类图标支持 AI 推荐 Emoji,标签颜色支持 AI 推荐十六进制色值
|
||||||
|
|
||||||
|
### 统计与图表
|
||||||
|
- 月度收支统计、分类占比、收支趋势、分组统计与概览汇总
|
||||||
|
- 基于 ECharts 的可视化图表展示
|
||||||
|
|
||||||
|
### 账单导入
|
||||||
|
- 支持支付宝(CSV)、微信(xlsx)、美团、交通银行、招商银行(PDF)账单解析
|
||||||
|
- 支持 zip 压缩包(含 ZipCrypto / AES 加密压缩包)上传
|
||||||
|
- 「解析预览 → 确认导入」两步流程,按交易号去重
|
||||||
|
|
||||||
|
### 自定义规则
|
||||||
|
- 基于关键词(匹配备注 / 交易对方 / 商品名称)、收支类型、金额区间组合的条件规则
|
||||||
|
- 命中后自动应用分类与标签,支持优先级排序与启用 / 停用
|
||||||
|
- 账单导入预览阶段展示命中的规则与建议分类 / 标签
|
||||||
|
|
||||||
|
### AI 能力(DeepSeek)
|
||||||
|
- 交易记录分类与标签的批量 / 单条智能建议,支持一键采纳
|
||||||
|
- 自然语言查询解析与自然语言记账解析
|
||||||
|
- AI 生成分类、标签,以及 Emoji / 颜色推荐
|
||||||
|
- AI 调用用量统计与明细查看
|
||||||
|
|
||||||
|
### 定时提醒与通知
|
||||||
|
- 按每天 / 每周 / 每月周期提醒导入新账单(默认每月 1 日)
|
||||||
|
- 多渠道推送:邮箱 SMTP(如 QQ 邮箱)、Server 酱(推送到个人微信)
|
||||||
|
- 渠道管理、测试发送与发送日志查看
|
||||||
|
|
||||||
|
### 系统日志
|
||||||
|
- 接口访问日志、登录日志的持久化与分页查询
|
||||||
|
- 后端运行日志在线查看,支持基于 SSE 的实时推送与筛选
|
||||||
|
|
||||||
|
### 账号与多语言
|
||||||
|
- JWT 登录认证,注册功能可开关
|
||||||
|
- 运行时数据库配置与切换(SQLite / MySQL),无需启动前准备
|
||||||
|
- 界面支持中文、英文、日文三种语言
|
||||||
|
|
||||||
## 技术栈
|
## 技术栈
|
||||||
|
|
||||||
| 层级 | 技术 |
|
| 层级 | 技术 |
|
||||||
|---|---|
|
|---|---|
|
||||||
| 后端 | Spring Boot 3.3.6 + Java 21 + MyBatis-Plus + MySQL / SQLite |
|
| 后端 | Spring Boot 3.3.6 + Java 21 + MyBatis-Plus 3.5.12 + MySQL / SQLite |
|
||||||
| 前端 | Vue 3 + TypeScript + Vite + Naive UI + ECharts |
|
| 前端 | Vue 3 + TypeScript + Vite + Naive UI + ECharts + Pinia |
|
||||||
| 构建 | Gradle 8.13 (后端) / npm (前端) |
|
| 构建 | Gradle 8.13 (后端) / npm (前端) |
|
||||||
| 认证 | JWT |
|
| 认证 | JWT |
|
||||||
|
| 对象映射 | MapStruct 1.6.3 |
|
||||||
|
| 账单解析 | EasyExcel 4.0.3 + PDFBox 3.0.3 + Zip4j 2.11.5 |
|
||||||
|
| AI 能力 | DeepSeek |
|
||||||
|
| 通知渠道 | 邮箱 SMTP / Server 酱 |
|
||||||
|
| 多语言 | 中文 / 英文 / 日文 (vue-i18n) |
|
||||||
| API 文档 | Knife4j (OpenAPI 3) |
|
| API 文档 | Knife4j (OpenAPI 3) |
|
||||||
| JDK 版本 | 21.0.12.1 (Temurin LTS) |
|
| JDK 版本 | 21.0.12.1 (Temurin LTS) |
|
||||||
| Node.js 版本 | v24.0.0 |
|
| Node.js 版本 | v24.0.0 |
|
||||||
@@ -78,23 +129,32 @@ java -jar build/libs/finance-app-0.0.1-SNAPSHOT.jar --server.port=18081
|
|||||||
finance-app/
|
finance-app/
|
||||||
├── build.gradle
|
├── build.gradle
|
||||||
├── src/main/java/cn/rosercode/finance/
|
├── src/main/java/cn/rosercode/finance/
|
||||||
│ ├── controller/ # 接口层
|
│ ├── client/ # 外部服务客户端(DeepSeek)
|
||||||
│ ├── service/ # 业务层
|
|
||||||
│ ├── mapper/ # 数据访问层
|
|
||||||
│ ├── entity/ # 实体类
|
|
||||||
│ ├── dto/ # 请求对象
|
|
||||||
│ ├── vo/ # 响应对象
|
|
||||||
│ ├── config/ # 配置类
|
|
||||||
│ ├── common/ # 公共类
|
│ ├── common/ # 公共类
|
||||||
│ ├── interceptor/ # 拦截器
|
│ ├── config/ # 配置类(应用配置、动态数据源)
|
||||||
│ └── util/ # 工具类
|
│ ├── controller/ # 接口层
|
||||||
|
│ ├── converter/ # MapStruct 对象转换器
|
||||||
|
│ ├── dto/ # 请求对象
|
||||||
|
│ ├── entity/ # 实体类
|
||||||
|
│ ├── enums/ # 枚举
|
||||||
|
│ ├── exporter/ # 导出处理
|
||||||
|
│ ├── importer/ # 账单解析器(支付宝/微信/美团/银行)
|
||||||
|
│ ├── interceptor/ # 拦截器(JWT、访问日志)
|
||||||
|
│ ├── mapper/ # 数据访问层
|
||||||
|
│ ├── notification/ # 通知渠道发送器
|
||||||
|
│ ├── scheduler/ # 定时任务
|
||||||
|
│ ├── service/ # 业务层(含 impl)
|
||||||
|
│ ├── util/ # 工具类
|
||||||
|
│ └── vo/ # 响应对象
|
||||||
├── src/main/resources/
|
├── src/main/resources/
|
||||||
│ ├── application.yml
|
│ ├── application.yml
|
||||||
│ ├── mapper/
|
│ ├── logback-spring.xml
|
||||||
│ └── sql/init.sql
|
│ ├── mapper/ # MyBatis XML
|
||||||
|
│ └── sql/ # 建表脚本(init.sql / schema-sqlite.sql 等)
|
||||||
└── frontend/ # Vue 3 前端
|
└── frontend/ # Vue 3 前端
|
||||||
└── src/
|
└── src/
|
||||||
├── api/ # API 请求封装
|
├── api/ # API 请求封装
|
||||||
|
├── locales/ # 多语言文案
|
||||||
├── router/ # 路由配置
|
├── router/ # 路由配置
|
||||||
├── store/ # 状态管理
|
├── store/ # 状态管理
|
||||||
└── views/ # 页面组件
|
└── views/ # 页面组件
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ plugins {
|
|||||||
id 'java'
|
id 'java'
|
||||||
id 'org.springframework.boot' version '3.3.6'
|
id 'org.springframework.boot' version '3.3.6'
|
||||||
id 'io.spring.dependency-management' version '1.1.7'
|
id 'io.spring.dependency-management' version '1.1.7'
|
||||||
|
id 'com.diffplug.spotless' version '8.10.2'
|
||||||
}
|
}
|
||||||
|
|
||||||
group = 'cn.rosercode'
|
group = 'cn.rosercode'
|
||||||
@@ -67,6 +68,16 @@ tasks.named('test') {
|
|||||||
useJUnitPlatform()
|
useJUnitPlatform()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ===== 代码格式规范 =====
|
||||||
|
// 统一 Java 导入顺序:java/javax -> 第三方库 -> 项目包,组间空行分隔
|
||||||
|
spotless {
|
||||||
|
java {
|
||||||
|
target 'src/main/java/**/*.java', 'src/test/java/**/*.java'
|
||||||
|
// '|' 表示同组导入不插入空行;'' 为未显式指定导入的兜底组(即所有第三方库)
|
||||||
|
importOrder('java|javax', '', 'cn.rosercode')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ===== 前端构建与打包 =====
|
// ===== 前端构建与打包 =====
|
||||||
def frontendDir = file("${projectDir}/frontend")
|
def frontendDir = file("${projectDir}/frontend")
|
||||||
def frontendDistDir = file("${frontendDir}/dist")
|
def frontendDistDir = file("${frontendDir}/dist")
|
||||||
|
|||||||
@@ -1 +1,13 @@
|
|||||||
|
pluginManagement {
|
||||||
|
resolutionStrategy {
|
||||||
|
eachPlugin {
|
||||||
|
// Spotless 的插件标记只发布在 Gradle 插件门户,本地 Nexus 未代理;
|
||||||
|
// 这里改为直接按 Maven 坐标解析插件实现(Maven Central 有该构件)
|
||||||
|
if (requested.id.id == 'com.diffplug.spotless') {
|
||||||
|
useModule("com.diffplug.spotless:spotless-plugin-gradle:${requested.version}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
rootProject.name = 'finance-app'
|
rootProject.name = 'finance-app'
|
||||||
|
|||||||
@@ -1,11 +1,5 @@
|
|||||||
package cn.rosercode.finance.client;
|
package cn.rosercode.finance.client;
|
||||||
|
|
||||||
import cn.rosercode.finance.common.BusinessException;
|
|
||||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
|
||||||
import com.fasterxml.jackson.databind.JsonNode;
|
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
|
||||||
import org.springframework.stereotype.Component;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.net.http.HttpClient;
|
import java.net.http.HttpClient;
|
||||||
@@ -17,12 +11,21 @@ import java.util.LinkedHashMap;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||||
|
import com.fasterxml.jackson.databind.JsonNode;
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import cn.rosercode.finance.common.BusinessException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* DeepSeek 客户端,封装 Chat Completions 接口的 HTTP 调用与响应解析。
|
* DeepSeek 客户端,封装 Chat Completions 接口的 HTTP 调用与响应解析。
|
||||||
*
|
*
|
||||||
* @date 2026-09-17 17:52:17
|
* @date 2026-09-17 17:52:17
|
||||||
*/
|
*/
|
||||||
@Component
|
@Component
|
||||||
|
@Slf4j
|
||||||
public class DeepSeekClient {
|
public class DeepSeekClient {
|
||||||
|
|
||||||
/** 单次请求的读取超时时间 */
|
/** 单次请求的读取超时时间 */
|
||||||
@@ -63,6 +66,7 @@ public class DeepSeekClient {
|
|||||||
// 兼容以斜杠结尾的 baseUrl
|
// 兼容以斜杠结尾的 baseUrl
|
||||||
String normalized = baseUrl.endsWith("/") ? baseUrl.substring(0, baseUrl.length() - 1) : baseUrl;
|
String normalized = baseUrl.endsWith("/") ? baseUrl.substring(0, baseUrl.length() - 1) : baseUrl;
|
||||||
String url = normalized + "/chat/completions";
|
String url = normalized + "/chat/completions";
|
||||||
|
long start = System.currentTimeMillis();
|
||||||
|
|
||||||
// 构造请求体,强制返回 JSON 对象
|
// 构造请求体,强制返回 JSON 对象
|
||||||
Map<String, Object> body = new LinkedHashMap<>();
|
Map<String, Object> body = new LinkedHashMap<>();
|
||||||
@@ -79,6 +83,7 @@ public class DeepSeekClient {
|
|||||||
try {
|
try {
|
||||||
requestBody = objectMapper.writeValueAsString(body);
|
requestBody = objectMapper.writeValueAsString(body);
|
||||||
} catch (JsonProcessingException e) {
|
} catch (JsonProcessingException e) {
|
||||||
|
log.error("构建 AI 请求体失败: model={}, error={}", model, e.getMessage());
|
||||||
throw new BusinessException("构建 AI 请求失败: " + e.getMessage());
|
throw new BusinessException("构建 AI 请求失败: " + e.getMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -93,14 +98,18 @@ public class DeepSeekClient {
|
|||||||
try {
|
try {
|
||||||
response = httpClient.send(request, HttpResponse.BodyHandlers.ofString(StandardCharsets.UTF_8));
|
response = httpClient.send(request, HttpResponse.BodyHandlers.ofString(StandardCharsets.UTF_8));
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
|
log.error("调用 DeepSeek 失败: model={}, error={}", model, e.getMessage());
|
||||||
throw new BusinessException("调用 DeepSeek 失败: " + e.getMessage());
|
throw new BusinessException("调用 DeepSeek 失败: " + e.getMessage());
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
// 恢复中断标记,避免吞掉中断信号
|
// 恢复中断标记,避免吞掉中断信号
|
||||||
Thread.currentThread().interrupt();
|
Thread.currentThread().interrupt();
|
||||||
|
log.warn("调用 DeepSeek 被中断: model={}", model);
|
||||||
throw new BusinessException("调用 DeepSeek 被中断");
|
throw new BusinessException("调用 DeepSeek 被中断");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (response.statusCode() != 200) {
|
if (response.statusCode() != 200) {
|
||||||
|
log.warn("DeepSeek 返回异常状态: model={}, status={}, body={}",
|
||||||
|
model, response.statusCode(), truncate(response.body()));
|
||||||
throw new BusinessException("DeepSeek 返回异常(" + response.statusCode() + "): " + truncate(response.body()));
|
throw new BusinessException("DeepSeek 返回异常(" + response.statusCode() + "): " + truncate(response.body()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -119,6 +128,8 @@ public class DeepSeekClient {
|
|||||||
result.setTotalTokens(usage.path("total_tokens").asInt(0));
|
result.setTotalTokens(usage.path("total_tokens").asInt(0));
|
||||||
// DeepSeek 用 prompt_cache_hit_tokens 表示缓存命中的输入 token
|
// DeepSeek 用 prompt_cache_hit_tokens 表示缓存命中的输入 token
|
||||||
result.setCachedTokens(usage.path("prompt_cache_hit_tokens").asInt(0));
|
result.setCachedTokens(usage.path("prompt_cache_hit_tokens").asInt(0));
|
||||||
|
log.info("DeepSeek 调用完成: model={}, 耗时={}ms, tokens={}", model,
|
||||||
|
System.currentTimeMillis() - start, result.getTotalTokens());
|
||||||
return result;
|
return result;
|
||||||
} catch (JsonProcessingException e) {
|
} catch (JsonProcessingException e) {
|
||||||
throw new BusinessException("解析 DeepSeek 响应失败: " + e.getMessage());
|
throw new BusinessException("解析 DeepSeek 响应失败: " + e.getMessage());
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
package cn.rosercode.finance.common;
|
package cn.rosercode.finance.common;
|
||||||
|
|
||||||
import cn.rosercode.finance.config.SpaRouteSupport;
|
import java.io.IOException;
|
||||||
|
|
||||||
import jakarta.servlet.ServletException;
|
import jakarta.servlet.ServletException;
|
||||||
import jakarta.servlet.http.HttpServletRequest;
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
import jakarta.servlet.http.HttpServletResponse;
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.web.bind.MethodArgumentNotValidException;
|
import org.springframework.web.bind.MethodArgumentNotValidException;
|
||||||
import org.springframework.web.bind.annotation.ExceptionHandler;
|
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||||
import org.springframework.web.bind.annotation.RestControllerAdvice;
|
import org.springframework.web.bind.annotation.RestControllerAdvice;
|
||||||
@@ -11,13 +13,14 @@ import org.springframework.web.context.request.async.AsyncRequestNotUsableExcept
|
|||||||
import org.springframework.web.context.request.async.AsyncRequestTimeoutException;
|
import org.springframework.web.context.request.async.AsyncRequestTimeoutException;
|
||||||
import org.springframework.web.servlet.resource.NoResourceFoundException;
|
import org.springframework.web.servlet.resource.NoResourceFoundException;
|
||||||
|
|
||||||
import java.io.IOException;
|
import cn.rosercode.finance.config.SpaRouteSupport;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 全局异常处理器。
|
* 全局异常处理器。
|
||||||
* <p>统一捕获并处理控制器层抛出的各类异常,将其转换为标准化的 JSON 响应返回给前端。</p>
|
* <p>统一捕获并处理控制器层抛出的各类异常,将其转换为标准化的 JSON 响应返回给前端。</p>
|
||||||
*/
|
*/
|
||||||
@RestControllerAdvice
|
@RestControllerAdvice
|
||||||
|
@Slf4j
|
||||||
public class GlobalExceptionHandler {
|
public class GlobalExceptionHandler {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -28,6 +31,7 @@ public class GlobalExceptionHandler {
|
|||||||
*/
|
*/
|
||||||
@ExceptionHandler(BusinessException.class)
|
@ExceptionHandler(BusinessException.class)
|
||||||
public Result<Void> handleBusinessException(BusinessException e) {
|
public Result<Void> handleBusinessException(BusinessException e) {
|
||||||
|
log.warn("业务异常[{}]: {}", e.getCode(), e.getMessage());
|
||||||
return Result.error(e.getCode(), e.getMessage());
|
return Result.error(e.getCode(), e.getMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -53,6 +57,7 @@ public class GlobalExceptionHandler {
|
|||||||
public Result<Void> handleValidationException(MethodArgumentNotValidException e) {
|
public Result<Void> handleValidationException(MethodArgumentNotValidException e) {
|
||||||
// 提取第一个校验错误信息
|
// 提取第一个校验错误信息
|
||||||
String message = e.getBindingResult().getAllErrors().get(0).getDefaultMessage();
|
String message = e.getBindingResult().getAllErrors().get(0).getDefaultMessage();
|
||||||
|
log.warn("参数校验失败: {}", message);
|
||||||
return Result.error(400, message);
|
return Result.error(400, message);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -108,8 +113,8 @@ public class GlobalExceptionHandler {
|
|||||||
if (notConfigured != null) {
|
if (notConfigured != null) {
|
||||||
return Result.error(notConfigured.getCode(), notConfigured.getMessage());
|
return Result.error(notConfigured.getCode(), notConfigured.getMessage());
|
||||||
}
|
}
|
||||||
// 打印异常堆栈信息,便于排查问题
|
// 记录异常堆栈,便于排查问题
|
||||||
e.printStackTrace();
|
log.error("服务器内部错误: {}", e.getMessage(), e);
|
||||||
return Result.error(500, "服务器内部错误: " + e.getMessage());
|
return Result.error(500, "服务器内部错误: " + e.getMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
package cn.rosercode.finance.common;
|
package cn.rosercode.finance.common;
|
||||||
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 分页查询结果封装类。
|
* 分页查询结果封装类。
|
||||||
* <p>用于封装分页查询的返回结果,包含数据列表、总记录数、当前页码和每页大小。</p>
|
* <p>用于封装分页查询的返回结果,包含数据列表、总记录数、当前页码和每页大小。</p>
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
package cn.rosercode.finance.config;
|
package cn.rosercode.finance.config;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.models.Components;
|
||||||
import io.swagger.v3.oas.models.OpenAPI;
|
import io.swagger.v3.oas.models.OpenAPI;
|
||||||
import io.swagger.v3.oas.models.info.Info;
|
import io.swagger.v3.oas.models.info.Info;
|
||||||
import io.swagger.v3.oas.models.Components;
|
|
||||||
import io.swagger.v3.oas.models.security.SecurityRequirement;
|
import io.swagger.v3.oas.models.security.SecurityRequirement;
|
||||||
import io.swagger.v3.oas.models.security.SecurityScheme;
|
import io.swagger.v3.oas.models.security.SecurityScheme;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
|
|||||||
@@ -1,5 +1,9 @@
|
|||||||
package cn.rosercode.finance.config;
|
package cn.rosercode.finance.config;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import jakarta.servlet.RequestDispatcher;
|
import jakarta.servlet.RequestDispatcher;
|
||||||
import jakarta.servlet.ServletException;
|
import jakarta.servlet.ServletException;
|
||||||
@@ -9,10 +13,6 @@ import org.springframework.boot.web.servlet.error.ErrorController;
|
|||||||
import org.springframework.stereotype.Controller;
|
import org.springframework.stereotype.Controller;
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.LinkedHashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 前端单页应用路由回退控制器。
|
* 前端单页应用路由回退控制器。
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -1,12 +1,13 @@
|
|||||||
package cn.rosercode.finance.config;
|
package cn.rosercode.finance.config;
|
||||||
|
|
||||||
import cn.rosercode.finance.interceptor.AccessLogInterceptor;
|
|
||||||
import cn.rosercode.finance.interceptor.JwtInterceptor;
|
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.web.servlet.config.annotation.CorsRegistry;
|
import org.springframework.web.servlet.config.annotation.CorsRegistry;
|
||||||
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
|
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
|
||||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||||
|
|
||||||
|
import cn.rosercode.finance.interceptor.AccessLogInterceptor;
|
||||||
|
import cn.rosercode.finance.interceptor.JwtInterceptor;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Web MVC 配置类。
|
* Web MVC 配置类。
|
||||||
* <p>配置拦截器、跨域策略等 Web 层相关设置。</p>
|
* <p>配置拦截器、跨域策略等 Web 层相关设置。</p>
|
||||||
|
|||||||
@@ -1,15 +1,14 @@
|
|||||||
package cn.rosercode.finance.config.app;
|
package cn.rosercode.finance.config.app;
|
||||||
|
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
import org.springframework.stereotype.Component;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.nio.file.Paths;
|
import java.nio.file.Paths;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 应用级运行时配置的本地文件存储。
|
* 应用级运行时配置的本地文件存储。
|
||||||
*
|
*
|
||||||
@@ -19,10 +18,9 @@ import java.nio.file.Paths;
|
|||||||
* @date 2026-09-18 12:09:22
|
* @date 2026-09-18 12:09:22
|
||||||
*/
|
*/
|
||||||
@Component
|
@Component
|
||||||
|
@Slf4j
|
||||||
public class AppConfigStore {
|
public class AppConfigStore {
|
||||||
|
|
||||||
private static final Logger log = LoggerFactory.getLogger(AppConfigStore.class);
|
|
||||||
|
|
||||||
/** 配置目录 */
|
/** 配置目录 */
|
||||||
private static final String CONFIG_DIR = "config";
|
private static final String CONFIG_DIR = "config";
|
||||||
|
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
package cn.rosercode.finance.config.datasource;
|
package cn.rosercode.finance.config.datasource;
|
||||||
|
|
||||||
import cn.rosercode.finance.service.DatabaseService;
|
|
||||||
import org.springframework.boot.ApplicationArguments;
|
import org.springframework.boot.ApplicationArguments;
|
||||||
import org.springframework.boot.ApplicationRunner;
|
import org.springframework.boot.ApplicationRunner;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import cn.rosercode.finance.service.DatabaseService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 数据库启动引导器。
|
* 数据库启动引导器。
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -1,16 +1,15 @@
|
|||||||
package cn.rosercode.finance.config.datasource;
|
package cn.rosercode.finance.config.datasource;
|
||||||
|
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
import org.springframework.stereotype.Component;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.nio.file.Paths;
|
import java.nio.file.Paths;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 数据库配置的本地文件存储。
|
* 数据库配置的本地文件存储。
|
||||||
*
|
*
|
||||||
@@ -20,10 +19,9 @@ import java.util.Optional;
|
|||||||
* @date 2026-09-18 11:00:14
|
* @date 2026-09-18 11:00:14
|
||||||
*/
|
*/
|
||||||
@Component
|
@Component
|
||||||
|
@Slf4j
|
||||||
public class DatabaseConfigStore {
|
public class DatabaseConfigStore {
|
||||||
|
|
||||||
private static final Logger log = LoggerFactory.getLogger(DatabaseConfigStore.class);
|
|
||||||
|
|
||||||
/** 配置文件相对工作目录的位置 */
|
/** 配置文件相对工作目录的位置 */
|
||||||
private static final String CONFIG_DIR = "config";
|
private static final String CONFIG_DIR = "config";
|
||||||
|
|
||||||
|
|||||||
@@ -1,13 +1,12 @@
|
|||||||
package cn.rosercode.finance.config.datasource;
|
package cn.rosercode.finance.config.datasource;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
|
|
||||||
|
|
||||||
import javax.sql.DataSource;
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
import javax.sql.DataSource;
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 动态数据源,支持在运行时切换底层真实数据源。
|
* 动态数据源,支持在运行时切换底层真实数据源。
|
||||||
@@ -19,10 +18,9 @@ import java.util.concurrent.ConcurrentHashMap;
|
|||||||
*
|
*
|
||||||
* @date 2026-09-18 11:00:28
|
* @date 2026-09-18 11:00:28
|
||||||
*/
|
*/
|
||||||
|
@Slf4j
|
||||||
public class DynamicDataSource extends AbstractRoutingDataSource {
|
public class DynamicDataSource extends AbstractRoutingDataSource {
|
||||||
|
|
||||||
private static final Logger log = LoggerFactory.getLogger(DynamicDataSource.class);
|
|
||||||
|
|
||||||
/** 自行维护的目标数据源映射,用于运行时增量注册与切换 */
|
/** 自行维护的目标数据源映射,用于运行时增量注册与切换 */
|
||||||
private final Map<Object, Object> targetDataSources = new ConcurrentHashMap<>();
|
private final Map<Object, Object> targetDataSources = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
|
|||||||
@@ -1,13 +1,12 @@
|
|||||||
package cn.rosercode.finance.config.datasource;
|
package cn.rosercode.finance.config.datasource;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
import javax.sql.DataSource;
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.core.io.ClassPathResource;
|
import org.springframework.core.io.ClassPathResource;
|
||||||
import org.springframework.jdbc.datasource.init.ResourceDatabasePopulator;
|
import org.springframework.jdbc.datasource.init.ResourceDatabasePopulator;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
import javax.sql.DataSource;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 数据库表结构初始化器。
|
* 数据库表结构初始化器。
|
||||||
*
|
*
|
||||||
@@ -17,10 +16,9 @@ import javax.sql.DataSource;
|
|||||||
* @date 2026-09-18 11:00:46
|
* @date 2026-09-18 11:00:46
|
||||||
*/
|
*/
|
||||||
@Component
|
@Component
|
||||||
|
@Slf4j
|
||||||
public class SchemaInitializer {
|
public class SchemaInitializer {
|
||||||
|
|
||||||
private static final Logger log = LoggerFactory.getLogger(SchemaInitializer.class);
|
|
||||||
|
|
||||||
/** MySQL 建表脚本 */
|
/** MySQL 建表脚本 */
|
||||||
private static final String MYSQL_SCRIPT = "sql/init.sql";
|
private static final String MYSQL_SCRIPT = "sql/init.sql";
|
||||||
|
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
package cn.rosercode.finance.config.datasource;
|
package cn.rosercode.finance.config.datasource;
|
||||||
|
|
||||||
import cn.rosercode.finance.common.DatabaseNotConfiguredException;
|
|
||||||
|
|
||||||
import javax.sql.DataSource;
|
|
||||||
import java.io.PrintWriter;
|
import java.io.PrintWriter;
|
||||||
import java.sql.Connection;
|
import java.sql.Connection;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
import javax.sql.DataSource;
|
||||||
|
|
||||||
|
import cn.rosercode.finance.common.DatabaseNotConfiguredException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 未配置数据库时使用的占位数据源。
|
* 未配置数据库时使用的占位数据源。
|
||||||
|
|||||||
@@ -1,5 +1,18 @@
|
|||||||
package cn.rosercode.finance.controller;
|
package cn.rosercode.finance.controller;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
|
import jakarta.validation.Valid;
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
|
import org.springframework.web.bind.annotation.PutMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestBody;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestParam;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
import cn.rosercode.finance.common.Result;
|
import cn.rosercode.finance.common.Result;
|
||||||
import cn.rosercode.finance.dto.AiApplyRequest;
|
import cn.rosercode.finance.dto.AiApplyRequest;
|
||||||
import cn.rosercode.finance.dto.AiCategoryRequest;
|
import cn.rosercode.finance.dto.AiCategoryRequest;
|
||||||
@@ -18,6 +31,7 @@ import cn.rosercode.finance.service.AiRecordService;
|
|||||||
import cn.rosercode.finance.service.AiSuggestionService;
|
import cn.rosercode.finance.service.AiSuggestionService;
|
||||||
import cn.rosercode.finance.service.AiTagService;
|
import cn.rosercode.finance.service.AiTagService;
|
||||||
import cn.rosercode.finance.service.AiUsageService;
|
import cn.rosercode.finance.service.AiUsageService;
|
||||||
|
import cn.rosercode.finance.util.UserContext;
|
||||||
import cn.rosercode.finance.vo.AiCategoryResultVO;
|
import cn.rosercode.finance.vo.AiCategoryResultVO;
|
||||||
import cn.rosercode.finance.vo.AiConfigVO;
|
import cn.rosercode.finance.vo.AiConfigVO;
|
||||||
import cn.rosercode.finance.vo.AiQueryResultVO;
|
import cn.rosercode.finance.vo.AiQueryResultVO;
|
||||||
@@ -25,19 +39,6 @@ import cn.rosercode.finance.vo.AiRecordResultVO;
|
|||||||
import cn.rosercode.finance.vo.AiSuggestionVO;
|
import cn.rosercode.finance.vo.AiSuggestionVO;
|
||||||
import cn.rosercode.finance.vo.AiTagResultVO;
|
import cn.rosercode.finance.vo.AiTagResultVO;
|
||||||
import cn.rosercode.finance.vo.AiUsageResultVO;
|
import cn.rosercode.finance.vo.AiUsageResultVO;
|
||||||
import io.swagger.v3.oas.annotations.Operation;
|
|
||||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
|
||||||
import jakarta.servlet.http.HttpServletRequest;
|
|
||||||
import jakarta.validation.Valid;
|
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
|
||||||
import org.springframework.web.bind.annotation.PostMapping;
|
|
||||||
import org.springframework.web.bind.annotation.PutMapping;
|
|
||||||
import org.springframework.web.bind.annotation.RequestBody;
|
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
|
||||||
import org.springframework.web.bind.annotation.RequestParam;
|
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* AI 控制器
|
* AI 控制器
|
||||||
@@ -77,27 +78,25 @@ public class AiController {
|
|||||||
/**
|
/**
|
||||||
* 获取当前用户的 AI 配置
|
* 获取当前用户的 AI 配置
|
||||||
*
|
*
|
||||||
* @param request HTTP请求,从中获取用户ID
|
|
||||||
* @return AI 配置(API Key 脱敏)
|
* @return AI 配置(API Key 脱敏)
|
||||||
*/
|
*/
|
||||||
@GetMapping("/config")
|
@GetMapping("/config")
|
||||||
@Operation(summary = "获取 AI 配置", description = "获取当前用户的 AI 智能建议配置,API Key 已脱敏")
|
@Operation(summary = "获取 AI 配置", description = "获取当前用户的 AI 智能建议配置,API Key 已脱敏")
|
||||||
public Result<AiConfigVO> getConfig(HttpServletRequest request) {
|
public Result<AiConfigVO> getConfig() {
|
||||||
Long userId = (Long) request.getAttribute("userId");
|
Long userId = UserContext.getUserId();
|
||||||
return Result.success(aiConfigService.getConfig(userId));
|
return Result.success(aiConfigService.getConfig(userId));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 保存当前用户的 AI 配置
|
* 保存当前用户的 AI 配置
|
||||||
*
|
*
|
||||||
* @param request HTTP请求,从中获取用户ID
|
|
||||||
* @param configRequest 配置保存请求
|
* @param configRequest 配置保存请求
|
||||||
* @return 操作结果
|
* @return 操作结果
|
||||||
*/
|
*/
|
||||||
@PutMapping("/config")
|
@PutMapping("/config")
|
||||||
@Operation(summary = "保存 AI 配置", description = "更新当前用户的 AI 配置,API Key 留空表示不修改")
|
@Operation(summary = "保存 AI 配置", description = "更新当前用户的 AI 配置,API Key 留空表示不修改")
|
||||||
public Result<Void> saveConfig(HttpServletRequest request, @RequestBody AiConfigRequest configRequest) {
|
public Result<Void> saveConfig(@RequestBody AiConfigRequest configRequest) {
|
||||||
Long userId = (Long) request.getAttribute("userId");
|
Long userId = UserContext.getUserId();
|
||||||
aiConfigService.saveConfig(userId, configRequest);
|
aiConfigService.saveConfig(userId, configRequest);
|
||||||
return Result.success();
|
return Result.success();
|
||||||
}
|
}
|
||||||
@@ -105,13 +104,12 @@ public class AiController {
|
|||||||
/**
|
/**
|
||||||
* 测试 DeepSeek 连通性
|
* 测试 DeepSeek 连通性
|
||||||
*
|
*
|
||||||
* @param request HTTP请求,从中获取用户ID
|
|
||||||
* @return 操作结果
|
* @return 操作结果
|
||||||
*/
|
*/
|
||||||
@PostMapping("/config/test")
|
@PostMapping("/config/test")
|
||||||
@Operation(summary = "测试连接", description = "使用当前配置向 DeepSeek 发送一条测试请求")
|
@Operation(summary = "测试连接", description = "使用当前配置向 DeepSeek 发送一条测试请求")
|
||||||
public Result<Void> testConfig(HttpServletRequest request) {
|
public Result<Void> testConfig() {
|
||||||
Long userId = (Long) request.getAttribute("userId");
|
Long userId = UserContext.getUserId();
|
||||||
aiConfigService.testConnection(userId);
|
aiConfigService.testConnection(userId);
|
||||||
return Result.success();
|
return Result.success();
|
||||||
}
|
}
|
||||||
@@ -119,150 +117,130 @@ public class AiController {
|
|||||||
/**
|
/**
|
||||||
* 生成分类与标签建议
|
* 生成分类与标签建议
|
||||||
*
|
*
|
||||||
* @param request HTTP请求,从中获取用户ID
|
|
||||||
* @param suggestRequest 建议请求,携带记录ID列表
|
* @param suggestRequest 建议请求,携带记录ID列表
|
||||||
* @return 逐条建议列表
|
* @return 逐条建议列表
|
||||||
*/
|
*/
|
||||||
@PostMapping("/suggest")
|
@PostMapping("/suggest")
|
||||||
@Operation(summary = "生成 AI 建议", description = "根据交易记录内容生成分类与标签建议")
|
@Operation(summary = "生成 AI 建议", description = "根据交易记录内容生成分类与标签建议")
|
||||||
public Result<List<AiSuggestionVO>> suggest(HttpServletRequest request,
|
public Result<List<AiSuggestionVO>> suggest(@RequestBody @Valid AiSuggestRequest suggestRequest) {
|
||||||
@RequestBody @Valid AiSuggestRequest suggestRequest) {
|
Long userId = UserContext.getUserId();
|
||||||
Long userId = (Long) request.getAttribute("userId");
|
|
||||||
return Result.success(aiSuggestionService.suggest(userId, suggestRequest.getIds(), suggestRequest.getScope()));
|
return Result.success(aiSuggestionService.suggest(userId, suggestRequest.getIds(), suggestRequest.getScope()));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 根据表单当前内容推荐分类与标签
|
* 根据表单当前内容推荐分类与标签
|
||||||
*
|
*
|
||||||
* @param request HTTP请求,从中获取用户ID
|
|
||||||
* @param suggestOneRequest 建议请求,携带表单当前内容
|
* @param suggestOneRequest 建议请求,携带表单当前内容
|
||||||
* @return 单条建议结果
|
* @return 单条建议结果
|
||||||
*/
|
*/
|
||||||
@PostMapping("/suggest-one")
|
@PostMapping("/suggest-one")
|
||||||
@Operation(summary = "单条记录 AI 建议", description = "根据表单当前内容推荐分类与标签,供新增或编辑时参考")
|
@Operation(summary = "单条记录 AI 建议", description = "根据表单当前内容推荐分类与标签,供新增或编辑时参考")
|
||||||
public Result<AiSuggestionVO> suggestOne(HttpServletRequest request,
|
public Result<AiSuggestionVO> suggestOne(@RequestBody @Valid AiSuggestOneRequest suggestOneRequest) {
|
||||||
@RequestBody @Valid AiSuggestOneRequest suggestOneRequest) {
|
Long userId = UserContext.getUserId();
|
||||||
Long userId = (Long) request.getAttribute("userId");
|
|
||||||
return Result.success(aiSuggestionService.suggestOne(userId, suggestOneRequest));
|
return Result.success(aiSuggestionService.suggestOne(userId, suggestOneRequest));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 一键应用 AI 建议
|
* 一键应用 AI 建议
|
||||||
*
|
*
|
||||||
* @param request HTTP请求,从中获取用户ID
|
|
||||||
* @param applyRequest 应用请求,携带逐条建议
|
* @param applyRequest 应用请求,携带逐条建议
|
||||||
* @return 实际发生变更的记录数
|
* @return 实际发生变更的记录数
|
||||||
*/
|
*/
|
||||||
@PostMapping("/apply")
|
@PostMapping("/apply")
|
||||||
@Operation(summary = "应用 AI 建议", description = "覆盖分类并追加标签,一键写入建议")
|
@Operation(summary = "应用 AI 建议", description = "覆盖分类并追加标签,一键写入建议")
|
||||||
public Result<Integer> apply(HttpServletRequest request,
|
public Result<Integer> apply(@RequestBody @Valid AiApplyRequest applyRequest) {
|
||||||
@RequestBody @Valid AiApplyRequest applyRequest) {
|
Long userId = UserContext.getUserId();
|
||||||
Long userId = (Long) request.getAttribute("userId");
|
|
||||||
return Result.success(aiSuggestionService.apply(userId, applyRequest));
|
return Result.success(aiSuggestionService.apply(userId, applyRequest));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取 AI 使用情况
|
* 获取 AI 使用情况
|
||||||
*
|
*
|
||||||
* @param request HTTP请求,从中获取用户ID
|
|
||||||
* @param limit 最近明细条数,默认 20
|
* @param limit 最近明细条数,默认 20
|
||||||
* @return 累计汇总与最近调用明细
|
* @return 累计汇总与最近调用明细
|
||||||
*/
|
*/
|
||||||
@GetMapping("/usage")
|
@GetMapping("/usage")
|
||||||
@Operation(summary = "获取 AI 使用情况", description = "获取当前用户 AI 调用的累计汇总与最近调用明细")
|
@Operation(summary = "获取 AI 使用情况", description = "获取当前用户 AI 调用的累计汇总与最近调用明细")
|
||||||
public Result<AiUsageResultVO> usage(HttpServletRequest request,
|
public Result<AiUsageResultVO> usage(@RequestParam(defaultValue = "20") int limit) {
|
||||||
@RequestParam(defaultValue = "20") int limit) {
|
Long userId = UserContext.getUserId();
|
||||||
Long userId = (Long) request.getAttribute("userId");
|
|
||||||
return Result.success(aiUsageService.getUsage(userId, limit));
|
return Result.success(aiUsageService.getUsage(userId, limit));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 解析自然语言查询为筛选条件
|
* 解析自然语言查询为筛选条件
|
||||||
*
|
*
|
||||||
* @param request HTTP请求,从中获取用户ID
|
|
||||||
* @param queryRequest 查询请求,携带自然语言语句
|
* @param queryRequest 查询请求,携带自然语言语句
|
||||||
* @return 结构化筛选条件
|
* @return 结构化筛选条件
|
||||||
*/
|
*/
|
||||||
@PostMapping("/query")
|
@PostMapping("/query")
|
||||||
@Operation(summary = "自然语言查询解析", description = "将自然语言查询解析为交易筛选条件,供用户确认后应用")
|
@Operation(summary = "自然语言查询解析", description = "将自然语言查询解析为交易筛选条件,供用户确认后应用")
|
||||||
public Result<AiQueryResultVO> query(HttpServletRequest request,
|
public Result<AiQueryResultVO> query(@RequestBody @Valid AiQueryRequest queryRequest) {
|
||||||
@RequestBody @Valid AiQueryRequest queryRequest) {
|
Long userId = UserContext.getUserId();
|
||||||
Long userId = (Long) request.getAttribute("userId");
|
|
||||||
return Result.success(aiQueryService.parse(userId, queryRequest.getQuery()));
|
return Result.success(aiQueryService.parse(userId, queryRequest.getQuery()));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 解析自然语言记账内容为交易记录
|
* 解析自然语言记账内容为交易记录
|
||||||
*
|
*
|
||||||
* @param request HTTP请求,从中获取用户ID
|
|
||||||
* @param recordRequest 记账请求,携带自然语言语句
|
* @param recordRequest 记账请求,携带自然语言语句
|
||||||
* @return 结构化交易记录
|
* @return 结构化交易记录
|
||||||
*/
|
*/
|
||||||
@PostMapping("/record")
|
@PostMapping("/record")
|
||||||
@Operation(summary = "自然语言记账解析", description = "将自然语言记账内容解析为交易记录,供用户确认后保存")
|
@Operation(summary = "自然语言记账解析", description = "将自然语言记账内容解析为交易记录,供用户确认后保存")
|
||||||
public Result<AiRecordResultVO> record(HttpServletRequest request,
|
public Result<AiRecordResultVO> record(@RequestBody @Valid AiRecordRequest recordRequest) {
|
||||||
@RequestBody @Valid AiRecordRequest recordRequest) {
|
Long userId = UserContext.getUserId();
|
||||||
Long userId = (Long) request.getAttribute("userId");
|
|
||||||
return Result.success(aiRecordService.parse(userId, recordRequest.getText()));
|
return Result.success(aiRecordService.parse(userId, recordRequest.getText()));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 根据自然语言描述生成分类
|
* 根据自然语言描述生成分类
|
||||||
*
|
*
|
||||||
* @param request HTTP请求,从中获取用户ID
|
|
||||||
* @param categoryRequest 生成请求,携带分类用途描述
|
* @param categoryRequest 生成请求,携带分类用途描述
|
||||||
* @return 分类建议
|
* @return 分类建议
|
||||||
*/
|
*/
|
||||||
@PostMapping("/category")
|
@PostMapping("/category")
|
||||||
@Operation(summary = "AI 生成分类", description = "根据自然语言描述生成分类名称、类型与图标")
|
@Operation(summary = "AI 生成分类", description = "根据自然语言描述生成分类名称、类型与图标")
|
||||||
public Result<AiCategoryResultVO> generateCategory(HttpServletRequest request,
|
public Result<AiCategoryResultVO> generateCategory(@RequestBody @Valid AiCategoryRequest categoryRequest) {
|
||||||
@RequestBody @Valid AiCategoryRequest categoryRequest) {
|
Long userId = UserContext.getUserId();
|
||||||
Long userId = (Long) request.getAttribute("userId");
|
|
||||||
return Result.success(aiCategoryService.parse(userId, categoryRequest.getText()));
|
return Result.success(aiCategoryService.parse(userId, categoryRequest.getText()));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 根据自然语言描述生成标签
|
* 根据自然语言描述生成标签
|
||||||
*
|
*
|
||||||
* @param request HTTP请求,从中获取用户ID
|
|
||||||
* @param tagRequest 生成请求,携带标签用途描述
|
* @param tagRequest 生成请求,携带标签用途描述
|
||||||
* @return 标签建议
|
* @return 标签建议
|
||||||
*/
|
*/
|
||||||
@PostMapping("/tag")
|
@PostMapping("/tag")
|
||||||
@Operation(summary = "AI 生成标签", description = "根据自然语言描述生成标签名称与颜色")
|
@Operation(summary = "AI 生成标签", description = "根据自然语言描述生成标签名称与颜色")
|
||||||
public Result<AiTagResultVO> generateTag(HttpServletRequest request,
|
public Result<AiTagResultVO> generateTag(@RequestBody @Valid AiTagRequest tagRequest) {
|
||||||
@RequestBody @Valid AiTagRequest tagRequest) {
|
Long userId = UserContext.getUserId();
|
||||||
Long userId = (Long) request.getAttribute("userId");
|
|
||||||
return Result.success(aiTagService.parse(userId, tagRequest.getText()));
|
return Result.success(aiTagService.parse(userId, tagRequest.getText()));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 根据分类名称推荐 Emoji 图标
|
* 根据分类名称推荐 Emoji 图标
|
||||||
*
|
*
|
||||||
* @param request HTTP请求,从中获取用户ID
|
|
||||||
* @param decorateRequest 建议请求,携带分类名称与收支类型
|
* @param decorateRequest 建议请求,携带分类名称与收支类型
|
||||||
* @return 推荐的 Emoji
|
* @return 推荐的 Emoji
|
||||||
*/
|
*/
|
||||||
@PostMapping("/emoji")
|
@PostMapping("/emoji")
|
||||||
@Operation(summary = "AI 推荐分类图标", description = "根据分类名称与收支类型推荐一个 Emoji")
|
@Operation(summary = "AI 推荐分类图标", description = "根据分类名称与收支类型推荐一个 Emoji")
|
||||||
public Result<String> suggestEmoji(HttpServletRequest request,
|
public Result<String> suggestEmoji(@RequestBody @Valid AiDecorateRequest decorateRequest) {
|
||||||
@RequestBody @Valid AiDecorateRequest decorateRequest) {
|
Long userId = UserContext.getUserId();
|
||||||
Long userId = (Long) request.getAttribute("userId");
|
|
||||||
return Result.success(aiDecorationService.suggestEmoji(userId, decorateRequest.getName(), decorateRequest.getType()));
|
return Result.success(aiDecorationService.suggestEmoji(userId, decorateRequest.getName(), decorateRequest.getType()));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 根据标签名称推荐颜色
|
* 根据标签名称推荐颜色
|
||||||
*
|
*
|
||||||
* @param request HTTP请求,从中获取用户ID
|
|
||||||
* @param decorateRequest 建议请求,携带标签名称
|
* @param decorateRequest 建议请求,携带标签名称
|
||||||
* @return 推荐的十六进制颜色
|
* @return 推荐的十六进制颜色
|
||||||
*/
|
*/
|
||||||
@PostMapping("/color")
|
@PostMapping("/color")
|
||||||
@Operation(summary = "AI 推荐标签颜色", description = "根据标签名称推荐一个十六进制颜色")
|
@Operation(summary = "AI 推荐标签颜色", description = "根据标签名称推荐一个十六进制颜色")
|
||||||
public Result<String> suggestColor(HttpServletRequest request,
|
public Result<String> suggestColor(@RequestBody @Valid AiDecorateRequest decorateRequest) {
|
||||||
@RequestBody @Valid AiDecorateRequest decorateRequest) {
|
Long userId = UserContext.getUserId();
|
||||||
Long userId = (Long) request.getAttribute("userId");
|
|
||||||
return Result.success(aiDecorationService.suggestColor(userId, decorateRequest.getName()));
|
return Result.success(aiDecorationService.suggestColor(userId, decorateRequest.getName()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,5 @@
|
|||||||
package cn.rosercode.finance.controller;
|
package cn.rosercode.finance.controller;
|
||||||
|
|
||||||
import cn.rosercode.finance.common.Result;
|
|
||||||
import cn.rosercode.finance.config.app.AppConfig;
|
|
||||||
import cn.rosercode.finance.config.app.AppConfigStore;
|
|
||||||
import cn.rosercode.finance.dto.LogRetentionRequest;
|
|
||||||
import cn.rosercode.finance.dto.NotificationUrlRequest;
|
|
||||||
import io.swagger.v3.oas.annotations.Operation;
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
@@ -13,6 +8,12 @@ import org.springframework.web.bind.annotation.RequestBody;
|
|||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
import cn.rosercode.finance.common.Result;
|
||||||
|
import cn.rosercode.finance.config.app.AppConfig;
|
||||||
|
import cn.rosercode.finance.config.app.AppConfigStore;
|
||||||
|
import cn.rosercode.finance.dto.LogRetentionRequest;
|
||||||
|
import cn.rosercode.finance.dto.NotificationUrlRequest;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 应用配置控制器
|
* 应用配置控制器
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -1,16 +1,10 @@
|
|||||||
package cn.rosercode.finance.controller;
|
package cn.rosercode.finance.controller;
|
||||||
|
|
||||||
import cn.rosercode.finance.common.BusinessException;
|
import java.io.IOException;
|
||||||
import cn.rosercode.finance.common.Result;
|
|
||||||
import cn.rosercode.finance.dto.BillImportRequest;
|
|
||||||
import cn.rosercode.finance.enums.BillType;
|
|
||||||
import cn.rosercode.finance.service.BillImportService;
|
|
||||||
import cn.rosercode.finance.vo.BillImportResultVO;
|
|
||||||
import cn.rosercode.finance.vo.BillParseResultVO;
|
|
||||||
import io.swagger.v3.oas.annotations.Operation;
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
import io.swagger.v3.oas.annotations.Parameter;
|
import io.swagger.v3.oas.annotations.Parameter;
|
||||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
import jakarta.servlet.http.HttpServletRequest;
|
|
||||||
import jakarta.validation.Valid;
|
import jakarta.validation.Valid;
|
||||||
import org.springframework.web.bind.annotation.PostMapping;
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
import org.springframework.web.bind.annotation.RequestBody;
|
import org.springframework.web.bind.annotation.RequestBody;
|
||||||
@@ -19,7 +13,14 @@ import org.springframework.web.bind.annotation.RequestParam;
|
|||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
import org.springframework.web.multipart.MultipartFile;
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
import java.io.IOException;
|
import cn.rosercode.finance.common.BusinessException;
|
||||||
|
import cn.rosercode.finance.common.Result;
|
||||||
|
import cn.rosercode.finance.dto.BillImportRequest;
|
||||||
|
import cn.rosercode.finance.enums.BillType;
|
||||||
|
import cn.rosercode.finance.service.BillImportService;
|
||||||
|
import cn.rosercode.finance.util.UserContext;
|
||||||
|
import cn.rosercode.finance.vo.BillImportResultVO;
|
||||||
|
import cn.rosercode.finance.vo.BillParseResultVO;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 账单导入控制器
|
* 账单导入控制器
|
||||||
@@ -42,7 +43,6 @@ public class BillImportController {
|
|||||||
/**
|
/**
|
||||||
* 解析账单文件(不落库)
|
* 解析账单文件(不落库)
|
||||||
*
|
*
|
||||||
* @param request HTTP请求,从中获取用户ID
|
|
||||||
* @param file 账单文件(支持 csv/xlsx 或 zip 压缩包)
|
* @param file 账单文件(支持 csv/xlsx 或 zip 压缩包)
|
||||||
* @param billType 账单类型,如 ALIPAY
|
* @param billType 账单类型,如 ALIPAY
|
||||||
* @param password 压缩包解压密码,未加密时可不传
|
* @param password 压缩包解压密码,未加密时可不传
|
||||||
@@ -51,11 +51,10 @@ public class BillImportController {
|
|||||||
*/
|
*/
|
||||||
@PostMapping("/parse")
|
@PostMapping("/parse")
|
||||||
@Operation(summary = "解析账单文件", description = "解析账单文件(支持 zip 压缩包)并返回预览数据,不写入数据库")
|
@Operation(summary = "解析账单文件", description = "解析账单文件(支持 zip 压缩包)并返回预览数据,不写入数据库")
|
||||||
public Result<BillParseResultVO> parse(HttpServletRequest request,
|
public Result<BillParseResultVO> parse(@Parameter(description = "账单文件") @RequestParam("file") MultipartFile file,
|
||||||
@Parameter(description = "账单文件") @RequestParam("file") MultipartFile file,
|
|
||||||
@Parameter(description = "账单类型,如 ALIPAY") @RequestParam("billType") String billType,
|
@Parameter(description = "账单类型,如 ALIPAY") @RequestParam("billType") String billType,
|
||||||
@Parameter(description = "压缩包解压密码") @RequestParam(value = "password", required = false) String password) throws IOException {
|
@Parameter(description = "压缩包解压密码") @RequestParam(value = "password", required = false) String password) throws IOException {
|
||||||
Long userId = (Long) request.getAttribute("userId");
|
Long userId = UserContext.getUserId();
|
||||||
if (file == null || file.isEmpty()) {
|
if (file == null || file.isEmpty()) {
|
||||||
throw new BusinessException("请选择账单文件");
|
throw new BusinessException("请选择账单文件");
|
||||||
}
|
}
|
||||||
@@ -65,15 +64,13 @@ public class BillImportController {
|
|||||||
/**
|
/**
|
||||||
* 确认导入用户勾选的账单行
|
* 确认导入用户勾选的账单行
|
||||||
*
|
*
|
||||||
* @param request HTTP请求,从中获取用户ID
|
|
||||||
* @param body 导入请求(默认分类与勾选行)
|
* @param body 导入请求(默认分类与勾选行)
|
||||||
* @return 导入结果统计
|
* @return 导入结果统计
|
||||||
*/
|
*/
|
||||||
@PostMapping("/confirm")
|
@PostMapping("/confirm")
|
||||||
@Operation(summary = "确认导入账单", description = "将用户勾选的账单行写入交易记录,按交易号去重")
|
@Operation(summary = "确认导入账单", description = "将用户勾选的账单行写入交易记录,按交易号去重")
|
||||||
public Result<BillImportResultVO> confirm(HttpServletRequest request,
|
public Result<BillImportResultVO> confirm(@RequestBody @Valid BillImportRequest body) {
|
||||||
@RequestBody @Valid BillImportRequest body) {
|
Long userId = UserContext.getUserId();
|
||||||
Long userId = (Long) request.getAttribute("userId");
|
|
||||||
return Result.success(billImportService.confirm(userId, body));
|
return Result.success(billImportService.confirm(userId, body));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,13 +1,10 @@
|
|||||||
package cn.rosercode.finance.controller;
|
package cn.rosercode.finance.controller;
|
||||||
|
|
||||||
import cn.rosercode.finance.common.Result;
|
import java.util.List;
|
||||||
import cn.rosercode.finance.dto.CategoryRequest;
|
|
||||||
import cn.rosercode.finance.service.CategoryService;
|
|
||||||
import cn.rosercode.finance.vo.CategoryVO;
|
|
||||||
import io.swagger.v3.oas.annotations.Operation;
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
import io.swagger.v3.oas.annotations.Parameter;
|
import io.swagger.v3.oas.annotations.Parameter;
|
||||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
import jakarta.servlet.http.HttpServletRequest;
|
|
||||||
import jakarta.validation.Valid;
|
import jakarta.validation.Valid;
|
||||||
import org.springframework.web.bind.annotation.DeleteMapping;
|
import org.springframework.web.bind.annotation.DeleteMapping;
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
@@ -19,7 +16,11 @@ import org.springframework.web.bind.annotation.RequestMapping;
|
|||||||
import org.springframework.web.bind.annotation.RequestParam;
|
import org.springframework.web.bind.annotation.RequestParam;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
import java.util.List;
|
import cn.rosercode.finance.common.Result;
|
||||||
|
import cn.rosercode.finance.dto.CategoryRequest;
|
||||||
|
import cn.rosercode.finance.service.CategoryService;
|
||||||
|
import cn.rosercode.finance.util.UserContext;
|
||||||
|
import cn.rosercode.finance.vo.CategoryVO;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 分类控制器
|
* 分类控制器
|
||||||
@@ -40,15 +41,13 @@ public class CategoryController {
|
|||||||
/**
|
/**
|
||||||
* 获取分类列表
|
* 获取分类列表
|
||||||
*
|
*
|
||||||
* @param request HTTP请求,从中获取用户ID
|
|
||||||
* @param type 分类类型(可选),用于按类型筛选
|
* @param type 分类类型(可选),用于按类型筛选
|
||||||
* @return 分类列表
|
* @return 分类列表
|
||||||
*/
|
*/
|
||||||
@GetMapping("/list")
|
@GetMapping("/list")
|
||||||
@Operation(summary = "获取分类列表", description = "获取当前用户的全部分类,支持按类型筛选")
|
@Operation(summary = "获取分类列表", description = "获取当前用户的全部分类,支持按类型筛选")
|
||||||
public Result<List<CategoryVO>> list(HttpServletRequest request,
|
public Result<List<CategoryVO>> list(@Parameter(description = "分类类型,可选值:income/expense") @RequestParam(required = false) String type) {
|
||||||
@Parameter(description = "分类类型,可选值:income/expense") @RequestParam(required = false) String type) {
|
Long userId = UserContext.getUserId();
|
||||||
Long userId = (Long) request.getAttribute("userId");
|
|
||||||
if (type != null && !type.isEmpty()) {
|
if (type != null && !type.isEmpty()) {
|
||||||
return Result.success(categoryService.listByType(userId, type));
|
return Result.success(categoryService.listByType(userId, type));
|
||||||
}
|
}
|
||||||
@@ -58,14 +57,13 @@ public class CategoryController {
|
|||||||
/**
|
/**
|
||||||
* 创建分类
|
* 创建分类
|
||||||
*
|
*
|
||||||
* @param request HTTP请求,从中获取用户ID
|
|
||||||
* @param categoryRequest 分类请求参数
|
* @param categoryRequest 分类请求参数
|
||||||
* @return 操作结果
|
* @return 操作结果
|
||||||
*/
|
*/
|
||||||
@PostMapping
|
@PostMapping
|
||||||
@Operation(summary = "创建分类", description = "为当前用户创建新的收支分类")
|
@Operation(summary = "创建分类", description = "为当前用户创建新的收支分类")
|
||||||
public Result<Void> create(HttpServletRequest request, @RequestBody @Valid CategoryRequest categoryRequest) {
|
public Result<Void> create(@RequestBody @Valid CategoryRequest categoryRequest) {
|
||||||
Long userId = (Long) request.getAttribute("userId");
|
Long userId = UserContext.getUserId();
|
||||||
categoryService.create(userId, categoryRequest);
|
categoryService.create(userId, categoryRequest);
|
||||||
return Result.success();
|
return Result.success();
|
||||||
}
|
}
|
||||||
@@ -73,17 +71,15 @@ public class CategoryController {
|
|||||||
/**
|
/**
|
||||||
* 更新分类
|
* 更新分类
|
||||||
*
|
*
|
||||||
* @param request HTTP请求,从中获取用户ID
|
|
||||||
* @param id 分类ID
|
* @param id 分类ID
|
||||||
* @param categoryRequest 分类请求参数
|
* @param categoryRequest 分类请求参数
|
||||||
* @return 操作结果
|
* @return 操作结果
|
||||||
*/
|
*/
|
||||||
@PutMapping("/{id}")
|
@PutMapping("/{id}")
|
||||||
@Operation(summary = "更新分类", description = "根据分类ID更新分类信息")
|
@Operation(summary = "更新分类", description = "根据分类ID更新分类信息")
|
||||||
public Result<Void> update(HttpServletRequest request,
|
public Result<Void> update(@Parameter(description = "分类ID") @PathVariable Long id,
|
||||||
@Parameter(description = "分类ID") @PathVariable Long id,
|
|
||||||
@RequestBody @Valid CategoryRequest categoryRequest) {
|
@RequestBody @Valid CategoryRequest categoryRequest) {
|
||||||
Long userId = (Long) request.getAttribute("userId");
|
Long userId = UserContext.getUserId();
|
||||||
categoryService.update(userId, id, categoryRequest);
|
categoryService.update(userId, id, categoryRequest);
|
||||||
return Result.success();
|
return Result.success();
|
||||||
}
|
}
|
||||||
@@ -91,15 +87,13 @@ public class CategoryController {
|
|||||||
/**
|
/**
|
||||||
* 删除分类
|
* 删除分类
|
||||||
*
|
*
|
||||||
* @param request HTTP请求,从中获取用户ID
|
|
||||||
* @param id 分类ID
|
* @param id 分类ID
|
||||||
* @return 操作结果
|
* @return 操作结果
|
||||||
*/
|
*/
|
||||||
@DeleteMapping("/{id}")
|
@DeleteMapping("/{id}")
|
||||||
@Operation(summary = "删除分类", description = "根据分类ID删除指定分类")
|
@Operation(summary = "删除分类", description = "根据分类ID删除指定分类")
|
||||||
public Result<Void> delete(HttpServletRequest request,
|
public Result<Void> delete(@Parameter(description = "分类ID") @PathVariable Long id) {
|
||||||
@Parameter(description = "分类ID") @PathVariable Long id) {
|
Long userId = UserContext.getUserId();
|
||||||
Long userId = (Long) request.getAttribute("userId");
|
|
||||||
categoryService.delete(userId, id);
|
categoryService.delete(userId, id);
|
||||||
return Result.success();
|
return Result.success();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,15 +1,16 @@
|
|||||||
package cn.rosercode.finance.controller;
|
package cn.rosercode.finance.controller;
|
||||||
|
|
||||||
import cn.rosercode.finance.common.Result;
|
|
||||||
import cn.rosercode.finance.dto.DatabaseConfigRequest;
|
|
||||||
import cn.rosercode.finance.service.DatabaseService;
|
|
||||||
import cn.rosercode.finance.vo.DatabaseStatusVO;
|
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
import org.springframework.web.bind.annotation.PostMapping;
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
import org.springframework.web.bind.annotation.RequestBody;
|
import org.springframework.web.bind.annotation.RequestBody;
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
import cn.rosercode.finance.common.Result;
|
||||||
|
import cn.rosercode.finance.dto.DatabaseConfigRequest;
|
||||||
|
import cn.rosercode.finance.service.DatabaseService;
|
||||||
|
import cn.rosercode.finance.vo.DatabaseStatusVO;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 数据库配置控制器。
|
* 数据库配置控制器。
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -1,5 +1,13 @@
|
|||||||
package cn.rosercode.finance.controller;
|
package cn.rosercode.finance.controller;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestParam;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
|
||||||
|
|
||||||
import cn.rosercode.finance.common.PageResult;
|
import cn.rosercode.finance.common.PageResult;
|
||||||
import cn.rosercode.finance.common.Result;
|
import cn.rosercode.finance.common.Result;
|
||||||
import cn.rosercode.finance.dto.LogQuery;
|
import cn.rosercode.finance.dto.LogQuery;
|
||||||
@@ -8,13 +16,6 @@ import cn.rosercode.finance.service.LogService;
|
|||||||
import cn.rosercode.finance.vo.AppLogVO;
|
import cn.rosercode.finance.vo.AppLogVO;
|
||||||
import cn.rosercode.finance.vo.HttpLogVO;
|
import cn.rosercode.finance.vo.HttpLogVO;
|
||||||
import cn.rosercode.finance.vo.LoginLogVO;
|
import cn.rosercode.finance.vo.LoginLogVO;
|
||||||
import io.swagger.v3.oas.annotations.Operation;
|
|
||||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
|
||||||
import org.springframework.web.bind.annotation.RequestParam;
|
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
|
||||||
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 系统日志控制器
|
* 系统日志控制器
|
||||||
|
|||||||
@@ -1,17 +1,9 @@
|
|||||||
package cn.rosercode.finance.controller;
|
package cn.rosercode.finance.controller;
|
||||||
|
|
||||||
import cn.rosercode.finance.common.Result;
|
import java.util.List;
|
||||||
import cn.rosercode.finance.dto.NotificationChannelRequest;
|
|
||||||
import cn.rosercode.finance.dto.NotificationConfigRequest;
|
|
||||||
import cn.rosercode.finance.service.NotificationChannelService;
|
|
||||||
import cn.rosercode.finance.service.NotificationConfigService;
|
|
||||||
import cn.rosercode.finance.service.NotificationService;
|
|
||||||
import cn.rosercode.finance.vo.NotificationChannelVO;
|
|
||||||
import cn.rosercode.finance.vo.NotificationConfigVO;
|
|
||||||
import cn.rosercode.finance.vo.NotificationLogVO;
|
|
||||||
import io.swagger.v3.oas.annotations.Operation;
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
import jakarta.servlet.http.HttpServletRequest;
|
|
||||||
import org.springframework.web.bind.annotation.DeleteMapping;
|
import org.springframework.web.bind.annotation.DeleteMapping;
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
import org.springframework.web.bind.annotation.PathVariable;
|
import org.springframework.web.bind.annotation.PathVariable;
|
||||||
@@ -22,7 +14,16 @@ import org.springframework.web.bind.annotation.RequestMapping;
|
|||||||
import org.springframework.web.bind.annotation.RequestParam;
|
import org.springframework.web.bind.annotation.RequestParam;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
import java.util.List;
|
import cn.rosercode.finance.common.Result;
|
||||||
|
import cn.rosercode.finance.dto.NotificationChannelRequest;
|
||||||
|
import cn.rosercode.finance.dto.NotificationConfigRequest;
|
||||||
|
import cn.rosercode.finance.service.NotificationChannelService;
|
||||||
|
import cn.rosercode.finance.service.NotificationConfigService;
|
||||||
|
import cn.rosercode.finance.service.NotificationService;
|
||||||
|
import cn.rosercode.finance.util.UserContext;
|
||||||
|
import cn.rosercode.finance.vo.NotificationChannelVO;
|
||||||
|
import cn.rosercode.finance.vo.NotificationConfigVO;
|
||||||
|
import cn.rosercode.finance.vo.NotificationLogVO;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 通知控制器
|
* 通知控制器
|
||||||
@@ -51,28 +52,25 @@ public class NotificationController {
|
|||||||
/**
|
/**
|
||||||
* 获取当前用户的通知配置。
|
* 获取当前用户的通知配置。
|
||||||
*
|
*
|
||||||
* @param request HTTP请求,从中获取用户ID
|
|
||||||
* @return 通知配置
|
* @return 通知配置
|
||||||
*/
|
*/
|
||||||
@GetMapping("/config")
|
@GetMapping("/config")
|
||||||
@Operation(summary = "获取通知配置", description = "获取当前用户的账单导入提醒周期配置")
|
@Operation(summary = "获取通知配置", description = "获取当前用户的账单导入提醒周期配置")
|
||||||
public Result<NotificationConfigVO> getConfig(HttpServletRequest request) {
|
public Result<NotificationConfigVO> getConfig() {
|
||||||
Long userId = (Long) request.getAttribute("userId");
|
Long userId = UserContext.getUserId();
|
||||||
return Result.success(notificationConfigService.getConfig(userId));
|
return Result.success(notificationConfigService.getConfig(userId));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 保存当前用户的通知配置。
|
* 保存当前用户的通知配置。
|
||||||
*
|
*
|
||||||
* @param request HTTP请求,从中获取用户ID
|
|
||||||
* @param configRequest 配置保存请求
|
* @param configRequest 配置保存请求
|
||||||
* @return 操作结果
|
* @return 操作结果
|
||||||
*/
|
*/
|
||||||
@PutMapping("/config")
|
@PutMapping("/config")
|
||||||
@Operation(summary = "保存通知配置", description = "更新当前用户的提醒周期与发送时间")
|
@Operation(summary = "保存通知配置", description = "更新当前用户的提醒周期与发送时间")
|
||||||
public Result<Void> saveConfig(HttpServletRequest request,
|
public Result<Void> saveConfig(@RequestBody NotificationConfigRequest configRequest) {
|
||||||
@RequestBody NotificationConfigRequest configRequest) {
|
Long userId = UserContext.getUserId();
|
||||||
Long userId = (Long) request.getAttribute("userId");
|
|
||||||
notificationConfigService.saveConfig(userId, configRequest);
|
notificationConfigService.saveConfig(userId, configRequest);
|
||||||
return Result.success();
|
return Result.success();
|
||||||
}
|
}
|
||||||
@@ -80,44 +78,40 @@ public class NotificationController {
|
|||||||
/**
|
/**
|
||||||
* 查询当前用户的通知渠道。
|
* 查询当前用户的通知渠道。
|
||||||
*
|
*
|
||||||
* @param request HTTP请求,从中获取用户ID
|
|
||||||
* @return 渠道列表
|
* @return 渠道列表
|
||||||
*/
|
*/
|
||||||
@GetMapping("/channels")
|
@GetMapping("/channels")
|
||||||
@Operation(summary = "查询通知渠道", description = "查询当前用户配置的所有推送渠道")
|
@Operation(summary = "查询通知渠道", description = "查询当前用户配置的所有推送渠道")
|
||||||
public Result<List<NotificationChannelVO>> listChannels(HttpServletRequest request) {
|
public Result<List<NotificationChannelVO>> listChannels() {
|
||||||
Long userId = (Long) request.getAttribute("userId");
|
Long userId = UserContext.getUserId();
|
||||||
return Result.success(notificationChannelService.listChannels(userId));
|
return Result.success(notificationChannelService.listChannels(userId));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 新增通知渠道。
|
* 新增通知渠道。
|
||||||
*
|
*
|
||||||
* @param request HTTP请求,从中获取用户ID
|
|
||||||
* @param channelRequest 渠道保存请求
|
* @param channelRequest 渠道保存请求
|
||||||
* @return 新渠道ID
|
* @return 新渠道ID
|
||||||
*/
|
*/
|
||||||
@PostMapping("/channels")
|
@PostMapping("/channels")
|
||||||
@Operation(summary = "新增通知渠道", description = "新增邮箱或 Server 酱推送渠道")
|
@Operation(summary = "新增通知渠道", description = "新增邮箱或 Server 酱推送渠道")
|
||||||
public Result<Long> createChannel(HttpServletRequest request,
|
public Result<Long> createChannel(@RequestBody NotificationChannelRequest channelRequest) {
|
||||||
@RequestBody NotificationChannelRequest channelRequest) {
|
Long userId = UserContext.getUserId();
|
||||||
Long userId = (Long) request.getAttribute("userId");
|
|
||||||
return Result.success(notificationChannelService.createChannel(userId, channelRequest));
|
return Result.success(notificationChannelService.createChannel(userId, channelRequest));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 修改通知渠道。
|
* 修改通知渠道。
|
||||||
*
|
*
|
||||||
* @param request HTTP请求,从中获取用户ID
|
|
||||||
* @param id 渠道ID
|
* @param id 渠道ID
|
||||||
* @param channelRequest 渠道保存请求
|
* @param channelRequest 渠道保存请求
|
||||||
* @return 操作结果
|
* @return 操作结果
|
||||||
*/
|
*/
|
||||||
@PutMapping("/channels/{id}")
|
@PutMapping("/channels/{id}")
|
||||||
@Operation(summary = "修改通知渠道", description = "更新指定渠道的名称、开关与配置")
|
@Operation(summary = "修改通知渠道", description = "更新指定渠道的名称、开关与配置")
|
||||||
public Result<Void> updateChannel(HttpServletRequest request, @PathVariable Long id,
|
public Result<Void> updateChannel(@PathVariable Long id,
|
||||||
@RequestBody NotificationChannelRequest channelRequest) {
|
@RequestBody NotificationChannelRequest channelRequest) {
|
||||||
Long userId = (Long) request.getAttribute("userId");
|
Long userId = UserContext.getUserId();
|
||||||
notificationChannelService.updateChannel(userId, id, channelRequest);
|
notificationChannelService.updateChannel(userId, id, channelRequest);
|
||||||
return Result.success();
|
return Result.success();
|
||||||
}
|
}
|
||||||
@@ -125,14 +119,13 @@ public class NotificationController {
|
|||||||
/**
|
/**
|
||||||
* 删除通知渠道。
|
* 删除通知渠道。
|
||||||
*
|
*
|
||||||
* @param request HTTP请求,从中获取用户ID
|
|
||||||
* @param id 渠道ID
|
* @param id 渠道ID
|
||||||
* @return 操作结果
|
* @return 操作结果
|
||||||
*/
|
*/
|
||||||
@DeleteMapping("/channels/{id}")
|
@DeleteMapping("/channels/{id}")
|
||||||
@Operation(summary = "删除通知渠道", description = "删除指定的推送渠道")
|
@Operation(summary = "删除通知渠道", description = "删除指定的推送渠道")
|
||||||
public Result<Void> deleteChannel(HttpServletRequest request, @PathVariable Long id) {
|
public Result<Void> deleteChannel(@PathVariable Long id) {
|
||||||
Long userId = (Long) request.getAttribute("userId");
|
Long userId = UserContext.getUserId();
|
||||||
notificationChannelService.deleteChannel(userId, id);
|
notificationChannelService.deleteChannel(userId, id);
|
||||||
return Result.success();
|
return Result.success();
|
||||||
}
|
}
|
||||||
@@ -140,14 +133,13 @@ public class NotificationController {
|
|||||||
/**
|
/**
|
||||||
* 测试指定渠道。
|
* 测试指定渠道。
|
||||||
*
|
*
|
||||||
* @param request HTTP请求,从中获取用户ID
|
|
||||||
* @param id 渠道ID
|
* @param id 渠道ID
|
||||||
* @return 操作结果
|
* @return 操作结果
|
||||||
*/
|
*/
|
||||||
@PostMapping("/channels/{id}/test")
|
@PostMapping("/channels/{id}/test")
|
||||||
@Operation(summary = "测试通知渠道", description = "向指定渠道发送一条测试消息")
|
@Operation(summary = "测试通知渠道", description = "向指定渠道发送一条测试消息")
|
||||||
public Result<Void> testChannel(HttpServletRequest request, @PathVariable Long id) {
|
public Result<Void> testChannel(@PathVariable Long id) {
|
||||||
Long userId = (Long) request.getAttribute("userId");
|
Long userId = UserContext.getUserId();
|
||||||
notificationService.sendTest(userId, id);
|
notificationService.sendTest(userId, id);
|
||||||
return Result.success();
|
return Result.success();
|
||||||
}
|
}
|
||||||
@@ -155,28 +147,25 @@ public class NotificationController {
|
|||||||
/**
|
/**
|
||||||
* 立即发送账单导入提醒。
|
* 立即发送账单导入提醒。
|
||||||
*
|
*
|
||||||
* @param request HTTP请求,从中获取用户ID
|
|
||||||
* @return 发送成功的渠道数
|
* @return 发送成功的渠道数
|
||||||
*/
|
*/
|
||||||
@PostMapping("/send-now")
|
@PostMapping("/send-now")
|
||||||
@Operation(summary = "立即发送提醒", description = "跳过周期设置,立即向所有已启用渠道发送账单导入提醒")
|
@Operation(summary = "立即发送提醒", description = "跳过周期设置,立即向所有已启用渠道发送账单导入提醒")
|
||||||
public Result<Integer> sendNow(HttpServletRequest request) {
|
public Result<Integer> sendNow() {
|
||||||
Long userId = (Long) request.getAttribute("userId");
|
Long userId = UserContext.getUserId();
|
||||||
return Result.success(notificationService.sendReminderNow(userId));
|
return Result.success(notificationService.sendReminderNow(userId));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 查询最近的发送日志。
|
* 查询最近的发送日志。
|
||||||
*
|
*
|
||||||
* @param request HTTP请求,从中获取用户ID
|
|
||||||
* @param limit 条数上限,默认 20
|
* @param limit 条数上限,默认 20
|
||||||
* @return 日志列表
|
* @return 日志列表
|
||||||
*/
|
*/
|
||||||
@GetMapping("/logs")
|
@GetMapping("/logs")
|
||||||
@Operation(summary = "查询发送日志", description = "查询当前用户最近的提醒发送结果")
|
@Operation(summary = "查询发送日志", description = "查询当前用户最近的提醒发送结果")
|
||||||
public Result<List<NotificationLogVO>> listLogs(HttpServletRequest request,
|
public Result<List<NotificationLogVO>> listLogs(@RequestParam(defaultValue = "20") int limit) {
|
||||||
@RequestParam(defaultValue = "20") int limit) {
|
Long userId = UserContext.getUserId();
|
||||||
Long userId = (Long) request.getAttribute("userId");
|
|
||||||
return Result.success(notificationService.listLogs(userId, limit));
|
return Result.success(notificationService.listLogs(userId, limit));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,13 +1,10 @@
|
|||||||
package cn.rosercode.finance.controller;
|
package cn.rosercode.finance.controller;
|
||||||
|
|
||||||
import cn.rosercode.finance.common.Result;
|
import java.util.List;
|
||||||
import cn.rosercode.finance.dto.RuleRequest;
|
|
||||||
import cn.rosercode.finance.service.RuleService;
|
|
||||||
import cn.rosercode.finance.vo.RuleVO;
|
|
||||||
import io.swagger.v3.oas.annotations.Operation;
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
import io.swagger.v3.oas.annotations.Parameter;
|
import io.swagger.v3.oas.annotations.Parameter;
|
||||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
import jakarta.servlet.http.HttpServletRequest;
|
|
||||||
import jakarta.validation.Valid;
|
import jakarta.validation.Valid;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import org.springframework.web.bind.annotation.DeleteMapping;
|
import org.springframework.web.bind.annotation.DeleteMapping;
|
||||||
@@ -19,7 +16,11 @@ import org.springframework.web.bind.annotation.RequestBody;
|
|||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
import java.util.List;
|
import cn.rosercode.finance.common.Result;
|
||||||
|
import cn.rosercode.finance.dto.RuleRequest;
|
||||||
|
import cn.rosercode.finance.service.RuleService;
|
||||||
|
import cn.rosercode.finance.util.UserContext;
|
||||||
|
import cn.rosercode.finance.vo.RuleVO;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 规则控制器
|
* 规则控制器
|
||||||
@@ -42,27 +43,25 @@ public class RuleController {
|
|||||||
/**
|
/**
|
||||||
* 获取规则列表
|
* 获取规则列表
|
||||||
*
|
*
|
||||||
* @param request HTTP请求,从中获取用户ID
|
|
||||||
* @return 规则列表
|
* @return 规则列表
|
||||||
*/
|
*/
|
||||||
@GetMapping("/list")
|
@GetMapping("/list")
|
||||||
@Operation(summary = "获取规则列表", description = "获取当前用户的全部规则,按优先级排序")
|
@Operation(summary = "获取规则列表", description = "获取当前用户的全部规则,按优先级排序")
|
||||||
public Result<List<RuleVO>> list(HttpServletRequest request) {
|
public Result<List<RuleVO>> list() {
|
||||||
Long userId = (Long) request.getAttribute("userId");
|
Long userId = UserContext.getUserId();
|
||||||
return Result.success(ruleService.list(userId));
|
return Result.success(ruleService.list(userId));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 创建规则
|
* 创建规则
|
||||||
*
|
*
|
||||||
* @param request HTTP请求,从中获取用户ID
|
|
||||||
* @param ruleRequest 规则请求参数
|
* @param ruleRequest 规则请求参数
|
||||||
* @return 操作结果
|
* @return 操作结果
|
||||||
*/
|
*/
|
||||||
@PostMapping
|
@PostMapping
|
||||||
@Operation(summary = "创建规则", description = "为当前用户创建新的分类与标签规则")
|
@Operation(summary = "创建规则", description = "为当前用户创建新的分类与标签规则")
|
||||||
public Result<Void> create(HttpServletRequest request, @RequestBody @Valid RuleRequest ruleRequest) {
|
public Result<Void> create(@RequestBody @Valid RuleRequest ruleRequest) {
|
||||||
Long userId = (Long) request.getAttribute("userId");
|
Long userId = UserContext.getUserId();
|
||||||
ruleService.create(userId, ruleRequest);
|
ruleService.create(userId, ruleRequest);
|
||||||
return Result.success();
|
return Result.success();
|
||||||
}
|
}
|
||||||
@@ -70,17 +69,15 @@ public class RuleController {
|
|||||||
/**
|
/**
|
||||||
* 更新规则
|
* 更新规则
|
||||||
*
|
*
|
||||||
* @param request HTTP请求,从中获取用户ID
|
|
||||||
* @param id 规则ID
|
* @param id 规则ID
|
||||||
* @param ruleRequest 规则请求参数
|
* @param ruleRequest 规则请求参数
|
||||||
* @return 操作结果
|
* @return 操作结果
|
||||||
*/
|
*/
|
||||||
@PutMapping("/{id}")
|
@PutMapping("/{id}")
|
||||||
@Operation(summary = "更新规则", description = "根据规则ID更新规则信息")
|
@Operation(summary = "更新规则", description = "根据规则ID更新规则信息")
|
||||||
public Result<Void> update(HttpServletRequest request,
|
public Result<Void> update(@Parameter(description = "规则ID") @PathVariable Long id,
|
||||||
@Parameter(description = "规则ID") @PathVariable Long id,
|
|
||||||
@RequestBody @Valid RuleRequest ruleRequest) {
|
@RequestBody @Valid RuleRequest ruleRequest) {
|
||||||
Long userId = (Long) request.getAttribute("userId");
|
Long userId = UserContext.getUserId();
|
||||||
ruleService.update(userId, id, ruleRequest);
|
ruleService.update(userId, id, ruleRequest);
|
||||||
return Result.success();
|
return Result.success();
|
||||||
}
|
}
|
||||||
@@ -88,15 +85,13 @@ public class RuleController {
|
|||||||
/**
|
/**
|
||||||
* 删除规则
|
* 删除规则
|
||||||
*
|
*
|
||||||
* @param request HTTP请求,从中获取用户ID
|
|
||||||
* @param id 规则ID
|
* @param id 规则ID
|
||||||
* @return 操作结果
|
* @return 操作结果
|
||||||
*/
|
*/
|
||||||
@DeleteMapping("/{id}")
|
@DeleteMapping("/{id}")
|
||||||
@Operation(summary = "删除规则", description = "根据规则ID删除指定规则及其标签关联")
|
@Operation(summary = "删除规则", description = "根据规则ID删除指定规则及其标签关联")
|
||||||
public Result<Void> delete(HttpServletRequest request,
|
public Result<Void> delete(@Parameter(description = "规则ID") @PathVariable Long id) {
|
||||||
@Parameter(description = "规则ID") @PathVariable Long id) {
|
Long userId = UserContext.getUserId();
|
||||||
Long userId = (Long) request.getAttribute("userId");
|
|
||||||
ruleService.delete(userId, id);
|
ruleService.delete(userId, id);
|
||||||
return Result.success();
|
return Result.success();
|
||||||
}
|
}
|
||||||
@@ -104,17 +99,15 @@ public class RuleController {
|
|||||||
/**
|
/**
|
||||||
* 启用或停用规则
|
* 启用或停用规则
|
||||||
*
|
*
|
||||||
* @param request HTTP请求,从中获取用户ID
|
|
||||||
* @param id 规则ID
|
* @param id 规则ID
|
||||||
* @param enabled 是否启用
|
* @param enabled 是否启用
|
||||||
* @return 操作结果
|
* @return 操作结果
|
||||||
*/
|
*/
|
||||||
@PutMapping("/{id}/enabled")
|
@PutMapping("/{id}/enabled")
|
||||||
@Operation(summary = "启用/停用规则", description = "切换指定规则的启用状态")
|
@Operation(summary = "启用/停用规则", description = "切换指定规则的启用状态")
|
||||||
public Result<Void> toggleEnabled(HttpServletRequest request,
|
public Result<Void> toggleEnabled(@Parameter(description = "规则ID") @PathVariable Long id,
|
||||||
@Parameter(description = "规则ID") @PathVariable Long id,
|
|
||||||
@RequestBody RuleEnabledRequest enabled) {
|
@RequestBody RuleEnabledRequest enabled) {
|
||||||
Long userId = (Long) request.getAttribute("userId");
|
Long userId = UserContext.getUserId();
|
||||||
ruleService.toggleEnabled(userId, id, enabled.getEnabled());
|
ruleService.toggleEnabled(userId, id, enabled.getEnabled());
|
||||||
return Result.success();
|
return Result.success();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,26 +1,27 @@
|
|||||||
package cn.rosercode.finance.controller;
|
package cn.rosercode.finance.controller;
|
||||||
|
|
||||||
import cn.rosercode.finance.common.Result;
|
import java.util.List;
|
||||||
import cn.rosercode.finance.dto.StatisticsQuery;
|
|
||||||
import cn.rosercode.finance.dto.StatisticsRangeQuery;
|
|
||||||
import cn.rosercode.finance.enums.StatisticsDimension;
|
|
||||||
import cn.rosercode.finance.service.StatisticsService;
|
|
||||||
import cn.rosercode.finance.vo.CategoryStatisticsVO;
|
|
||||||
import cn.rosercode.finance.vo.MonthlyStatisticsVO;
|
|
||||||
import cn.rosercode.finance.vo.StatisticsGroupVO;
|
|
||||||
import cn.rosercode.finance.vo.StatisticsSummaryVO;
|
|
||||||
import cn.rosercode.finance.vo.TrendStatisticsVO;
|
|
||||||
import io.swagger.v3.oas.annotations.Operation;
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
import io.swagger.v3.oas.annotations.Parameter;
|
import io.swagger.v3.oas.annotations.Parameter;
|
||||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
import jakarta.servlet.http.HttpServletRequest;
|
|
||||||
import jakarta.validation.Valid;
|
import jakarta.validation.Valid;
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
import org.springframework.web.bind.annotation.RequestParam;
|
import org.springframework.web.bind.annotation.RequestParam;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
import java.util.List;
|
import cn.rosercode.finance.common.Result;
|
||||||
|
import cn.rosercode.finance.dto.StatisticsQuery;
|
||||||
|
import cn.rosercode.finance.dto.StatisticsRangeQuery;
|
||||||
|
import cn.rosercode.finance.enums.StatisticsDimension;
|
||||||
|
import cn.rosercode.finance.service.StatisticsService;
|
||||||
|
import cn.rosercode.finance.util.UserContext;
|
||||||
|
import cn.rosercode.finance.vo.CategoryStatisticsVO;
|
||||||
|
import cn.rosercode.finance.vo.MonthlyStatisticsVO;
|
||||||
|
import cn.rosercode.finance.vo.StatisticsGroupVO;
|
||||||
|
import cn.rosercode.finance.vo.StatisticsSummaryVO;
|
||||||
|
import cn.rosercode.finance.vo.TrendStatisticsVO;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 统计控制器
|
* 统计控制器
|
||||||
@@ -41,77 +42,70 @@ public class StatisticsController {
|
|||||||
/**
|
/**
|
||||||
* 获取月度统计数据
|
* 获取月度统计数据
|
||||||
*
|
*
|
||||||
* @param request HTTP请求,从中获取用户ID
|
|
||||||
* @param query 统计查询参数
|
* @param query 统计查询参数
|
||||||
* @return 月度统计结果
|
* @return 月度统计结果
|
||||||
*/
|
*/
|
||||||
@GetMapping("/monthly")
|
@GetMapping("/monthly")
|
||||||
@Operation(summary = "获取月度统计数据", description = "获取当前用户指定月份的收支统计汇总数据")
|
@Operation(summary = "获取月度统计数据", description = "获取当前用户指定月份的收支统计汇总数据")
|
||||||
public Result<MonthlyStatisticsVO> monthly(HttpServletRequest request, @Valid
|
public Result<MonthlyStatisticsVO> monthly(@Valid
|
||||||
@Parameter(description = "统计查询参数") StatisticsQuery query) {
|
@Parameter(description = "统计查询参数") StatisticsQuery query) {
|
||||||
Long userId = (Long) request.getAttribute("userId");
|
Long userId = UserContext.getUserId();
|
||||||
return Result.success(statisticsService.getMonthlyStatistics(userId, query));
|
return Result.success(statisticsService.getMonthlyStatistics(userId, query));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取分类统计数据
|
* 获取分类统计数据
|
||||||
*
|
*
|
||||||
* @param request HTTP请求,从中获取用户ID
|
|
||||||
* @param query 统计查询参数
|
* @param query 统计查询参数
|
||||||
* @return 分类统计列表
|
* @return 分类统计列表
|
||||||
*/
|
*/
|
||||||
@GetMapping("/category")
|
@GetMapping("/category")
|
||||||
@Operation(summary = "获取分类统计数据", description = "获取当前用户指定月份按分类维度的统计数据")
|
@Operation(summary = "获取分类统计数据", description = "获取当前用户指定月份按分类维度的统计数据")
|
||||||
public Result<List<CategoryStatisticsVO>> category(HttpServletRequest request, @Valid
|
public Result<List<CategoryStatisticsVO>> category(@Valid
|
||||||
@Parameter(description = "统计查询参数") StatisticsQuery query) {
|
@Parameter(description = "统计查询参数") StatisticsQuery query) {
|
||||||
Long userId = (Long) request.getAttribute("userId");
|
Long userId = UserContext.getUserId();
|
||||||
return Result.success(statisticsService.getCategoryStatistics(userId, query));
|
return Result.success(statisticsService.getCategoryStatistics(userId, query));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取趋势统计数据
|
* 获取趋势统计数据
|
||||||
*
|
*
|
||||||
* @param request HTTP请求,从中获取用户ID
|
|
||||||
* @param query 统计查询参数
|
* @param query 统计查询参数
|
||||||
* @return 趋势统计列表
|
* @return 趋势统计列表
|
||||||
*/
|
*/
|
||||||
@GetMapping("/trend")
|
@GetMapping("/trend")
|
||||||
@Operation(summary = "获取趋势统计数据", description = "获取当前用户指定时间范围内的收支趋势数据")
|
@Operation(summary = "获取趋势统计数据", description = "获取当前用户指定时间范围内的收支趋势数据")
|
||||||
public Result<List<TrendStatisticsVO>> trend(HttpServletRequest request, @Valid
|
public Result<List<TrendStatisticsVO>> trend(@Valid
|
||||||
@Parameter(description = "统计查询参数") StatisticsQuery query) {
|
@Parameter(description = "统计查询参数") StatisticsQuery query) {
|
||||||
Long userId = (Long) request.getAttribute("userId");
|
Long userId = UserContext.getUserId();
|
||||||
return Result.success(statisticsService.getTrendStatistics(userId, query));
|
return Result.success(statisticsService.getTrendStatistics(userId, query));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取指定时间范围的统计概览
|
* 获取指定时间范围的统计概览
|
||||||
*
|
*
|
||||||
* @param request HTTP请求,从中获取用户ID
|
|
||||||
* @param query 时间范围查询参数
|
* @param query 时间范围查询参数
|
||||||
* @return 统计概览
|
* @return 统计概览
|
||||||
*/
|
*/
|
||||||
@GetMapping("/summary")
|
@GetMapping("/summary")
|
||||||
@Operation(summary = "获取统计概览", description = "获取当前用户指定时间范围的收支汇总、日均、最大单笔与平均每笔")
|
@Operation(summary = "获取统计概览", description = "获取当前用户指定时间范围的收支汇总、日均、最大单笔与平均每笔")
|
||||||
public Result<StatisticsSummaryVO> summary(HttpServletRequest request,
|
public Result<StatisticsSummaryVO> summary(@Parameter(description = "时间范围查询参数") StatisticsRangeQuery query) {
|
||||||
@Parameter(description = "时间范围查询参数") StatisticsRangeQuery query) {
|
Long userId = UserContext.getUserId();
|
||||||
Long userId = (Long) request.getAttribute("userId");
|
|
||||||
return Result.success(statisticsService.getSummary(userId, query));
|
return Result.success(statisticsService.getSummary(userId, query));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 按维度获取分组统计数据
|
* 按维度获取分组统计数据
|
||||||
*
|
*
|
||||||
* @param request HTTP请求,从中获取用户ID
|
|
||||||
* @param dimension 统计维度(day/week/month/quarter/year/paymentMethod/category/type)
|
* @param dimension 统计维度(day/week/month/quarter/year/paymentMethod/category/type)
|
||||||
* @param query 时间范围查询参数
|
* @param query 时间范围查询参数
|
||||||
* @return 分组统计列表
|
* @return 分组统计列表
|
||||||
*/
|
*/
|
||||||
@GetMapping("/group")
|
@GetMapping("/group")
|
||||||
@Operation(summary = "获取分组统计数据", description = "按指定维度对时间范围内的交易进行分组统计")
|
@Operation(summary = "获取分组统计数据", description = "按指定维度对时间范围内的交易进行分组统计")
|
||||||
public Result<List<StatisticsGroupVO>> group(HttpServletRequest request,
|
public Result<List<StatisticsGroupVO>> group(@Parameter(description = "统计维度") @RequestParam("dimension") String dimension,
|
||||||
@Parameter(description = "统计维度") @RequestParam("dimension") String dimension,
|
|
||||||
@Parameter(description = "时间范围查询参数") StatisticsRangeQuery query) {
|
@Parameter(description = "时间范围查询参数") StatisticsRangeQuery query) {
|
||||||
Long userId = (Long) request.getAttribute("userId");
|
Long userId = UserContext.getUserId();
|
||||||
return Result.success(statisticsService.getGroup(userId, query, StatisticsDimension.from(dimension)));
|
return Result.success(statisticsService.getGroup(userId, query, StatisticsDimension.from(dimension)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,13 +1,10 @@
|
|||||||
package cn.rosercode.finance.controller;
|
package cn.rosercode.finance.controller;
|
||||||
|
|
||||||
import cn.rosercode.finance.common.Result;
|
import java.util.List;
|
||||||
import cn.rosercode.finance.dto.TagRequest;
|
|
||||||
import cn.rosercode.finance.service.TagService;
|
|
||||||
import cn.rosercode.finance.vo.TagVO;
|
|
||||||
import io.swagger.v3.oas.annotations.Operation;
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
import io.swagger.v3.oas.annotations.Parameter;
|
import io.swagger.v3.oas.annotations.Parameter;
|
||||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
import jakarta.servlet.http.HttpServletRequest;
|
|
||||||
import jakarta.validation.Valid;
|
import jakarta.validation.Valid;
|
||||||
import org.springframework.web.bind.annotation.DeleteMapping;
|
import org.springframework.web.bind.annotation.DeleteMapping;
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
@@ -18,7 +15,11 @@ import org.springframework.web.bind.annotation.RequestBody;
|
|||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
import java.util.List;
|
import cn.rosercode.finance.common.Result;
|
||||||
|
import cn.rosercode.finance.dto.TagRequest;
|
||||||
|
import cn.rosercode.finance.service.TagService;
|
||||||
|
import cn.rosercode.finance.util.UserContext;
|
||||||
|
import cn.rosercode.finance.vo.TagVO;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 标签控制器
|
* 标签控制器
|
||||||
@@ -41,27 +42,25 @@ public class TagController {
|
|||||||
/**
|
/**
|
||||||
* 获取标签列表
|
* 获取标签列表
|
||||||
*
|
*
|
||||||
* @param request HTTP请求,从中获取用户ID
|
|
||||||
* @return 标签列表
|
* @return 标签列表
|
||||||
*/
|
*/
|
||||||
@GetMapping("/list")
|
@GetMapping("/list")
|
||||||
@Operation(summary = "获取标签列表", description = "获取当前用户的全部标签")
|
@Operation(summary = "获取标签列表", description = "获取当前用户的全部标签")
|
||||||
public Result<List<TagVO>> list(HttpServletRequest request) {
|
public Result<List<TagVO>> list() {
|
||||||
Long userId = (Long) request.getAttribute("userId");
|
Long userId = UserContext.getUserId();
|
||||||
return Result.success(tagService.list(userId));
|
return Result.success(tagService.list(userId));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 创建标签
|
* 创建标签
|
||||||
*
|
*
|
||||||
* @param request HTTP请求,从中获取用户ID
|
|
||||||
* @param tagRequest 标签请求参数
|
* @param tagRequest 标签请求参数
|
||||||
* @return 操作结果
|
* @return 操作结果
|
||||||
*/
|
*/
|
||||||
@PostMapping
|
@PostMapping
|
||||||
@Operation(summary = "创建标签", description = "为当前用户创建新的标签")
|
@Operation(summary = "创建标签", description = "为当前用户创建新的标签")
|
||||||
public Result<Void> create(HttpServletRequest request, @RequestBody @Valid TagRequest tagRequest) {
|
public Result<Void> create(@RequestBody @Valid TagRequest tagRequest) {
|
||||||
Long userId = (Long) request.getAttribute("userId");
|
Long userId = UserContext.getUserId();
|
||||||
tagService.create(userId, tagRequest);
|
tagService.create(userId, tagRequest);
|
||||||
return Result.success();
|
return Result.success();
|
||||||
}
|
}
|
||||||
@@ -69,17 +68,15 @@ public class TagController {
|
|||||||
/**
|
/**
|
||||||
* 更新标签
|
* 更新标签
|
||||||
*
|
*
|
||||||
* @param request HTTP请求,从中获取用户ID
|
|
||||||
* @param id 标签ID
|
* @param id 标签ID
|
||||||
* @param tagRequest 标签请求参数
|
* @param tagRequest 标签请求参数
|
||||||
* @return 操作结果
|
* @return 操作结果
|
||||||
*/
|
*/
|
||||||
@PutMapping("/{id}")
|
@PutMapping("/{id}")
|
||||||
@Operation(summary = "更新标签", description = "根据标签ID更新标签信息")
|
@Operation(summary = "更新标签", description = "根据标签ID更新标签信息")
|
||||||
public Result<Void> update(HttpServletRequest request,
|
public Result<Void> update(@Parameter(description = "标签ID") @PathVariable Long id,
|
||||||
@Parameter(description = "标签ID") @PathVariable Long id,
|
|
||||||
@RequestBody @Valid TagRequest tagRequest) {
|
@RequestBody @Valid TagRequest tagRequest) {
|
||||||
Long userId = (Long) request.getAttribute("userId");
|
Long userId = UserContext.getUserId();
|
||||||
tagService.update(userId, id, tagRequest);
|
tagService.update(userId, id, tagRequest);
|
||||||
return Result.success();
|
return Result.success();
|
||||||
}
|
}
|
||||||
@@ -87,15 +84,13 @@ public class TagController {
|
|||||||
/**
|
/**
|
||||||
* 删除标签
|
* 删除标签
|
||||||
*
|
*
|
||||||
* @param request HTTP请求,从中获取用户ID
|
|
||||||
* @param id 标签ID
|
* @param id 标签ID
|
||||||
* @return 操作结果
|
* @return 操作结果
|
||||||
*/
|
*/
|
||||||
@DeleteMapping("/{id}")
|
@DeleteMapping("/{id}")
|
||||||
@Operation(summary = "删除标签", description = "根据标签ID删除指定标签及其交易关联")
|
@Operation(summary = "删除标签", description = "根据标签ID删除指定标签及其交易关联")
|
||||||
public Result<Void> delete(HttpServletRequest request,
|
public Result<Void> delete(@Parameter(description = "标签ID") @PathVariable Long id) {
|
||||||
@Parameter(description = "标签ID") @PathVariable Long id) {
|
Long userId = UserContext.getUserId();
|
||||||
Long userId = (Long) request.getAttribute("userId");
|
|
||||||
tagService.delete(userId, id);
|
tagService.delete(userId, id);
|
||||||
return Result.success();
|
return Result.success();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,24 +1,20 @@
|
|||||||
package cn.rosercode.finance.controller;
|
package cn.rosercode.finance.controller;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.URLEncoder;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.time.format.DateTimeFormatter;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
import com.alibaba.excel.EasyExcel;
|
import com.alibaba.excel.EasyExcel;
|
||||||
import com.alibaba.excel.ExcelWriter;
|
import com.alibaba.excel.ExcelWriter;
|
||||||
import com.alibaba.excel.write.metadata.WriteSheet;
|
import com.alibaba.excel.write.metadata.WriteSheet;
|
||||||
import com.alibaba.excel.write.style.HorizontalCellStyleStrategy;
|
import com.alibaba.excel.write.style.HorizontalCellStyleStrategy;
|
||||||
import cn.rosercode.finance.common.PageResult;
|
|
||||||
import cn.rosercode.finance.common.Result;
|
|
||||||
import cn.rosercode.finance.dto.BatchCategoryRequest;
|
|
||||||
import cn.rosercode.finance.dto.BatchDeleteRequest;
|
|
||||||
import cn.rosercode.finance.dto.BatchTagRequest;
|
|
||||||
import cn.rosercode.finance.dto.TransactionQuery;
|
|
||||||
import cn.rosercode.finance.dto.TransactionRequest;
|
|
||||||
import cn.rosercode.finance.exporter.TransactionExportSheetHandler;
|
|
||||||
import cn.rosercode.finance.service.TransactionService;
|
|
||||||
import cn.rosercode.finance.vo.TransactionExportVO;
|
|
||||||
import cn.rosercode.finance.vo.TransactionVO;
|
|
||||||
import io.swagger.v3.oas.annotations.Operation;
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
import io.swagger.v3.oas.annotations.Parameter;
|
import io.swagger.v3.oas.annotations.Parameter;
|
||||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
import jakarta.servlet.http.HttpServletRequest;
|
|
||||||
import jakarta.servlet.http.HttpServletResponse;
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
import jakarta.validation.Valid;
|
import jakarta.validation.Valid;
|
||||||
import org.apache.poi.ss.usermodel.Sheet;
|
import org.apache.poi.ss.usermodel.Sheet;
|
||||||
@@ -32,13 +28,18 @@ import org.springframework.web.bind.annotation.RequestBody;
|
|||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
import java.io.IOException;
|
import cn.rosercode.finance.common.PageResult;
|
||||||
import java.net.URLEncoder;
|
import cn.rosercode.finance.common.Result;
|
||||||
import java.nio.charset.StandardCharsets;
|
import cn.rosercode.finance.dto.BatchCategoryRequest;
|
||||||
import java.time.LocalDateTime;
|
import cn.rosercode.finance.dto.BatchDeleteRequest;
|
||||||
import java.time.format.DateTimeFormatter;
|
import cn.rosercode.finance.dto.BatchTagRequest;
|
||||||
import java.util.List;
|
import cn.rosercode.finance.dto.TransactionQuery;
|
||||||
import java.util.Map;
|
import cn.rosercode.finance.dto.TransactionRequest;
|
||||||
|
import cn.rosercode.finance.exporter.TransactionExportSheetHandler;
|
||||||
|
import cn.rosercode.finance.service.TransactionService;
|
||||||
|
import cn.rosercode.finance.util.UserContext;
|
||||||
|
import cn.rosercode.finance.vo.TransactionExportVO;
|
||||||
|
import cn.rosercode.finance.vo.TransactionVO;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 交易记录控制器
|
* 交易记录控制器
|
||||||
@@ -70,29 +71,26 @@ public class TransactionController {
|
|||||||
/**
|
/**
|
||||||
* 分页查询交易记录
|
* 分页查询交易记录
|
||||||
*
|
*
|
||||||
* @param request HTTP请求,从中获取用户ID
|
|
||||||
* @param query 分页查询参数
|
* @param query 分页查询参数
|
||||||
* @return 分页交易记录列表
|
* @return 分页交易记录列表
|
||||||
*/
|
*/
|
||||||
@GetMapping("/page")
|
@GetMapping("/page")
|
||||||
@Operation(summary = "分页查询交易记录", description = "根据查询条件分页获取当前用户的交易记录")
|
@Operation(summary = "分页查询交易记录", description = "根据查询条件分页获取当前用户的交易记录")
|
||||||
public Result<PageResult<TransactionVO>> page(HttpServletRequest request,
|
public Result<PageResult<TransactionVO>> page(@Parameter(description = "分页查询参数") TransactionQuery query) {
|
||||||
@Parameter(description = "分页查询参数") TransactionQuery query) {
|
Long userId = UserContext.getUserId();
|
||||||
Long userId = (Long) request.getAttribute("userId");
|
|
||||||
return Result.success(transactionService.page(userId, query));
|
return Result.success(transactionService.page(userId, query));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 新增交易记录
|
* 新增交易记录
|
||||||
*
|
*
|
||||||
* @param request HTTP请求,从中获取用户ID
|
|
||||||
* @param transactionRequest 交易记录请求参数
|
* @param transactionRequest 交易记录请求参数
|
||||||
* @return 操作结果
|
* @return 操作结果
|
||||||
*/
|
*/
|
||||||
@PostMapping
|
@PostMapping
|
||||||
@Operation(summary = "新增交易记录", description = "为当前用户新增一条交易记录")
|
@Operation(summary = "新增交易记录", description = "为当前用户新增一条交易记录")
|
||||||
public Result<Void> create(HttpServletRequest request, @RequestBody @Valid TransactionRequest transactionRequest) {
|
public Result<Void> create(@RequestBody @Valid TransactionRequest transactionRequest) {
|
||||||
Long userId = (Long) request.getAttribute("userId");
|
Long userId = UserContext.getUserId();
|
||||||
transactionService.create(userId, transactionRequest);
|
transactionService.create(userId, transactionRequest);
|
||||||
return Result.success();
|
return Result.success();
|
||||||
}
|
}
|
||||||
@@ -100,17 +98,15 @@ public class TransactionController {
|
|||||||
/**
|
/**
|
||||||
* 更新交易记录
|
* 更新交易记录
|
||||||
*
|
*
|
||||||
* @param request HTTP请求,从中获取用户ID
|
|
||||||
* @param id 交易记录ID
|
* @param id 交易记录ID
|
||||||
* @param transactionRequest 交易记录请求参数
|
* @param transactionRequest 交易记录请求参数
|
||||||
* @return 操作结果
|
* @return 操作结果
|
||||||
*/
|
*/
|
||||||
@PutMapping("/{id}")
|
@PutMapping("/{id}")
|
||||||
@Operation(summary = "更新交易记录", description = "根据交易记录ID更新交易信息")
|
@Operation(summary = "更新交易记录", description = "根据交易记录ID更新交易信息")
|
||||||
public Result<Void> update(HttpServletRequest request,
|
public Result<Void> update(@Parameter(description = "交易记录ID") @PathVariable Long id,
|
||||||
@Parameter(description = "交易记录ID") @PathVariable Long id,
|
|
||||||
@RequestBody @Valid TransactionRequest transactionRequest) {
|
@RequestBody @Valid TransactionRequest transactionRequest) {
|
||||||
Long userId = (Long) request.getAttribute("userId");
|
Long userId = UserContext.getUserId();
|
||||||
transactionService.update(userId, id, transactionRequest);
|
transactionService.update(userId, id, transactionRequest);
|
||||||
return Result.success();
|
return Result.success();
|
||||||
}
|
}
|
||||||
@@ -118,15 +114,13 @@ public class TransactionController {
|
|||||||
/**
|
/**
|
||||||
* 删除交易记录
|
* 删除交易记录
|
||||||
*
|
*
|
||||||
* @param request HTTP请求,从中获取用户ID
|
|
||||||
* @param id 交易记录ID
|
* @param id 交易记录ID
|
||||||
* @return 操作结果
|
* @return 操作结果
|
||||||
*/
|
*/
|
||||||
@DeleteMapping("/{id}")
|
@DeleteMapping("/{id}")
|
||||||
@Operation(summary = "删除交易记录", description = "根据交易记录ID删除指定交易记录")
|
@Operation(summary = "删除交易记录", description = "根据交易记录ID删除指定交易记录")
|
||||||
public Result<Void> delete(HttpServletRequest request,
|
public Result<Void> delete(@Parameter(description = "交易记录ID") @PathVariable Long id) {
|
||||||
@Parameter(description = "交易记录ID") @PathVariable Long id) {
|
Long userId = UserContext.getUserId();
|
||||||
Long userId = (Long) request.getAttribute("userId");
|
|
||||||
transactionService.delete(userId, id);
|
transactionService.delete(userId, id);
|
||||||
return Result.success();
|
return Result.success();
|
||||||
}
|
}
|
||||||
@@ -134,32 +128,28 @@ public class TransactionController {
|
|||||||
/**
|
/**
|
||||||
* 批量删除交易记录
|
* 批量删除交易记录
|
||||||
*
|
*
|
||||||
* @param request HTTP请求,从中获取用户ID
|
|
||||||
* @param body 批量删除请求(记录ID列表)
|
* @param body 批量删除请求(记录ID列表)
|
||||||
* @return 实际删除的记录数
|
* @return 实际删除的记录数
|
||||||
*/
|
*/
|
||||||
@DeleteMapping("/batch")
|
@DeleteMapping("/batch")
|
||||||
@Operation(summary = "批量删除交易记录", description = "根据记录ID列表批量删除当前用户的交易记录")
|
@Operation(summary = "批量删除交易记录", description = "根据记录ID列表批量删除当前用户的交易记录")
|
||||||
public Result<Integer> batchDelete(HttpServletRequest request,
|
public Result<Integer> batchDelete(@RequestBody @Valid BatchDeleteRequest body) {
|
||||||
@RequestBody @Valid BatchDeleteRequest body) {
|
Long userId = UserContext.getUserId();
|
||||||
Long userId = (Long) request.getAttribute("userId");
|
|
||||||
return Result.success(transactionService.batchDelete(userId, body.getIds()));
|
return Result.success(transactionService.batchDelete(userId, body.getIds()));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 切换交易记录的"计入统计"标记
|
* 切换交易记录的"计入统计"标记
|
||||||
*
|
*
|
||||||
* @param request HTTP请求,从中获取用户ID
|
|
||||||
* @param id 交易记录ID
|
* @param id 交易记录ID
|
||||||
* @param body 请求体,包含 includeInStats 字段
|
* @param body 请求体,包含 includeInStats 字段
|
||||||
* @return 操作结果
|
* @return 操作结果
|
||||||
*/
|
*/
|
||||||
@PutMapping("/{id}/stats")
|
@PutMapping("/{id}/stats")
|
||||||
@Operation(summary = "切换计入统计标记", description = "切换交易记录是否计入统计(用于表格中开关)")
|
@Operation(summary = "切换计入统计标记", description = "切换交易记录是否计入统计(用于表格中开关)")
|
||||||
public Result<Void> toggleStats(HttpServletRequest request,
|
public Result<Void> toggleStats(@Parameter(description = "交易记录ID") @PathVariable Long id,
|
||||||
@Parameter(description = "交易记录ID") @PathVariable Long id,
|
|
||||||
@RequestBody Map<String, Boolean> body) {
|
@RequestBody Map<String, Boolean> body) {
|
||||||
Long userId = (Long) request.getAttribute("userId");
|
Long userId = UserContext.getUserId();
|
||||||
Boolean includeInStats = body != null ? body.get("includeInStats") : null;
|
Boolean includeInStats = body != null ? body.get("includeInStats") : null;
|
||||||
transactionService.toggleStats(userId, id, includeInStats);
|
transactionService.toggleStats(userId, id, includeInStats);
|
||||||
return Result.success();
|
return Result.success();
|
||||||
@@ -168,17 +158,15 @@ public class TransactionController {
|
|||||||
/**
|
/**
|
||||||
* 切换交易记录的备注隐藏标记
|
* 切换交易记录的备注隐藏标记
|
||||||
*
|
*
|
||||||
* @param request HTTP请求,从中获取用户ID
|
|
||||||
* @param id 交易记录ID
|
* @param id 交易记录ID
|
||||||
* @param body 请求体,包含 remarkHidden 字段
|
* @param body 请求体,包含 remarkHidden 字段
|
||||||
* @return 操作结果
|
* @return 操作结果
|
||||||
*/
|
*/
|
||||||
@PutMapping("/{id}/remark-hidden")
|
@PutMapping("/{id}/remark-hidden")
|
||||||
@Operation(summary = "切换备注隐藏标记", description = "切换交易记录的备注是否隐藏(用于表格中单元格按钮)")
|
@Operation(summary = "切换备注隐藏标记", description = "切换交易记录的备注是否隐藏(用于表格中单元格按钮)")
|
||||||
public Result<Void> toggleRemarkHidden(HttpServletRequest request,
|
public Result<Void> toggleRemarkHidden(@Parameter(description = "交易记录ID") @PathVariable Long id,
|
||||||
@Parameter(description = "交易记录ID") @PathVariable Long id,
|
|
||||||
@RequestBody Map<String, Boolean> body) {
|
@RequestBody Map<String, Boolean> body) {
|
||||||
Long userId = (Long) request.getAttribute("userId");
|
Long userId = UserContext.getUserId();
|
||||||
Boolean remarkHidden = body != null ? body.get("remarkHidden") : null;
|
Boolean remarkHidden = body != null ? body.get("remarkHidden") : null;
|
||||||
transactionService.toggleRemarkHidden(userId, id, remarkHidden);
|
transactionService.toggleRemarkHidden(userId, id, remarkHidden);
|
||||||
return Result.success();
|
return Result.success();
|
||||||
@@ -187,47 +175,40 @@ public class TransactionController {
|
|||||||
/**
|
/**
|
||||||
* 批量设置交易记录的分类
|
* 批量设置交易记录的分类
|
||||||
*
|
*
|
||||||
* @param request HTTP请求,从中获取用户ID
|
|
||||||
* @param body 批量设置请求参数
|
* @param body 批量设置请求参数
|
||||||
* @return 实际更新的记录数
|
* @return 实际更新的记录数
|
||||||
*/
|
*/
|
||||||
@PutMapping("/batch-category")
|
@PutMapping("/batch-category")
|
||||||
@Operation(summary = "批量设置分类", description = "将当前表格展示的多条交易记录按类型一键归入所选分类")
|
@Operation(summary = "批量设置分类", description = "将当前表格展示的多条交易记录按类型一键归入所选分类")
|
||||||
public Result<Integer> batchUpdateCategory(HttpServletRequest request,
|
public Result<Integer> batchUpdateCategory(@RequestBody @Valid BatchCategoryRequest body) {
|
||||||
@RequestBody @Valid BatchCategoryRequest body) {
|
Long userId = UserContext.getUserId();
|
||||||
Long userId = (Long) request.getAttribute("userId");
|
|
||||||
return Result.success(transactionService.batchUpdateCategory(userId, body));
|
return Result.success(transactionService.batchUpdateCategory(userId, body));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 批量给交易记录添加/移除标签
|
* 批量给交易记录添加/移除标签
|
||||||
*
|
*
|
||||||
* @param request HTTP请求,从中获取用户ID
|
|
||||||
* @param body 批量标签请求参数
|
* @param body 批量标签请求参数
|
||||||
* @return 涉及的记录数
|
* @return 涉及的记录数
|
||||||
*/
|
*/
|
||||||
@PutMapping("/batch-tags")
|
@PutMapping("/batch-tags")
|
||||||
@Operation(summary = "批量设置标签", description = "为选中的交易记录添加或移除标签")
|
@Operation(summary = "批量设置标签", description = "为选中的交易记录添加或移除标签")
|
||||||
public Result<Integer> batchTags(HttpServletRequest request,
|
public Result<Integer> batchTags(@RequestBody @Valid BatchTagRequest body) {
|
||||||
@RequestBody @Valid BatchTagRequest body) {
|
Long userId = UserContext.getUserId();
|
||||||
Long userId = (Long) request.getAttribute("userId");
|
|
||||||
return Result.success(transactionService.batchTags(userId, body));
|
return Result.success(transactionService.batchTags(userId, body));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 导出交易记录为 Excel 文件
|
* 导出交易记录为 Excel 文件
|
||||||
*
|
*
|
||||||
* @param request HTTP请求,从中获取用户ID
|
|
||||||
* @param response HTTP响应,用于输出文件流
|
|
||||||
* @param query 查询条件
|
* @param query 查询条件
|
||||||
* @throws IOException 文件输出异常
|
* @throws IOException 文件输出异常
|
||||||
*/
|
*/
|
||||||
@GetMapping("/export")
|
@GetMapping("/export")
|
||||||
@Operation(summary = "导出交易记录", description = "根据查询条件导出交易记录为 Excel 文件")
|
@Operation(summary = "导出交易记录", description = "根据查询条件导出交易记录为 Excel 文件")
|
||||||
public void export(HttpServletRequest request,
|
public void export(@Parameter(description = "查询条件") TransactionQuery query) throws IOException {
|
||||||
HttpServletResponse response,
|
Long userId = UserContext.getUserId();
|
||||||
@Parameter(description = "查询条件") TransactionQuery query) throws IOException {
|
HttpServletResponse response = UserContext.getResponse();
|
||||||
Long userId = (Long) request.getAttribute("userId");
|
|
||||||
|
|
||||||
// 设置响应头
|
// 设置响应头
|
||||||
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
|
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
|
||||||
|
|||||||
@@ -1,17 +1,7 @@
|
|||||||
package cn.rosercode.finance.controller;
|
package cn.rosercode.finance.controller;
|
||||||
|
|
||||||
import cn.rosercode.finance.common.Result;
|
|
||||||
import cn.rosercode.finance.dto.LoginRequest;
|
|
||||||
import cn.rosercode.finance.dto.RegisterRequest;
|
|
||||||
import cn.rosercode.finance.dto.RegistrationUpdateRequest;
|
|
||||||
import cn.rosercode.finance.service.RegistrationService;
|
|
||||||
import cn.rosercode.finance.service.UserService;
|
|
||||||
import cn.rosercode.finance.vo.LoginVO;
|
|
||||||
import cn.rosercode.finance.vo.RegistrationStatusVO;
|
|
||||||
import cn.rosercode.finance.vo.UserVO;
|
|
||||||
import io.swagger.v3.oas.annotations.Operation;
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
import jakarta.servlet.http.HttpServletRequest;
|
|
||||||
import jakarta.validation.Valid;
|
import jakarta.validation.Valid;
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
import org.springframework.web.bind.annotation.PostMapping;
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
@@ -20,6 +10,17 @@ import org.springframework.web.bind.annotation.RequestBody;
|
|||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
import cn.rosercode.finance.common.Result;
|
||||||
|
import cn.rosercode.finance.dto.LoginRequest;
|
||||||
|
import cn.rosercode.finance.dto.RegisterRequest;
|
||||||
|
import cn.rosercode.finance.dto.RegistrationUpdateRequest;
|
||||||
|
import cn.rosercode.finance.service.RegistrationService;
|
||||||
|
import cn.rosercode.finance.service.UserService;
|
||||||
|
import cn.rosercode.finance.util.UserContext;
|
||||||
|
import cn.rosercode.finance.vo.LoginVO;
|
||||||
|
import cn.rosercode.finance.vo.RegistrationStatusVO;
|
||||||
|
import cn.rosercode.finance.vo.UserVO;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 用户控制器
|
* 用户控制器
|
||||||
*
|
*
|
||||||
@@ -90,13 +91,12 @@ public class UserController {
|
|||||||
/**
|
/**
|
||||||
* 获取当前用户信息
|
* 获取当前用户信息
|
||||||
*
|
*
|
||||||
* @param request HTTP请求,从中获取用户ID
|
|
||||||
* @return 用户信息
|
* @return 用户信息
|
||||||
*/
|
*/
|
||||||
@GetMapping("/info")
|
@GetMapping("/info")
|
||||||
@Operation(summary = "获取当前用户信息", description = "获取已登录用户的详细信息")
|
@Operation(summary = "获取当前用户信息", description = "获取已登录用户的详细信息")
|
||||||
public Result<UserVO> info(HttpServletRequest request) {
|
public Result<UserVO> info() {
|
||||||
Long userId = (Long) request.getAttribute("userId");
|
Long userId = UserContext.getUserId();
|
||||||
return Result.success(userService.getUserInfo(userId));
|
return Result.success(userService.getUserInfo(userId));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,11 @@
|
|||||||
package cn.rosercode.finance.converter;
|
package cn.rosercode.finance.converter;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.mapstruct.Mapper;
|
||||||
|
import org.mapstruct.Mapping;
|
||||||
|
import org.mapstruct.ReportingPolicy;
|
||||||
|
|
||||||
import cn.rosercode.finance.entity.AiUsage;
|
import cn.rosercode.finance.entity.AiUsage;
|
||||||
import cn.rosercode.finance.entity.Category;
|
import cn.rosercode.finance.entity.Category;
|
||||||
import cn.rosercode.finance.entity.HttpLog;
|
import cn.rosercode.finance.entity.HttpLog;
|
||||||
@@ -20,11 +26,6 @@ import cn.rosercode.finance.vo.RuleVO;
|
|||||||
import cn.rosercode.finance.vo.TagVO;
|
import cn.rosercode.finance.vo.TagVO;
|
||||||
import cn.rosercode.finance.vo.TransactionVO;
|
import cn.rosercode.finance.vo.TransactionVO;
|
||||||
import cn.rosercode.finance.vo.UserVO;
|
import cn.rosercode.finance.vo.UserVO;
|
||||||
import org.mapstruct.Mapper;
|
|
||||||
import org.mapstruct.Mapping;
|
|
||||||
import org.mapstruct.ReportingPolicy;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 实体与视图对象之间的转换器,由 MapStruct 在编译期生成实现。
|
* 实体与视图对象之间的转换器,由 MapStruct 在编译期生成实现。
|
||||||
|
|||||||
@@ -1,12 +1,13 @@
|
|||||||
package cn.rosercode.finance.dto;
|
package cn.rosercode.finance.dto;
|
||||||
|
|
||||||
import cn.rosercode.finance.vo.AiNewTagVO;
|
import java.util.List;
|
||||||
|
|
||||||
import jakarta.validation.Valid;
|
import jakarta.validation.Valid;
|
||||||
import jakarta.validation.constraints.NotEmpty;
|
import jakarta.validation.constraints.NotEmpty;
|
||||||
import jakarta.validation.constraints.NotNull;
|
import jakarta.validation.constraints.NotNull;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
import java.util.List;
|
import cn.rosercode.finance.vo.AiNewTagVO;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* AI 建议应用请求DTO,携带逐条记录的建议分类与标签,用于一键写入。
|
* AI 建议应用请求DTO,携带逐条记录的建议分类与标签,用于一键写入。
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
package cn.rosercode.finance.dto;
|
package cn.rosercode.finance.dto;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
|
||||||
import jakarta.validation.constraints.NotBlank;
|
import jakarta.validation.constraints.NotBlank;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 单条记录 AI 建议请求 DTO,携带表单当前内容用于生成分类与标签建议。
|
* 单条记录 AI 建议请求 DTO,携带表单当前内容用于生成分类与标签建议。
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
package cn.rosercode.finance.dto;
|
package cn.rosercode.finance.dto;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import jakarta.validation.constraints.NotEmpty;
|
import jakarta.validation.constraints.NotEmpty;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* AI 建议请求DTO,携带需要分析分类与标签的交易记录ID列表。
|
* AI 建议请求DTO,携带需要分析分类与标签的交易记录ID列表。
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
package cn.rosercode.finance.dto;
|
package cn.rosercode.finance.dto;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import jakarta.validation.constraints.NotEmpty;
|
import jakarta.validation.constraints.NotEmpty;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 批量设置分类请求 DTO,用于将当前表格展示的多条交易记录一键归入分类。
|
* 批量设置分类请求 DTO,用于将当前表格展示的多条交易记录一键归入分类。
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
package cn.rosercode.finance.dto;
|
package cn.rosercode.finance.dto;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import jakarta.validation.constraints.NotEmpty;
|
import jakarta.validation.constraints.NotEmpty;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 批量删除交易记录请求DTO,用于一次性删除多条收支记录。
|
* 批量删除交易记录请求DTO,用于一次性删除多条收支记录。
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
package cn.rosercode.finance.dto;
|
package cn.rosercode.finance.dto;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import jakarta.validation.constraints.NotEmpty;
|
import jakarta.validation.constraints.NotEmpty;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 批量设置标签请求DTO,用于为多条交易记录添加或移除标签。
|
* 批量设置标签请求DTO,用于为多条交易记录添加或移除标签。
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
package cn.rosercode.finance.dto;
|
package cn.rosercode.finance.dto;
|
||||||
|
|
||||||
import jakarta.validation.constraints.NotBlank;
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import jakarta.validation.constraints.NotBlank;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 账单导入请求 DTO,用于「后导入」阶段接收前端回传的勾选行。
|
* 账单导入请求 DTO,用于「后导入」阶段接收前端回传的勾选行。
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
package cn.rosercode.finance.dto;
|
package cn.rosercode.finance.dto;
|
||||||
|
|
||||||
import cn.rosercode.finance.config.datasource.DataSourceType;
|
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
|
import cn.rosercode.finance.config.datasource.DataSourceType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 数据库配置请求对象,用于提交 MySQL 或 SQLite 的连接信息。
|
* 数据库配置请求对象,用于提交 MySQL 或 SQLite 的连接信息。
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
package cn.rosercode.finance.dto;
|
package cn.rosercode.finance.dto;
|
||||||
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 通知渠道保存请求DTO,用于新增或修改消息推送渠道。
|
* 通知渠道保存请求DTO,用于新增或修改消息推送渠道。
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
package cn.rosercode.finance.dto;
|
package cn.rosercode.finance.dto;
|
||||||
|
|
||||||
import jakarta.validation.constraints.NotBlank;
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import jakarta.validation.constraints.NotBlank;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 规则请求DTO,用于接收创建或更新自定义分类与标签规则时提交的信息。
|
* 规则请求DTO,用于接收创建或更新自定义分类与标签规则时提交的信息。
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
package cn.rosercode.finance.dto;
|
package cn.rosercode.finance.dto;
|
||||||
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 统计查询 DTO,用于按时间区间及可选过滤条件进行统计。
|
* 统计查询 DTO,用于按时间区间及可选过滤条件进行统计。
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
package cn.rosercode.finance.dto;
|
package cn.rosercode.finance.dto;
|
||||||
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 交易查询DTO,用于接收交易记录分页查询的筛选条件
|
* 交易查询DTO,用于接收交易记录分页查询的筛选条件
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
package cn.rosercode.finance.dto;
|
package cn.rosercode.finance.dto;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import jakarta.validation.constraints.DecimalMin;
|
import jakarta.validation.constraints.DecimalMin;
|
||||||
import jakarta.validation.constraints.NotBlank;
|
import jakarta.validation.constraints.NotBlank;
|
||||||
import jakarta.validation.constraints.NotNull;
|
import jakarta.validation.constraints.NotNull;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
|
||||||
import java.time.LocalDateTime;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 交易请求DTO,用于接收创建或更新交易记录时提交的信息
|
* 交易请求DTO,用于接收创建或更新交易记录时提交的信息
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
package cn.rosercode.finance.entity;
|
package cn.rosercode.finance.entity;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.annotation.IdType;
|
import com.baomidou.mybatisplus.annotation.IdType;
|
||||||
import com.baomidou.mybatisplus.annotation.TableId;
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
import com.baomidou.mybatisplus.annotation.TableName;
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
import java.time.LocalDateTime;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* AI 配置实体类,对应数据库表 t_ai_config,用于记录用户的 AI 智能建议配置。
|
* AI 配置实体类,对应数据库表 t_ai_config,用于记录用户的 AI 智能建议配置。
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
package cn.rosercode.finance.entity;
|
package cn.rosercode.finance.entity;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.annotation.IdType;
|
import com.baomidou.mybatisplus.annotation.IdType;
|
||||||
import com.baomidou.mybatisplus.annotation.TableId;
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
import com.baomidou.mybatisplus.annotation.TableName;
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
import java.time.LocalDateTime;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* AI 使用记录实体类,对应数据库表 t_ai_usage,记录每次调用 DeepSeek 的用量与结果。
|
* AI 使用记录实体类,对应数据库表 t_ai_usage,记录每次调用 DeepSeek 的用量与结果。
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
package cn.rosercode.finance.entity;
|
package cn.rosercode.finance.entity;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.annotation.IdType;
|
import com.baomidou.mybatisplus.annotation.IdType;
|
||||||
import com.baomidou.mybatisplus.annotation.TableId;
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
import com.baomidou.mybatisplus.annotation.TableName;
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
import java.time.LocalDateTime;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 分类实体类,对应数据库表 t_category,用于记录收支分类信息
|
* 分类实体类,对应数据库表 t_category,用于记录收支分类信息
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
package cn.rosercode.finance.entity;
|
package cn.rosercode.finance.entity;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.annotation.IdType;
|
import com.baomidou.mybatisplus.annotation.IdType;
|
||||||
import com.baomidou.mybatisplus.annotation.TableId;
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
import com.baomidou.mybatisplus.annotation.TableName;
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
import java.time.LocalDateTime;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* HTTP 访问日志实体类,对应数据库表 t_http_log,记录每次接口请求的方法、路径、状态与耗时。
|
* HTTP 访问日志实体类,对应数据库表 t_http_log,记录每次接口请求的方法、路径、状态与耗时。
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
package cn.rosercode.finance.entity;
|
package cn.rosercode.finance.entity;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.annotation.IdType;
|
import com.baomidou.mybatisplus.annotation.IdType;
|
||||||
import com.baomidou.mybatisplus.annotation.TableId;
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
import com.baomidou.mybatisplus.annotation.TableName;
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
import java.time.LocalDateTime;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 登录日志实体类,对应数据库表 t_login_log,记录每次登录尝试的结果。
|
* 登录日志实体类,对应数据库表 t_login_log,记录每次登录尝试的结果。
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
package cn.rosercode.finance.entity;
|
package cn.rosercode.finance.entity;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.annotation.IdType;
|
import com.baomidou.mybatisplus.annotation.IdType;
|
||||||
import com.baomidou.mybatisplus.annotation.TableId;
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
import com.baomidou.mybatisplus.annotation.TableName;
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
import java.time.LocalDateTime;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 通知渠道实体类,对应数据库表 t_notification_channel,用于记录用户配置的消息推送渠道。
|
* 通知渠道实体类,对应数据库表 t_notification_channel,用于记录用户配置的消息推送渠道。
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
package cn.rosercode.finance.entity;
|
package cn.rosercode.finance.entity;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.annotation.IdType;
|
import com.baomidou.mybatisplus.annotation.IdType;
|
||||||
import com.baomidou.mybatisplus.annotation.TableId;
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
import com.baomidou.mybatisplus.annotation.TableName;
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
import java.time.LocalDateTime;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 通知配置实体类,对应数据库表 t_notification_config,用于记录用户的账单导入提醒周期。
|
* 通知配置实体类,对应数据库表 t_notification_config,用于记录用户的账单导入提醒周期。
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
package cn.rosercode.finance.entity;
|
package cn.rosercode.finance.entity;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.annotation.IdType;
|
import com.baomidou.mybatisplus.annotation.IdType;
|
||||||
import com.baomidou.mybatisplus.annotation.TableId;
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
import com.baomidou.mybatisplus.annotation.TableName;
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
import java.time.LocalDateTime;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 通知日志实体类,对应数据库表 t_notification_log,用于记录每次提醒的发送结果。
|
* 通知日志实体类,对应数据库表 t_notification_log,用于记录每次提醒的发送结果。
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
package cn.rosercode.finance.entity;
|
package cn.rosercode.finance.entity;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.annotation.IdType;
|
import com.baomidou.mybatisplus.annotation.IdType;
|
||||||
import com.baomidou.mybatisplus.annotation.TableId;
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
import com.baomidou.mybatisplus.annotation.TableName;
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
|
||||||
import java.time.LocalDateTime;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 自定义分类与标签规则实体类,对应数据库表 t_rule。
|
* 自定义分类与标签规则实体类,对应数据库表 t_rule。
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
package cn.rosercode.finance.entity;
|
package cn.rosercode.finance.entity;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.annotation.IdType;
|
import com.baomidou.mybatisplus.annotation.IdType;
|
||||||
import com.baomidou.mybatisplus.annotation.TableId;
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
import com.baomidou.mybatisplus.annotation.TableName;
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
import java.time.LocalDateTime;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 规则标签关联实体类,对应数据库表 t_rule_tag,表示规则与标签的多对多关系。
|
* 规则标签关联实体类,对应数据库表 t_rule_tag,表示规则与标签的多对多关系。
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
package cn.rosercode.finance.entity;
|
package cn.rosercode.finance.entity;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.annotation.IdType;
|
import com.baomidou.mybatisplus.annotation.IdType;
|
||||||
import com.baomidou.mybatisplus.annotation.TableId;
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
import com.baomidou.mybatisplus.annotation.TableName;
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
import java.time.LocalDateTime;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 标签实体类,对应数据库表 t_tag,用于记录用户自定义标签。
|
* 标签实体类,对应数据库表 t_tag,用于记录用户自定义标签。
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
package cn.rosercode.finance.entity;
|
package cn.rosercode.finance.entity;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.annotation.IdType;
|
import com.baomidou.mybatisplus.annotation.IdType;
|
||||||
import com.baomidou.mybatisplus.annotation.TableId;
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
import com.baomidou.mybatisplus.annotation.TableName;
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
|
||||||
import java.time.LocalDateTime;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 交易记录实体类,对应数据库表 t_transaction,用于记录每笔收支交易
|
* 交易记录实体类,对应数据库表 t_transaction,用于记录每笔收支交易
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
package cn.rosercode.finance.entity;
|
package cn.rosercode.finance.entity;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.annotation.IdType;
|
import com.baomidou.mybatisplus.annotation.IdType;
|
||||||
import com.baomidou.mybatisplus.annotation.TableId;
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
import com.baomidou.mybatisplus.annotation.TableName;
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
import java.time.LocalDateTime;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 交易标签关联实体类,对应数据库表 t_transaction_tag,维护交易与标签的多对多关系。
|
* 交易标签关联实体类,对应数据库表 t_transaction_tag,维护交易与标签的多对多关系。
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
package cn.rosercode.finance.entity;
|
package cn.rosercode.finance.entity;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.annotation.IdType;
|
import com.baomidou.mybatisplus.annotation.IdType;
|
||||||
import com.baomidou.mybatisplus.annotation.TableId;
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
import com.baomidou.mybatisplus.annotation.TableName;
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
import java.time.LocalDateTime;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 用户实体类,对应数据库表 t_user
|
* 用户实体类,对应数据库表 t_user
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -1,14 +1,5 @@
|
|||||||
package cn.rosercode.finance.importer;
|
package cn.rosercode.finance.importer;
|
||||||
|
|
||||||
import cn.rosercode.finance.enums.BillType;
|
|
||||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
|
||||||
import org.apache.commons.csv.CSVFormat;
|
|
||||||
import org.apache.commons.csv.CSVParser;
|
|
||||||
import org.apache.commons.csv.CSVRecord;
|
|
||||||
import org.springframework.stereotype.Component;
|
|
||||||
import org.springframework.util.StringUtils;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
@@ -24,6 +15,16 @@ import java.util.LinkedHashMap;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import org.apache.commons.csv.CSVFormat;
|
||||||
|
import org.apache.commons.csv.CSVParser;
|
||||||
|
import org.apache.commons.csv.CSVRecord;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
|
import cn.rosercode.finance.enums.BillType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 支付宝账单解析器。
|
* 支付宝账单解析器。
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -1,11 +1,5 @@
|
|||||||
package cn.rosercode.finance.importer;
|
package cn.rosercode.finance.importer;
|
||||||
|
|
||||||
import cn.rosercode.finance.common.BusinessException;
|
|
||||||
import net.lingala.zip4j.ZipFile;
|
|
||||||
import net.lingala.zip4j.exception.ZipException;
|
|
||||||
import net.lingala.zip4j.model.FileHeader;
|
|
||||||
import org.springframework.stereotype.Component;
|
|
||||||
|
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
@@ -13,6 +7,13 @@ import java.nio.file.Files;
|
|||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import net.lingala.zip4j.ZipFile;
|
||||||
|
import net.lingala.zip4j.exception.ZipException;
|
||||||
|
import net.lingala.zip4j.model.FileHeader;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import cn.rosercode.finance.common.BusinessException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 账单压缩包解压工具。
|
* 账单压缩包解压工具。
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
package cn.rosercode.finance.importer;
|
package cn.rosercode.finance.importer;
|
||||||
|
|
||||||
import cn.rosercode.finance.enums.BillType;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import cn.rosercode.finance.enums.BillType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 账单解析器接口,定义不同账单来源的解析行为。
|
* 账单解析器接口,定义不同账单来源的解析行为。
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -1,17 +1,5 @@
|
|||||||
package cn.rosercode.finance.importer;
|
package cn.rosercode.finance.importer;
|
||||||
|
|
||||||
import cn.rosercode.finance.enums.BillType;
|
|
||||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
|
||||||
import org.apache.poi.ss.usermodel.Cell;
|
|
||||||
import org.apache.poi.ss.usermodel.CellType;
|
|
||||||
import org.apache.poi.ss.usermodel.Row;
|
|
||||||
import org.apache.poi.ss.usermodel.Sheet;
|
|
||||||
import org.apache.poi.ss.usermodel.Workbook;
|
|
||||||
import org.apache.poi.ss.usermodel.WorkbookFactory;
|
|
||||||
import org.springframework.stereotype.Component;
|
|
||||||
import org.springframework.util.StringUtils;
|
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
@@ -25,6 +13,19 @@ import java.util.LinkedHashMap;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import org.apache.poi.ss.usermodel.Cell;
|
||||||
|
import org.apache.poi.ss.usermodel.CellType;
|
||||||
|
import org.apache.poi.ss.usermodel.Row;
|
||||||
|
import org.apache.poi.ss.usermodel.Sheet;
|
||||||
|
import org.apache.poi.ss.usermodel.Workbook;
|
||||||
|
import org.apache.poi.ss.usermodel.WorkbookFactory;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
|
import cn.rosercode.finance.enums.BillType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 交通银行账单解析器。
|
* 交通银行账单解析器。
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -1,14 +1,5 @@
|
|||||||
package cn.rosercode.finance.importer;
|
package cn.rosercode.finance.importer;
|
||||||
|
|
||||||
import cn.rosercode.finance.enums.BillType;
|
|
||||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
|
||||||
import org.apache.commons.csv.CSVFormat;
|
|
||||||
import org.apache.commons.csv.CSVParser;
|
|
||||||
import org.apache.commons.csv.CSVRecord;
|
|
||||||
import org.springframework.stereotype.Component;
|
|
||||||
import org.springframework.util.StringUtils;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
import java.math.RoundingMode;
|
import java.math.RoundingMode;
|
||||||
@@ -27,6 +18,16 @@ import java.util.LinkedHashMap;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import org.apache.commons.csv.CSVFormat;
|
||||||
|
import org.apache.commons.csv.CSVParser;
|
||||||
|
import org.apache.commons.csv.CSVRecord;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
|
import cn.rosercode.finance.enums.BillType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 招商银行账单解析器。
|
* 招商银行账单解析器。
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -1,14 +1,5 @@
|
|||||||
package cn.rosercode.finance.importer;
|
package cn.rosercode.finance.importer;
|
||||||
|
|
||||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
|
||||||
import org.apache.pdfbox.Loader;
|
|
||||||
import org.apache.pdfbox.pdmodel.PDDocument;
|
|
||||||
import org.apache.pdfbox.text.PDFTextStripper;
|
|
||||||
import org.apache.pdfbox.text.TextPosition;
|
|
||||||
import org.springframework.stereotype.Component;
|
|
||||||
import org.springframework.util.StringUtils;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
import java.math.RoundingMode;
|
import java.math.RoundingMode;
|
||||||
@@ -22,6 +13,15 @@ import java.util.List;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import org.apache.pdfbox.Loader;
|
||||||
|
import org.apache.pdfbox.pdmodel.PDDocument;
|
||||||
|
import org.apache.pdfbox.text.PDFTextStripper;
|
||||||
|
import org.apache.pdfbox.text.TextPosition;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 招商银行「交易流水」PDF 解析器。
|
* 招商银行「交易流水」PDF 解析器。
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -1,14 +1,5 @@
|
|||||||
package cn.rosercode.finance.importer;
|
package cn.rosercode.finance.importer;
|
||||||
|
|
||||||
import cn.rosercode.finance.enums.BillType;
|
|
||||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
|
||||||
import org.apache.commons.csv.CSVFormat;
|
|
||||||
import org.apache.commons.csv.CSVParser;
|
|
||||||
import org.apache.commons.csv.CSVRecord;
|
|
||||||
import org.springframework.stereotype.Component;
|
|
||||||
import org.springframework.util.StringUtils;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
@@ -24,6 +15,16 @@ import java.util.LinkedHashMap;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import org.apache.commons.csv.CSVFormat;
|
||||||
|
import org.apache.commons.csv.CSVParser;
|
||||||
|
import org.apache.commons.csv.CSVRecord;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
|
import cn.rosercode.finance.enums.BillType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 美团账单解析器。
|
* 美团账单解析器。
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -1,12 +1,13 @@
|
|||||||
package cn.rosercode.finance.importer;
|
package cn.rosercode.finance.importer;
|
||||||
|
|
||||||
import cn.rosercode.finance.vo.TagVO;
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import cn.rosercode.finance.vo.TagVO;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 账单解析结果行,作为「先解析、后导入」流程中解析阶段的中间对象。
|
* 账单解析结果行,作为「先解析、后导入」流程中解析阶段的中间对象。
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -1,17 +1,5 @@
|
|||||||
package cn.rosercode.finance.importer;
|
package cn.rosercode.finance.importer;
|
||||||
|
|
||||||
import cn.rosercode.finance.enums.BillType;
|
|
||||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
|
||||||
import org.apache.poi.ss.usermodel.Cell;
|
|
||||||
import org.apache.poi.ss.usermodel.CellType;
|
|
||||||
import org.apache.poi.ss.usermodel.Row;
|
|
||||||
import org.apache.poi.ss.usermodel.Sheet;
|
|
||||||
import org.apache.poi.ss.usermodel.Workbook;
|
|
||||||
import org.apache.poi.ss.usermodel.WorkbookFactory;
|
|
||||||
import org.springframework.stereotype.Component;
|
|
||||||
import org.springframework.util.StringUtils;
|
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
@@ -23,6 +11,19 @@ import java.util.LinkedHashMap;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import org.apache.poi.ss.usermodel.Cell;
|
||||||
|
import org.apache.poi.ss.usermodel.CellType;
|
||||||
|
import org.apache.poi.ss.usermodel.Row;
|
||||||
|
import org.apache.poi.ss.usermodel.Sheet;
|
||||||
|
import org.apache.poi.ss.usermodel.Workbook;
|
||||||
|
import org.apache.poi.ss.usermodel.WorkbookFactory;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
|
import cn.rosercode.finance.enums.BillType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 微信支付账单解析器。
|
* 微信支付账单解析器。
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
package cn.rosercode.finance.interceptor;
|
package cn.rosercode.finance.interceptor;
|
||||||
|
|
||||||
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import org.springframework.web.servlet.HandlerInterceptor;
|
||||||
|
|
||||||
import cn.rosercode.finance.entity.HttpLog;
|
import cn.rosercode.finance.entity.HttpLog;
|
||||||
import cn.rosercode.finance.service.LogService;
|
import cn.rosercode.finance.service.LogService;
|
||||||
import cn.rosercode.finance.util.RequestUtils;
|
import cn.rosercode.finance.util.RequestUtils;
|
||||||
import jakarta.servlet.http.HttpServletRequest;
|
|
||||||
import jakarta.servlet.http.HttpServletResponse;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
import org.springframework.stereotype.Component;
|
|
||||||
import org.springframework.web.servlet.HandlerInterceptor;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* HTTP 访问日志拦截器。
|
* HTTP 访问日志拦截器。
|
||||||
@@ -19,10 +19,9 @@ import org.springframework.web.servlet.HandlerInterceptor;
|
|||||||
* @date 2026-09-18 16:53:21
|
* @date 2026-09-18 16:53:21
|
||||||
*/
|
*/
|
||||||
@Component
|
@Component
|
||||||
|
@Slf4j
|
||||||
public class AccessLogInterceptor implements HandlerInterceptor {
|
public class AccessLogInterceptor implements HandlerInterceptor {
|
||||||
|
|
||||||
private static final Logger log = LoggerFactory.getLogger(AccessLogInterceptor.class);
|
|
||||||
|
|
||||||
/** 请求属性名:请求开始时间 */
|
/** 请求属性名:请求开始时间 */
|
||||||
private static final String START_TIME_ATTR = "accessLogStartTime";
|
private static final String START_TIME_ATTR = "accessLogStartTime";
|
||||||
|
|
||||||
|
|||||||
@@ -1,15 +1,16 @@
|
|||||||
package cn.rosercode.finance.interceptor;
|
package cn.rosercode.finance.interceptor;
|
||||||
|
|
||||||
import cn.rosercode.finance.config.datasource.DataSourceContextHolder;
|
import java.util.HashMap;
|
||||||
import cn.rosercode.finance.util.JwtUtil;
|
import java.util.Map;
|
||||||
|
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import jakarta.servlet.http.HttpServletRequest;
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
import jakarta.servlet.http.HttpServletResponse;
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
import org.springframework.web.servlet.HandlerInterceptor;
|
import org.springframework.web.servlet.HandlerInterceptor;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import cn.rosercode.finance.config.datasource.DataSourceContextHolder;
|
||||||
import java.util.Map;
|
import cn.rosercode.finance.util.JwtUtil;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* JWT 认证拦截器。
|
* JWT 认证拦截器。
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
package cn.rosercode.finance.mapper;
|
package cn.rosercode.finance.mapper;
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
import cn.rosercode.finance.entity.AiConfig;
|
|
||||||
import org.apache.ibatis.annotations.Mapper;
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
|
||||||
|
import cn.rosercode.finance.entity.AiConfig;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* AI 配置Mapper接口,继承MyBatis-Plus的BaseMapper,提供AI配置表的基础CRUD操作。
|
* AI 配置Mapper接口,继承MyBatis-Plus的BaseMapper,提供AI配置表的基础CRUD操作。
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -1,12 +1,13 @@
|
|||||||
package cn.rosercode.finance.mapper;
|
package cn.rosercode.finance.mapper;
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
import cn.rosercode.finance.entity.AiUsage;
|
|
||||||
import cn.rosercode.finance.vo.AiUsageSummaryVO;
|
|
||||||
import org.apache.ibatis.annotations.Mapper;
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
import org.apache.ibatis.annotations.Param;
|
import org.apache.ibatis.annotations.Param;
|
||||||
import org.apache.ibatis.annotations.Select;
|
import org.apache.ibatis.annotations.Select;
|
||||||
|
|
||||||
|
import cn.rosercode.finance.entity.AiUsage;
|
||||||
|
import cn.rosercode.finance.vo.AiUsageSummaryVO;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* AI 使用记录Mapper接口,继承MyBatis-Plus的BaseMapper,并提供汇总统计查询。
|
* AI 使用记录Mapper接口,继承MyBatis-Plus的BaseMapper,并提供汇总统计查询。
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
package cn.rosercode.finance.mapper;
|
package cn.rosercode.finance.mapper;
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
import cn.rosercode.finance.entity.Category;
|
|
||||||
import org.apache.ibatis.annotations.Mapper;
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
|
||||||
|
import cn.rosercode.finance.entity.Category;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 分类Mapper接口,继承MyBatis-Plus的BaseMapper,提供分类表的基础CRUD操作
|
* 分类Mapper接口,继承MyBatis-Plus的BaseMapper,提供分类表的基础CRUD操作
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
package cn.rosercode.finance.mapper;
|
package cn.rosercode.finance.mapper;
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
import cn.rosercode.finance.entity.HttpLog;
|
|
||||||
import org.apache.ibatis.annotations.Mapper;
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
|
||||||
|
import cn.rosercode.finance.entity.HttpLog;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* HTTP 访问日志Mapper接口,继承MyBatis-Plus的BaseMapper,提供访问日志表的基础CRUD操作。
|
* HTTP 访问日志Mapper接口,继承MyBatis-Plus的BaseMapper,提供访问日志表的基础CRUD操作。
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
package cn.rosercode.finance.mapper;
|
package cn.rosercode.finance.mapper;
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
import cn.rosercode.finance.entity.LoginLog;
|
|
||||||
import org.apache.ibatis.annotations.Mapper;
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
|
||||||
|
import cn.rosercode.finance.entity.LoginLog;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 登录日志Mapper接口,继承MyBatis-Plus的BaseMapper,提供登录日志表的基础CRUD操作。
|
* 登录日志Mapper接口,继承MyBatis-Plus的BaseMapper,提供登录日志表的基础CRUD操作。
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
package cn.rosercode.finance.mapper;
|
package cn.rosercode.finance.mapper;
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
import cn.rosercode.finance.entity.NotificationChannel;
|
|
||||||
import org.apache.ibatis.annotations.Mapper;
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
|
||||||
|
import cn.rosercode.finance.entity.NotificationChannel;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 通知渠道Mapper接口,继承MyBatis-Plus的BaseMapper,提供通知渠道表的基础CRUD操作。
|
* 通知渠道Mapper接口,继承MyBatis-Plus的BaseMapper,提供通知渠道表的基础CRUD操作。
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
package cn.rosercode.finance.mapper;
|
package cn.rosercode.finance.mapper;
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
import cn.rosercode.finance.entity.NotificationConfig;
|
|
||||||
import org.apache.ibatis.annotations.Mapper;
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
|
||||||
|
import cn.rosercode.finance.entity.NotificationConfig;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 通知配置Mapper接口,继承MyBatis-Plus的BaseMapper,提供通知配置表的基础CRUD操作。
|
* 通知配置Mapper接口,继承MyBatis-Plus的BaseMapper,提供通知配置表的基础CRUD操作。
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
package cn.rosercode.finance.mapper;
|
package cn.rosercode.finance.mapper;
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
import cn.rosercode.finance.entity.NotificationLog;
|
|
||||||
import org.apache.ibatis.annotations.Mapper;
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
|
||||||
|
import cn.rosercode.finance.entity.NotificationLog;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 通知日志Mapper接口,继承MyBatis-Plus的BaseMapper,提供通知日志表的基础CRUD操作。
|
* 通知日志Mapper接口,继承MyBatis-Plus的BaseMapper,提供通知日志表的基础CRUD操作。
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
package cn.rosercode.finance.mapper;
|
package cn.rosercode.finance.mapper;
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
import cn.rosercode.finance.entity.Rule;
|
|
||||||
import org.apache.ibatis.annotations.Mapper;
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
|
||||||
|
import cn.rosercode.finance.entity.Rule;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 规则Mapper接口,继承MyBatis-Plus的BaseMapper,提供规则表的基础CRUD操作。
|
* 规则Mapper接口,继承MyBatis-Plus的BaseMapper,提供规则表的基础CRUD操作。
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
package cn.rosercode.finance.mapper;
|
package cn.rosercode.finance.mapper;
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
import cn.rosercode.finance.entity.RuleTag;
|
|
||||||
import org.apache.ibatis.annotations.Mapper;
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
|
||||||
|
import cn.rosercode.finance.entity.RuleTag;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 规则标签关联Mapper接口,继承MyBatis-Plus的BaseMapper,提供规则标签关联表的基础CRUD操作。
|
* 规则标签关联Mapper接口,继承MyBatis-Plus的BaseMapper,提供规则标签关联表的基础CRUD操作。
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
package cn.rosercode.finance.mapper;
|
package cn.rosercode.finance.mapper;
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
import cn.rosercode.finance.entity.Tag;
|
|
||||||
import org.apache.ibatis.annotations.Mapper;
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
|
||||||
|
import cn.rosercode.finance.entity.Tag;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 标签Mapper接口,继承MyBatis-Plus的BaseMapper,提供标签表的基础CRUD操作。
|
* 标签Mapper接口,继承MyBatis-Plus的BaseMapper,提供标签表的基础CRUD操作。
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -1,11 +1,12 @@
|
|||||||
package cn.rosercode.finance.mapper;
|
package cn.rosercode.finance.mapper;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
import cn.rosercode.finance.entity.Transaction;
|
|
||||||
import org.apache.ibatis.annotations.Mapper;
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
import org.apache.ibatis.annotations.Param;
|
import org.apache.ibatis.annotations.Param;
|
||||||
|
|
||||||
import java.util.List;
|
import cn.rosercode.finance.entity.Transaction;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 交易记录Mapper接口,继承MyBatis-Plus的BaseMapper,提供交易记录表的基础CRUD操作
|
* 交易记录Mapper接口,继承MyBatis-Plus的BaseMapper,提供交易记录表的基础CRUD操作
|
||||||
|
|||||||
@@ -1,11 +1,12 @@
|
|||||||
package cn.rosercode.finance.mapper;
|
package cn.rosercode.finance.mapper;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
import cn.rosercode.finance.entity.TransactionTag;
|
|
||||||
import org.apache.ibatis.annotations.Mapper;
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
import org.apache.ibatis.annotations.Param;
|
import org.apache.ibatis.annotations.Param;
|
||||||
|
|
||||||
import java.util.List;
|
import cn.rosercode.finance.entity.TransactionTag;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 交易标签关联Mapper接口,继承MyBatis-Plus的BaseMapper,提供关联表的基础CRUD操作。
|
* 交易标签关联Mapper接口,继承MyBatis-Plus的BaseMapper,提供关联表的基础CRUD操作。
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
package cn.rosercode.finance.mapper;
|
package cn.rosercode.finance.mapper;
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
import cn.rosercode.finance.entity.User;
|
|
||||||
import org.apache.ibatis.annotations.Mapper;
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
|
||||||
|
import cn.rosercode.finance.entity.User;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 用户Mapper接口,继承MyBatis-Plus的BaseMapper,提供用户表的基础CRUD操作
|
* 用户Mapper接口,继承MyBatis-Plus的BaseMapper,提供用户表的基础CRUD操作
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -1,9 +1,5 @@
|
|||||||
package cn.rosercode.finance.notification;
|
package cn.rosercode.finance.notification;
|
||||||
|
|
||||||
import cn.rosercode.finance.common.BusinessException;
|
|
||||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.net.URLEncoder;
|
import java.net.URLEncoder;
|
||||||
@@ -14,6 +10,11 @@ import java.nio.charset.StandardCharsets;
|
|||||||
import java.time.Duration;
|
import java.time.Duration;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
|
||||||
|
import cn.rosercode.finance.common.BusinessException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* HTTP 通知发送器抽象基类。
|
* HTTP 通知发送器抽象基类。
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
package cn.rosercode.finance.notification;
|
package cn.rosercode.finance.notification;
|
||||||
|
|
||||||
import cn.rosercode.finance.common.BusinessException;
|
import java.util.Map;
|
||||||
import cn.rosercode.finance.enums.NotificationChannelType;
|
import java.util.Properties;
|
||||||
|
|
||||||
import jakarta.mail.MessagingException;
|
import jakarta.mail.MessagingException;
|
||||||
import jakarta.mail.internet.MimeMessage;
|
import jakarta.mail.internet.MimeMessage;
|
||||||
import org.springframework.mail.MailException;
|
import org.springframework.mail.MailException;
|
||||||
@@ -9,8 +10,8 @@ import org.springframework.mail.javamail.JavaMailSenderImpl;
|
|||||||
import org.springframework.mail.javamail.MimeMessageHelper;
|
import org.springframework.mail.javamail.MimeMessageHelper;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
import java.util.Map;
|
import cn.rosercode.finance.common.BusinessException;
|
||||||
import java.util.Properties;
|
import cn.rosercode.finance.enums.NotificationChannelType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 邮箱通知发送器,通过 SMTP 发送纯文本邮件(兼容 QQ 邮箱)。
|
* 邮箱通知发送器,通过 SMTP 发送纯文本邮件(兼容 QQ 邮箱)。
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
package cn.rosercode.finance.notification;
|
package cn.rosercode.finance.notification;
|
||||||
|
|
||||||
import cn.rosercode.finance.enums.NotificationChannelType;
|
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
import cn.rosercode.finance.enums.NotificationChannelType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 通知发送器接口,定义不同渠道的消息推送能力。
|
* 通知发送器接口,定义不同渠道的消息推送能力。
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -1,13 +1,14 @@
|
|||||||
package cn.rosercode.finance.notification;
|
package cn.rosercode.finance.notification;
|
||||||
|
|
||||||
import cn.rosercode.finance.common.BusinessException;
|
|
||||||
import cn.rosercode.finance.enums.NotificationChannelType;
|
|
||||||
import org.springframework.stereotype.Component;
|
|
||||||
|
|
||||||
import java.util.EnumMap;
|
import java.util.EnumMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import cn.rosercode.finance.common.BusinessException;
|
||||||
|
import cn.rosercode.finance.enums.NotificationChannelType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 通知发送器工厂,按渠道类型分发到对应的发送器实现。
|
* 通知发送器工厂,按渠道类型分发到对应的发送器实现。
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -1,14 +1,15 @@
|
|||||||
package cn.rosercode.finance.notification;
|
package cn.rosercode.finance.notification;
|
||||||
|
|
||||||
import cn.rosercode.finance.common.BusinessException;
|
import java.util.LinkedHashMap;
|
||||||
import cn.rosercode.finance.enums.NotificationChannelType;
|
import java.util.Map;
|
||||||
|
|
||||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||||
import com.fasterxml.jackson.databind.JsonNode;
|
import com.fasterxml.jackson.databind.JsonNode;
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
import java.util.LinkedHashMap;
|
import cn.rosercode.finance.common.BusinessException;
|
||||||
import java.util.Map;
|
import cn.rosercode.finance.enums.NotificationChannelType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Server 酱通知发送器,通过 Server 酱 Turbo 接口将消息推送到个人微信。
|
* Server 酱通知发送器,通过 Server 酱 Turbo 接口将消息推送到个人微信。
|
||||||
|
|||||||
@@ -1,18 +1,18 @@
|
|||||||
package cn.rosercode.finance.scheduler;
|
package cn.rosercode.finance.scheduler;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.scheduling.annotation.Scheduled;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
import cn.rosercode.finance.config.app.AppConfig;
|
import cn.rosercode.finance.config.app.AppConfig;
|
||||||
import cn.rosercode.finance.config.app.AppConfigStore;
|
import cn.rosercode.finance.config.app.AppConfigStore;
|
||||||
import cn.rosercode.finance.entity.HttpLog;
|
import cn.rosercode.finance.entity.HttpLog;
|
||||||
import cn.rosercode.finance.entity.LoginLog;
|
import cn.rosercode.finance.entity.LoginLog;
|
||||||
import cn.rosercode.finance.mapper.HttpLogMapper;
|
import cn.rosercode.finance.mapper.HttpLogMapper;
|
||||||
import cn.rosercode.finance.mapper.LoginLogMapper;
|
import cn.rosercode.finance.mapper.LoginLogMapper;
|
||||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
import org.springframework.scheduling.annotation.Scheduled;
|
|
||||||
import org.springframework.stereotype.Component;
|
|
||||||
|
|
||||||
import java.time.LocalDateTime;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 日志清理调度器。
|
* 日志清理调度器。
|
||||||
@@ -23,10 +23,9 @@ import java.time.LocalDateTime;
|
|||||||
* @date 2026-09-18 17:15:49
|
* @date 2026-09-18 17:15:49
|
||||||
*/
|
*/
|
||||||
@Component
|
@Component
|
||||||
|
@Slf4j
|
||||||
public class LogCleanupScheduler {
|
public class LogCleanupScheduler {
|
||||||
|
|
||||||
private static final Logger log = LoggerFactory.getLogger(LogCleanupScheduler.class);
|
|
||||||
|
|
||||||
private final AppConfigStore appConfigStore;
|
private final AppConfigStore appConfigStore;
|
||||||
private final HttpLogMapper httpLogMapper;
|
private final HttpLogMapper httpLogMapper;
|
||||||
private final LoginLogMapper loginLogMapper;
|
private final LoginLogMapper loginLogMapper;
|
||||||
|
|||||||
@@ -1,17 +1,5 @@
|
|||||||
package cn.rosercode.finance.scheduler;
|
package cn.rosercode.finance.scheduler;
|
||||||
|
|
||||||
import cn.rosercode.finance.entity.NotificationChannel;
|
|
||||||
import cn.rosercode.finance.entity.NotificationConfig;
|
|
||||||
import cn.rosercode.finance.enums.NotificationFrequency;
|
|
||||||
import cn.rosercode.finance.mapper.NotificationConfigMapper;
|
|
||||||
import cn.rosercode.finance.service.NotificationChannelService;
|
|
||||||
import cn.rosercode.finance.service.NotificationService;
|
|
||||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
import org.springframework.scheduling.annotation.Scheduled;
|
|
||||||
import org.springframework.stereotype.Component;
|
|
||||||
|
|
||||||
import java.time.LocalDate;
|
import java.time.LocalDate;
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
import java.time.LocalTime;
|
import java.time.LocalTime;
|
||||||
@@ -19,6 +7,18 @@ import java.time.format.DateTimeFormatter;
|
|||||||
import java.time.format.DateTimeParseException;
|
import java.time.format.DateTimeParseException;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.scheduling.annotation.Scheduled;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import cn.rosercode.finance.entity.NotificationChannel;
|
||||||
|
import cn.rosercode.finance.entity.NotificationConfig;
|
||||||
|
import cn.rosercode.finance.enums.NotificationFrequency;
|
||||||
|
import cn.rosercode.finance.mapper.NotificationConfigMapper;
|
||||||
|
import cn.rosercode.finance.service.NotificationChannelService;
|
||||||
|
import cn.rosercode.finance.service.NotificationService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 通知调度器。
|
* 通知调度器。
|
||||||
*
|
*
|
||||||
@@ -28,10 +28,9 @@ import java.util.List;
|
|||||||
* @date 2026-09-18 12:38:30
|
* @date 2026-09-18 12:38:30
|
||||||
*/
|
*/
|
||||||
@Component
|
@Component
|
||||||
|
@Slf4j
|
||||||
public class NotificationScheduler {
|
public class NotificationScheduler {
|
||||||
|
|
||||||
private static final Logger log = LoggerFactory.getLogger(NotificationScheduler.class);
|
|
||||||
|
|
||||||
/** 时间格式 */
|
/** 时间格式 */
|
||||||
private static final DateTimeFormatter TIME_FORMATTER = DateTimeFormatter.ofPattern("HH:mm");
|
private static final DateTimeFormatter TIME_FORMATTER = DateTimeFormatter.ofPattern("HH:mm");
|
||||||
|
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
package cn.rosercode.finance.service;
|
package cn.rosercode.finance.service;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import cn.rosercode.finance.dto.AiApplyRequest;
|
import cn.rosercode.finance.dto.AiApplyRequest;
|
||||||
import cn.rosercode.finance.dto.AiSuggestOneRequest;
|
import cn.rosercode.finance.dto.AiSuggestOneRequest;
|
||||||
import cn.rosercode.finance.vo.AiSuggestionVO;
|
import cn.rosercode.finance.vo.AiSuggestionVO;
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* AI 建议服务接口,提供交易记录的分类与标签智能建议及应用能力。
|
* AI 建议服务接口,提供交易记录的分类与标签智能建议及应用能力。
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -1,10 +1,5 @@
|
|||||||
package cn.rosercode.finance.service;
|
package cn.rosercode.finance.service;
|
||||||
|
|
||||||
import cn.rosercode.finance.util.AppLogUtils;
|
|
||||||
import jakarta.annotation.PreDestroy;
|
|
||||||
import org.springframework.stereotype.Service;
|
|
||||||
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
|
|
||||||
|
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.RandomAccessFile;
|
import java.io.RandomAccessFile;
|
||||||
@@ -18,6 +13,12 @@ import java.util.concurrent.ScheduledExecutorService;
|
|||||||
import java.util.concurrent.ScheduledFuture;
|
import java.util.concurrent.ScheduledFuture;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
import jakarta.annotation.PreDestroy;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
|
||||||
|
|
||||||
|
import cn.rosercode.finance.util.AppLogUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 应用运行日志实时推送服务。
|
* 应用运行日志实时推送服务。
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
package cn.rosercode.finance.service;
|
package cn.rosercode.finance.service;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
import cn.rosercode.finance.dto.BillImportRequest;
|
import cn.rosercode.finance.dto.BillImportRequest;
|
||||||
import cn.rosercode.finance.enums.BillType;
|
import cn.rosercode.finance.enums.BillType;
|
||||||
import cn.rosercode.finance.vo.BillImportResultVO;
|
import cn.rosercode.finance.vo.BillImportResultVO;
|
||||||
import cn.rosercode.finance.vo.BillParseResultVO;
|
import cn.rosercode.finance.vo.BillParseResultVO;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 账单导入服务,负责「先解析、后导入」两阶段的业务逻辑。
|
* 账单导入服务,负责「先解析、后导入」两阶段的业务逻辑。
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
package cn.rosercode.finance.service;
|
package cn.rosercode.finance.service;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import cn.rosercode.finance.dto.CategoryRequest;
|
import cn.rosercode.finance.dto.CategoryRequest;
|
||||||
import cn.rosercode.finance.vo.CategoryVO;
|
import cn.rosercode.finance.vo.CategoryVO;
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 分类服务接口,提供收支分类的增删改查操作。
|
* 分类服务接口,提供收支分类的增删改查操作。
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
package cn.rosercode.finance.service;
|
package cn.rosercode.finance.service;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import cn.rosercode.finance.dto.NotificationChannelRequest;
|
import cn.rosercode.finance.dto.NotificationChannelRequest;
|
||||||
import cn.rosercode.finance.entity.NotificationChannel;
|
import cn.rosercode.finance.entity.NotificationChannel;
|
||||||
import cn.rosercode.finance.vo.NotificationChannelVO;
|
import cn.rosercode.finance.vo.NotificationChannelVO;
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 通知渠道服务接口,负责用户消息推送渠道的增删改查。
|
* 通知渠道服务接口,负责用户消息推送渠道的增删改查。
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
package cn.rosercode.finance.service;
|
package cn.rosercode.finance.service;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import cn.rosercode.finance.entity.NotificationChannel;
|
import cn.rosercode.finance.entity.NotificationChannel;
|
||||||
import cn.rosercode.finance.vo.NotificationLogVO;
|
import cn.rosercode.finance.vo.NotificationLogVO;
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 通知发送服务接口,负责消息的实际推送与发送日志记录。
|
* 通知发送服务接口,负责消息的实际推送与发送日志记录。
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
package cn.rosercode.finance.service;
|
package cn.rosercode.finance.service;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 规则匹配上下文,承载单条交易的匹配所需信息。
|
* 规则匹配上下文,承载单条交易的匹配所需信息。
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
package cn.rosercode.finance.service;
|
package cn.rosercode.finance.service;
|
||||||
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 规则匹配结果,承载命中规则后建议应用的分类与标签。
|
* 规则匹配结果,承载命中规则后建议应用的分类与标签。
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
package cn.rosercode.finance.service;
|
package cn.rosercode.finance.service;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import cn.rosercode.finance.dto.RuleRequest;
|
import cn.rosercode.finance.dto.RuleRequest;
|
||||||
import cn.rosercode.finance.vo.RuleVO;
|
import cn.rosercode.finance.vo.RuleVO;
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 规则服务,负责自定义分类与标签规则的增删改查及匹配。
|
* 规则服务,负责自定义分类与标签规则的增删改查及匹配。
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
package cn.rosercode.finance.service;
|
package cn.rosercode.finance.service;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import cn.rosercode.finance.dto.StatisticsQuery;
|
import cn.rosercode.finance.dto.StatisticsQuery;
|
||||||
import cn.rosercode.finance.dto.StatisticsRangeQuery;
|
import cn.rosercode.finance.dto.StatisticsRangeQuery;
|
||||||
import cn.rosercode.finance.enums.StatisticsDimension;
|
import cn.rosercode.finance.enums.StatisticsDimension;
|
||||||
@@ -9,8 +11,6 @@ import cn.rosercode.finance.vo.StatisticsGroupVO;
|
|||||||
import cn.rosercode.finance.vo.StatisticsSummaryVO;
|
import cn.rosercode.finance.vo.StatisticsSummaryVO;
|
||||||
import cn.rosercode.finance.vo.TrendStatisticsVO;
|
import cn.rosercode.finance.vo.TrendStatisticsVO;
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 统计服务接口,提供月度收支统计、分类统计和趋势分析功能。
|
* 统计服务接口,提供月度收支统计、分类统计和趋势分析功能。
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
package cn.rosercode.finance.service;
|
package cn.rosercode.finance.service;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import cn.rosercode.finance.dto.TagRequest;
|
import cn.rosercode.finance.dto.TagRequest;
|
||||||
import cn.rosercode.finance.vo.TagVO;
|
import cn.rosercode.finance.vo.TagVO;
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 标签服务接口,提供标签的增删改查操作。
|
* 标签服务接口,提供标签的增删改查操作。
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
package cn.rosercode.finance.service;
|
package cn.rosercode.finance.service;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import cn.rosercode.finance.common.PageResult;
|
import cn.rosercode.finance.common.PageResult;
|
||||||
import cn.rosercode.finance.dto.BatchCategoryRequest;
|
import cn.rosercode.finance.dto.BatchCategoryRequest;
|
||||||
import cn.rosercode.finance.dto.BatchTagRequest;
|
import cn.rosercode.finance.dto.BatchTagRequest;
|
||||||
@@ -8,8 +10,6 @@ import cn.rosercode.finance.dto.TransactionRequest;
|
|||||||
import cn.rosercode.finance.vo.TransactionExportVO;
|
import cn.rosercode.finance.vo.TransactionExportVO;
|
||||||
import cn.rosercode.finance.vo.TransactionVO;
|
import cn.rosercode.finance.vo.TransactionVO;
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 交易记录服务接口,提供收支记录的分页查询、增删改操作。
|
* 交易记录服务接口,提供收支记录的分页查询、增删改操作。
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -1,5 +1,12 @@
|
|||||||
package cn.rosercode.finance.service.impl;
|
package cn.rosercode.finance.service.impl;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||||
|
import com.fasterxml.jackson.databind.JsonNode;
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
import cn.rosercode.finance.client.DeepSeekClient;
|
import cn.rosercode.finance.client.DeepSeekClient;
|
||||||
import cn.rosercode.finance.client.DeepSeekResponse;
|
import cn.rosercode.finance.client.DeepSeekResponse;
|
||||||
import cn.rosercode.finance.common.BusinessException;
|
import cn.rosercode.finance.common.BusinessException;
|
||||||
@@ -9,12 +16,6 @@ import cn.rosercode.finance.service.AiCategoryService;
|
|||||||
import cn.rosercode.finance.service.AiConfigService;
|
import cn.rosercode.finance.service.AiConfigService;
|
||||||
import cn.rosercode.finance.service.AiUsageService;
|
import cn.rosercode.finance.service.AiUsageService;
|
||||||
import cn.rosercode.finance.vo.AiCategoryResultVO;
|
import cn.rosercode.finance.vo.AiCategoryResultVO;
|
||||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
|
||||||
import com.fasterxml.jackson.databind.JsonNode;
|
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
|
||||||
import org.springframework.stereotype.Service;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* AI 生成分类服务实现类,根据自然语言描述生成分类名称、类型与图标。
|
* AI 生成分类服务实现类,根据自然语言描述生成分类名称、类型与图标。
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user