fix: 修复账单删除功能并支持分析页面删除操作
Some checks are pending
Deploy BillAI / Deploy to Production (push) Waiting to run

- 将删除接口从 DELETE /api/bills/:id 改为 POST /api/bills/:id/delete 以兼容 SvelteKit 代理
- 分析页面组件 (TopExpenses/BillRecordsTable/DailyTrendChart) 支持删除并同步更新统计数据
- Review 接口改为直接查询 MongoDB 而非读取文件
- 软删除时记录 updated_at 时间戳
- 添加 .dockerignore 文件优化构建
- 完善 AGENTS.md 文档
This commit is contained in:
clz
2026-02-16 22:28:49 +08:00
parent a5f1a370c7
commit 642ea2d3ef
13 changed files with 277 additions and 151 deletions

View File

@@ -14,7 +14,7 @@ type DeleteBillResponse struct {
Message string `json:"message,omitempty"`
}
// DeleteBill DELETE /api/bills/:id 删除清洗后的账单记录
// DeleteBill POST /api/bills/:id/delete 删除清洗后的账单记录
func DeleteBill(c *gin.Context) {
id := strings.TrimSpace(c.Param("id"))
if id == "" {

View File

@@ -1,61 +1,59 @@
package handler
import (
"fmt"
"net/http"
"os"
"path/filepath"
"strings"
"github.com/gin-gonic/gin"
"billai-server/config"
"billai-server/model"
"billai-server/service"
"billai-server/repository"
)
// Review 获取需要复核的记录
func Review(c *gin.Context) {
// 获取文件名参
fileName := c.Query("file")
if fileName == "" {
c.JSON(http.StatusBadRequest, model.ReviewResponse{
// 获取数
repo := repository.GetRepository()
if repo == nil {
c.JSON(http.StatusInternalServerError, model.ReviewResponse{
Result: false,
Message: "请提供文件名参数 (file)",
Message: "数据库未连接",
})
return
}
// 构建文件路径
outputDirAbs := config.ResolvePath(config.Global.OutputDir)
filePath := filepath.Join(outputDirAbs, fileName)
// 检查文件是否存在
if _, err := os.Stat(filePath); os.IsNotExist(err) {
c.JSON(http.StatusNotFound, model.ReviewResponse{
// 从MongoDB查询所有需要复核的账单
bills, err := repo.GetBillsNeedReview()
if err != nil {
c.JSON(http.StatusInternalServerError, model.ReviewResponse{
Result: false,
Message: "文件不存在: " + fileName,
Message: "查询失败: " + err.Error(),
})
return
}
// 判断文件格式
format := "csv"
if strings.HasSuffix(fileName, ".json") {
format = "json"
}
// 提取需要复核的记录
records := service.ExtractNeedsReview(filePath, format)
// 统计高低优先级数量
// 统计高低优先级数量并转换为 ReviewRecord
highCount := 0
lowCount := 0
for _, r := range records {
if r.ReviewLevel == "HIGH" {
records := make([]model.ReviewRecord, 0, len(bills))
for _, bill := range bills {
if bill.ReviewLevel == "HIGH" {
highCount++
} else if r.ReviewLevel == "LOW" {
} else if bill.ReviewLevel == "LOW" {
lowCount++
}
records = append(records, model.ReviewRecord{
Time: bill.Time.Time().Format("2006-01-02 15:04:05"),
Category: bill.Category,
Merchant: bill.Merchant,
Description: bill.Description,
IncomeExpense: bill.IncomeExpense,
Amount: fmt.Sprintf("%.2f", bill.Amount),
Remark: bill.Remark,
ReviewLevel: bill.ReviewLevel,
})
}
c.JSON(http.StatusOK, model.ReviewResponse{