feat: Refactor transaction handling and add new features

- Updated ReasonGroupList.vue to modify classify button behavior for adding new classifications.
- Refactored TransactionDetail.vue to integrate PopupContainer and enhance transaction detail display.
- Improved TransactionDetailDialog.vue with updated classify button functionality.
- Simplified BalanceView.vue by removing manual entry button.
- Enhanced PeriodicRecord.vue to update classify button interactions.
- Removed unused add transaction dialog from TransactionsRecord.vue.
- Added new API endpoints in TransactionRecordController for parsing transactions and handling offsets.
- Introduced BillForm.vue and ManualBillAdd.vue for streamlined bill entry.
- Implemented OneLineBillAdd.vue for intelligent transaction parsing.
- Created GlobalAddBill.vue for a unified bill addition interface.
This commit is contained in:
2026-01-01 14:43:43 +08:00
parent 8dfe7f1688
commit e00b5cffb7
18 changed files with 977 additions and 384 deletions

View File

@@ -5,6 +5,8 @@ public interface ISmartHandleService
Task SmartClassifyAsync(long[] transactionIds, Action<(string type, string data)> chunkAction);
Task AnalyzeBillAsync(string userInput, Action<string> chunkAction);
Task<TransactionParseResult?> ParseOneLineBillAsync(string text);
}
public class SmartHandleService(
@@ -419,6 +421,41 @@ public class SmartHandleService(
_ => "未知"
};
}
public async Task<TransactionParseResult?> ParseOneLineBillAsync(string text)
{
// 获取所有分类
var categories = await categoryRepository.GetAllAsync();
var categoryList = string.Join("、", categories.Select(c => $"{GetTypeName(c.Type)}-{c.Name}"));
var sysPrompt = $"""
你是一个智能账单解析助手。请从用户提供的文本中提取交易信息,包括日期、金额、摘要、类型和分类。
请返回 JSON 格式,包含以下字段:
- OccurredAt: 日期时间,格式 yyyy-MM-dd HH:mm:ss。当前系统时间为{DateTime.Now:yyyy-MM-dd HH:mm:ss}。
- Amount: 金额,数字。
- Reason: 备注/摘要,原文或其他补充信息。
- Type: 交易类型0=支出1=收入2=不计入收支。根据语义判断。
- Classify: 分类,请从以下现有分类中选择最匹配的一个:{categoryList}。如果无法匹配,请返回""其他""。
只返回 JSON不要包含 markdown 标记。
""";
var json = await openAiService.ChatAsync(sysPrompt, text);
if (string.IsNullOrWhiteSpace(json)) return null;
try
{
// 清理可能的 markdown 标记
json = json.Replace("```json", "").Replace("```", "").Trim();
var options = new JsonSerializerOptions { PropertyNameCaseInsensitive = true };
return JsonSerializer.Deserialize<TransactionParseResult>(json, options);
}
catch (Exception ex)
{
logger.LogError(ex, "解析账单失败");
return null;
}
}
}
/// <summary>
@@ -435,3 +472,5 @@ public record GroupClassifyResult
[JsonPropertyName("type")]
public TransactionType Type { get; set; }
}
public record TransactionParseResult(string OccurredAt, string Classify, decimal Amount, string Reason, TransactionType Type);