refactor: 移除AIController中的所有測試和假資料API

- 刪除test/generate測試端點和TestGenerateCards方法
- 刪除test/save測試端點和TestSaveCards方法
- 移除GenerateMockCards假資料生成方法
- 移除TestSaveCardsRequest測試用請求類別
- 清理generate API中的mock邏輯,改為直接錯誤回應
- 提升API安全性,移除無認證的測試端點

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
鄭沛軒 2025-09-21 21:47:26 +08:00
parent 11e19d5e1c
commit be1126e7db
1 changed files with 5 additions and 235 deletions

View File

@ -36,87 +36,6 @@ public class AIController : ControllerBase
_logger = logger;
}
/// <summary>
/// AI 生成詞卡測試端點 (開發用,無需認證)
/// </summary>
[HttpPost("test/generate")]
[AllowAnonymous]
public async Task<ActionResult> TestGenerateCards([FromBody] GenerateCardsRequest request)
{
try
{
// 基本驗證
if (string.IsNullOrWhiteSpace(request.InputText))
{
return BadRequest(new { Success = false, Error = "Input text is required" });
}
if (request.InputText.Length > 5000)
{
return BadRequest(new { Success = false, Error = "Input text must be less than 5000 characters" });
}
if (!new[] { "vocabulary", "smart" }.Contains(request.ExtractionType))
{
return BadRequest(new { Success = false, Error = "Invalid extraction type" });
}
if (request.CardCount < 1 || request.CardCount > 20)
{
return BadRequest(new { Success = false, Error = "Card count must be between 1 and 20" });
}
// 測試模式:直接使用模擬資料
try
{
var generatedCards = await _geminiService.GenerateCardsAsync(
request.InputText,
request.ExtractionType,
request.CardCount);
return Ok(new
{
Success = true,
Data = new
{
TaskId = Guid.NewGuid(),
Status = "completed",
GeneratedCards = generatedCards
},
Message = $"Successfully generated {generatedCards.Count} cards"
});
}
catch (InvalidOperationException ex) when (ex.Message.Contains("API key"))
{
_logger.LogWarning("Gemini API key not configured, using mock data");
// 返回模擬資料
var mockCards = GenerateMockCards(request.CardCount);
return Ok(new
{
Success = true,
Data = new
{
TaskId = Guid.NewGuid(),
Status = "completed",
GeneratedCards = mockCards
},
Message = $"Generated {mockCards.Count} mock cards (Test mode)"
});
}
}
catch (Exception ex)
{
_logger.LogError(ex, "Error in AI card generation test");
return StatusCode(500, new
{
Success = false,
Error = "Failed to generate cards",
Details = ex.Message,
Timestamp = DateTime.UtcNow
});
}
}
/// <summary>
/// AI 生成詞卡 (支援 /frontend/app/generate/page.tsx)
@ -215,20 +134,12 @@ public class AIController : ControllerBase
}
catch (InvalidOperationException ex) when (ex.Message.Contains("API key"))
{
_logger.LogWarning("Gemini API key not configured, using mock data");
// 返回模擬資料(開發階段)
var mockCards = GenerateMockCards(request.CardCount);
return Ok(new
_logger.LogError("Gemini API key not configured");
return StatusCode(500, new
{
Success = true,
Data = new
{
TaskId = Guid.NewGuid(),
Status = "completed",
GeneratedCards = mockCards
},
Message = $"Generated {mockCards.Count} mock cards (Gemini API not configured)"
Success = false,
Error = "AI service not configured",
Timestamp = DateTime.UtcNow
});
}
}
@ -244,99 +155,6 @@ public class AIController : ControllerBase
}
}
/// <summary>
/// 測試版保存生成的詞卡 (無需認證)
/// </summary>
[HttpPost("test/save")]
[AllowAnonymous]
public async Task<ActionResult> TestSaveCards([FromBody] TestSaveCardsRequest request)
{
try
{
// 基本驗證
if (request.SelectedCards == null || request.SelectedCards.Count == 0)
{
return BadRequest(new { Success = false, Error = "Selected cards are required" });
}
// 創建或使用預設卡組
var defaultCardSet = await _context.CardSets
.FirstOrDefaultAsync(cs => cs.IsDefault);
if (defaultCardSet == null)
{
// 創建預設卡組
defaultCardSet = new CardSet
{
Id = Guid.NewGuid(),
UserId = Guid.NewGuid(), // 測試用戶 ID
Name = "AI 生成詞卡",
Description = "通過 AI 智能生成的詞卡集合",
Color = "#3B82F6",
IsDefault = true,
CreatedAt = DateTime.UtcNow,
UpdatedAt = DateTime.UtcNow
};
_context.CardSets.Add(defaultCardSet);
}
// 將生成的詞卡轉換為資料庫實體
var flashcardsToSave = request.SelectedCards.Select(card => new Flashcard
{
Id = Guid.NewGuid(),
UserId = defaultCardSet.UserId,
CardSetId = defaultCardSet.Id,
Word = card.Word,
Translation = card.Translation,
Definition = card.Definition,
PartOfSpeech = card.PartOfSpeech,
Pronunciation = card.Pronunciation,
Example = card.Example,
ExampleTranslation = card.ExampleTranslation,
DifficultyLevel = card.DifficultyLevel,
CreatedAt = DateTime.UtcNow,
UpdatedAt = DateTime.UtcNow
}).ToList();
_context.Flashcards.AddRange(flashcardsToSave);
// 更新卡組計數
defaultCardSet.CardCount += flashcardsToSave.Count;
defaultCardSet.UpdatedAt = DateTime.UtcNow;
await _context.SaveChangesAsync();
return Ok(new
{
Success = true,
Data = new
{
SavedCount = flashcardsToSave.Count,
CardSetId = defaultCardSet.Id,
CardSetName = defaultCardSet.Name,
Cards = flashcardsToSave.Select(f => new
{
f.Id,
f.Word,
f.Translation,
f.Definition
})
},
Message = $"Successfully saved {flashcardsToSave.Count} cards to deck '{defaultCardSet.Name}'"
});
}
catch (Exception ex)
{
_logger.LogError(ex, "Error saving generated cards");
return StatusCode(500, new
{
Success = false,
Error = "Failed to save cards",
Details = ex.Message,
Timestamp = DateTime.UtcNow
});
}
}
/// <summary>
/// 保存生成的詞卡
@ -1417,50 +1235,6 @@ public class AIController : ControllerBase
#endregion
/// <summary>
/// 生成模擬資料 (開發階段使用)
/// </summary>
private List<GeneratedCard> GenerateMockCards(int count)
{
var mockCards = new List<GeneratedCard>
{
new() {
Word = "accomplish",
PartOfSpeech = "verb",
Pronunciation = "/əˈkʌmplɪʃ/",
Translation = "完成、達成",
Definition = "To finish something successfully or to achieve something",
Synonyms = new() { "achieve", "complete" },
Example = "She accomplished her goal of learning English.",
ExampleTranslation = "她達成了學習英語的目標。",
DifficultyLevel = "B1"
},
new() {
Word = "negotiate",
PartOfSpeech = "verb",
Pronunciation = "/nɪˈɡəʊʃieɪt/",
Translation = "協商、談判",
Definition = "To discuss something with someone in order to reach an agreement",
Synonyms = new() { "bargain", "discuss" },
Example = "We need to negotiate a better deal.",
ExampleTranslation = "我們需要協商一個更好的交易。",
DifficultyLevel = "B2"
},
new() {
Word = "perspective",
PartOfSpeech = "noun",
Pronunciation = "/pərˈspektɪv/",
Translation = "觀點、看法",
Definition = "A particular way of considering something",
Synonyms = new() { "viewpoint", "opinion" },
Example = "From my perspective, this is the best solution.",
ExampleTranslation = "從我的觀點來看,這是最好的解決方案。",
DifficultyLevel = "B2"
}
};
return mockCards.Take(Math.Min(count, mockCards.Count)).ToList();
}
}
// Request DTOs
@ -1483,10 +1257,6 @@ public class ValidateCardRequest
public Guid? ErrorReportId { get; set; }
}
public class TestSaveCardsRequest
{
public List<GeneratedCard> SelectedCards { get; set; } = new();
}
// 新增的API請求/響應 DTOs
public class AnalyzeSentenceRequest