- 标签:新增 t_tag / t_transaction_tag 表与标签 CRUD,支持交易打标签、按标签筛选、批量添加/移除标签、导入账单默认标签,新增标签管理页 - 账单导入:新增微信支付 xlsx 解析器(WechatBillParser),支持支付宝 / 微信按类型导入;解析行保存原始完整数据(raw_data)并可在列表查看 - 收支记录:排序移至顶部并改为服务端排序(交易时间 / 金额,记忆偏好);筛选条件收纳为「更多筛选」弹层;分类筛选显示图标;一键设置支持「计入统计」;导入预览支持关键字 / 类型 / 状态 / 金额筛选 - 数据库:init.sql 新增 raw_data 字段与标签表,新增 init_tags.sql 默认标签种子 - 其他:更新 README 测试账号
212 lines
9.0 KiB
Java
212 lines
9.0 KiB
Java
package com.example.finance.controller;
|
|
|
|
import com.alibaba.excel.EasyExcel;
|
|
import com.example.finance.common.PageResult;
|
|
import com.example.finance.common.Result;
|
|
import com.example.finance.dto.BatchCategoryRequest;
|
|
import com.example.finance.dto.BatchTagRequest;
|
|
import com.example.finance.dto.TransactionQuery;
|
|
import com.example.finance.dto.TransactionRequest;
|
|
import com.example.finance.service.TransactionService;
|
|
import com.example.finance.vo.TransactionExportVO;
|
|
import com.example.finance.vo.TransactionVO;
|
|
import io.swagger.v3.oas.annotations.Operation;
|
|
import io.swagger.v3.oas.annotations.Parameter;
|
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
|
import jakarta.servlet.http.HttpServletRequest;
|
|
import jakarta.servlet.http.HttpServletResponse;
|
|
import jakarta.validation.Valid;
|
|
import org.springframework.web.bind.annotation.DeleteMapping;
|
|
import org.springframework.web.bind.annotation.GetMapping;
|
|
import org.springframework.web.bind.annotation.PathVariable;
|
|
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.RestController;
|
|
|
|
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;
|
|
|
|
/**
|
|
* 交易记录控制器
|
|
*
|
|
* <p>提供交易记录的分页查询、新增、更新、删除接口</p>
|
|
*/
|
|
@RestController
|
|
@RequestMapping("/api/transaction")
|
|
@Tag(name = "交易记录管理", description = "收支交易记录的增删改查相关接口")
|
|
public class TransactionController {
|
|
|
|
private final TransactionService transactionService;
|
|
|
|
public TransactionController(TransactionService transactionService) {
|
|
this.transactionService = transactionService;
|
|
}
|
|
|
|
/**
|
|
* 分页查询交易记录
|
|
*
|
|
* @param request HTTP请求,从中获取用户ID
|
|
* @param query 分页查询参数
|
|
* @return 分页交易记录列表
|
|
*/
|
|
@GetMapping("/page")
|
|
@Operation(summary = "分页查询交易记录", description = "根据查询条件分页获取当前用户的交易记录")
|
|
public Result<PageResult<TransactionVO>> page(HttpServletRequest request,
|
|
@Parameter(description = "分页查询参数") TransactionQuery query) {
|
|
Long userId = (Long) request.getAttribute("userId");
|
|
return Result.success(transactionService.page(userId, query));
|
|
}
|
|
|
|
/**
|
|
* 新增交易记录
|
|
*
|
|
* @param request HTTP请求,从中获取用户ID
|
|
* @param transactionRequest 交易记录请求参数
|
|
* @return 操作结果
|
|
*/
|
|
@PostMapping
|
|
@Operation(summary = "新增交易记录", description = "为当前用户新增一条交易记录")
|
|
public Result<Void> create(HttpServletRequest request, @RequestBody @Valid TransactionRequest transactionRequest) {
|
|
Long userId = (Long) request.getAttribute("userId");
|
|
transactionService.create(userId, transactionRequest);
|
|
return Result.success();
|
|
}
|
|
|
|
/**
|
|
* 更新交易记录
|
|
*
|
|
* @param request HTTP请求,从中获取用户ID
|
|
* @param id 交易记录ID
|
|
* @param transactionRequest 交易记录请求参数
|
|
* @return 操作结果
|
|
*/
|
|
@PutMapping("/{id}")
|
|
@Operation(summary = "更新交易记录", description = "根据交易记录ID更新交易信息")
|
|
public Result<Void> update(HttpServletRequest request,
|
|
@Parameter(description = "交易记录ID") @PathVariable Long id,
|
|
@RequestBody @Valid TransactionRequest transactionRequest) {
|
|
Long userId = (Long) request.getAttribute("userId");
|
|
transactionService.update(userId, id, transactionRequest);
|
|
return Result.success();
|
|
}
|
|
|
|
/**
|
|
* 删除交易记录
|
|
*
|
|
* @param request HTTP请求,从中获取用户ID
|
|
* @param id 交易记录ID
|
|
* @return 操作结果
|
|
*/
|
|
@DeleteMapping("/{id}")
|
|
@Operation(summary = "删除交易记录", description = "根据交易记录ID删除指定交易记录")
|
|
public Result<Void> delete(HttpServletRequest request,
|
|
@Parameter(description = "交易记录ID") @PathVariable Long id) {
|
|
Long userId = (Long) request.getAttribute("userId");
|
|
transactionService.delete(userId, id);
|
|
return Result.success();
|
|
}
|
|
|
|
/**
|
|
* 切换交易记录的"计入统计"标记
|
|
*
|
|
* @param request HTTP请求,从中获取用户ID
|
|
* @param id 交易记录ID
|
|
* @param body 请求体,包含 includeInStats 字段
|
|
* @return 操作结果
|
|
*/
|
|
@PutMapping("/{id}/stats")
|
|
@Operation(summary = "切换计入统计标记", description = "切换交易记录是否计入统计(用于表格中开关)")
|
|
public Result<Void> toggleStats(HttpServletRequest request,
|
|
@Parameter(description = "交易记录ID") @PathVariable Long id,
|
|
@RequestBody Map<String, Boolean> body) {
|
|
Long userId = (Long) request.getAttribute("userId");
|
|
Boolean includeInStats = body != null ? body.get("includeInStats") : null;
|
|
transactionService.toggleStats(userId, id, includeInStats);
|
|
return Result.success();
|
|
}
|
|
|
|
/**
|
|
* 切换交易记录的备注隐藏标记
|
|
*
|
|
* @param request HTTP请求,从中获取用户ID
|
|
* @param id 交易记录ID
|
|
* @param body 请求体,包含 remarkHidden 字段
|
|
* @return 操作结果
|
|
*/
|
|
@PutMapping("/{id}/remark-hidden")
|
|
@Operation(summary = "切换备注隐藏标记", description = "切换交易记录的备注是否隐藏(用于表格中单元格按钮)")
|
|
public Result<Void> toggleRemarkHidden(HttpServletRequest request,
|
|
@Parameter(description = "交易记录ID") @PathVariable Long id,
|
|
@RequestBody Map<String, Boolean> body) {
|
|
Long userId = (Long) request.getAttribute("userId");
|
|
Boolean remarkHidden = body != null ? body.get("remarkHidden") : null;
|
|
transactionService.toggleRemarkHidden(userId, id, remarkHidden);
|
|
return Result.success();
|
|
}
|
|
|
|
/**
|
|
* 批量设置交易记录的分类
|
|
*
|
|
* @param request HTTP请求,从中获取用户ID
|
|
* @param body 批量设置请求参数
|
|
* @return 实际更新的记录数
|
|
*/
|
|
@PutMapping("/batch-category")
|
|
@Operation(summary = "批量设置分类", description = "将当前表格展示的多条交易记录按类型一键归入所选分类")
|
|
public Result<Integer> batchUpdateCategory(HttpServletRequest request,
|
|
@RequestBody @Valid BatchCategoryRequest body) {
|
|
Long userId = (Long) request.getAttribute("userId");
|
|
return Result.success(transactionService.batchUpdateCategory(userId, body));
|
|
}
|
|
|
|
/**
|
|
* 批量给交易记录添加/移除标签
|
|
*
|
|
* @param request HTTP请求,从中获取用户ID
|
|
* @param body 批量标签请求参数
|
|
* @return 涉及的记录数
|
|
*/
|
|
@PutMapping("/batch-tags")
|
|
@Operation(summary = "批量设置标签", description = "为选中的交易记录添加或移除标签")
|
|
public Result<Integer> batchTags(HttpServletRequest request,
|
|
@RequestBody @Valid BatchTagRequest body) {
|
|
Long userId = (Long) request.getAttribute("userId");
|
|
return Result.success(transactionService.batchTags(userId, body));
|
|
}
|
|
|
|
/**
|
|
* 导出交易记录为 Excel 文件
|
|
*
|
|
* @param request HTTP请求,从中获取用户ID
|
|
* @param response HTTP响应,用于输出文件流
|
|
* @param query 查询条件
|
|
* @throws IOException 文件输出异常
|
|
*/
|
|
@GetMapping("/export")
|
|
@Operation(summary = "导出交易记录", description = "根据查询条件导出交易记录为 Excel 文件")
|
|
public void export(HttpServletRequest request,
|
|
HttpServletResponse response,
|
|
@Parameter(description = "查询条件") TransactionQuery query) throws IOException {
|
|
Long userId = (Long) request.getAttribute("userId");
|
|
|
|
// 设置响应头
|
|
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
|
|
response.setCharacterEncoding("utf-8");
|
|
String fileName = URLEncoder.encode("交易记录_" + LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMdd_HHmmss")), StandardCharsets.UTF_8).replaceAll("\\+", "%20");
|
|
response.setHeader("Content-Disposition", "attachment;filename=" + fileName + ".xlsx");
|
|
|
|
// 查询数据并写入 Excel
|
|
List<TransactionExportVO> data = transactionService.export(userId, query);
|
|
EasyExcel.write(response.getOutputStream(), TransactionExportVO.class)
|
|
.sheet("交易记录")
|
|
.doWrite(data);
|
|
}
|
|
}
|