diff --git a/apps/backend/src/services/classification.service.ts b/apps/backend/src/services/classification.service.ts index 1e339c8..177fd24 100644 --- a/apps/backend/src/services/classification.service.ts +++ b/apps/backend/src/services/classification.service.ts @@ -71,14 +71,17 @@ export function extractAmountFromText(title: string, body?: string): number | un const normalized = normalizeText(title, body).toLowerCase(); const sanitized = normalized.replace(/[,,。]/g, ' '); - const amountPatterns = [ + // 金额上下文关键词(没有出现就不要用宽松规则匹配) + const moneyContext = /(金额|人民币|rmb|cny|元|块|圆|收款|到账|入账|转账|支付|扣款|消费|已支付|已扣款|红包|微信支付|支付宝)/i; + + // 严格规则:需要货币符号或金额关键词 + const strictPatterns = [ /(?:¥|¥|\$|人民币|rmb|cny)\s*([-+]?\d+(?:\.\d{1,2})?)/i, /([-+]?\d+(?:\.\d{1,2})?)\s*(?:元|块|圆)/i, - /金额[::]?\s*([-+]?\d+(?:\.\d{1,2})?)/i, - /([-+]?\d+(?:\.\d{1,2})?)(?:\s*(?:元|块|圆))?/i + /金额[::]?\s*([-+]?\d+(?:\.\d{1,2})?)/i ]; - for (const pattern of amountPatterns) { + for (const pattern of strictPatterns) { const match = sanitized.match(pattern); if (match) { const raw = match[1]; @@ -90,5 +93,17 @@ export function extractAmountFromText(title: string, body?: string): number | un } } + // 宽松规则(无货币词的裸数字)仅在上下文包含金钱相关关键词时启用 + if (moneyContext.test(sanitized)) { + const loose = /([-+]?\d+(?:\.\d{1,2})?)/; + const match = sanitized.match(loose); + if (match) { + const parsed = Number.parseFloat(match[1]); + if (!Number.isNaN(parsed)) { + return Math.abs(parsed); + } + } + } + return undefined; }