package service import ( "math" "regexp" "strconv" "time" "xiaji-go/models" "github.com/yanyiwu/gojieba" "gorm.io/gorm" ) type FinanceService struct { db *gorm.DB jieba *gojieba.Jieba } func NewFinanceService(db *gorm.DB) *FinanceService { return &FinanceService{ db: db, jieba: gojieba.NewJieba(), } } func (s *FinanceService) Close() { s.jieba.Free() } // ParseText 从自然语言文本中提取金额(分)和分类 func (s *FinanceService) ParseText(text string) (int64, string) { // 1. 提取金额 — 优先匹配带单位的,如 "15.5元"、"¥30"、"20块" amountPatterns := []*regexp.Regexp{ regexp.MustCompile(`[¥¥]\s*(\d+\.?\d*)`), regexp.MustCompile(`(\d+\.?\d*)\s*[元块]`), } var amountStr string for _, re := range amountPatterns { m := re.FindStringSubmatch(text) if len(m) > 1 { amountStr = m[1] break } } // 兜底:取最后一个独立数字 if amountStr == "" { re := regexp.MustCompile(`(\d+\.?\d*)`) matches := re.FindAllStringSubmatch(text, -1) if len(matches) > 0 { amountStr = matches[len(matches)-1][1] } } if amountStr == "" { return 0, "" } amountFloat, err := strconv.ParseFloat(amountStr, 64) if err != nil || amountFloat <= 0 { return 0, "" } // 转为分 amountCents := int64(math.Round(amountFloat * 100)) // 2. 提取分类(Jieba 分词 + 数据库匹配) words := s.jieba.Cut(text, true) category := "其他" for _, word := range words { var ck models.CategoryKeyword if err := s.db.Where("keyword = ?", word).First(&ck).Error; err == nil { category = ck.Category break } } return amountCents, category } // AddTransaction 解析文本并创建一条交易记录 func (s *FinanceService) AddTransaction(userID int64, text string) (int64, string, error) { amount, category := s.ParseText(text) if amount == 0 { return 0, "", nil } tx := models.Transaction{ UserID: userID, Amount: amount, Category: category, Note: text, Date: time.Now().Format("2006-01-02"), } return amount, category, s.db.Create(&tx).Error } // GetTransactions 获取用户的交易记录 func (s *FinanceService) GetTransactions(userID int64, limit int) ([]models.Transaction, error) { var items []models.Transaction err := s.db.Where("user_id = ? AND is_deleted = ?", userID, false). Order("id desc").Limit(limit).Find(&items).Error return items, err } // GetTransactionsByDate 获取用户指定日期的交易记录 func (s *FinanceService) GetTransactionsByDate(userID int64, date string) ([]models.Transaction, error) { var items []models.Transaction err := s.db.Where("user_id = ? AND date = ? AND is_deleted = ?", userID, date, false). Order("id desc").Find(&items).Error return items, err }