# 互動式單字查詢功能設計規格書 ## 1. 功能概述 ### 1.1 目標 實現低成本、高效率的互動式單字查詢系統,讓用戶能夠點擊句子中的任何單字即時查看詳細意思,同時智能識別片語和俚語。 ### 1.2 核心優勢 - **成本效益**:一次 API 調用,多次查詢零成本 - **即時響應**:點擊查詢無延遲 - **智能識別**:片語/俚語優先顯示和警告 - **用戶友善**:視覺化高亮和直觀操作 ## 2. 系統架構設計 ### 2.1 整體流程 ``` 用戶輸入句子 → AI 預分析 → 高價值標記 → 分析結果快取 → 互動式顯示 → 點擊查詢 ↓ ↓ ↓ ↓ ↓ ↓ 50字限制 一次API調用 識別學習價值 24小時快取 可點擊文字 智能計費 (扣除1次) 重要詞彙 存儲詳情 不同顏色 高價值免費 低價值收費 ``` ### 2.2 API 架構 #### 2.2.1 句子分析 API ``` POST /api/ai/analyze-sentence Content-Type: application/json Request: { "inputText": "He brought this thing up during our meeting and no one agreed.", "userId": "uuid", // 用於使用次數統計 "forceRefresh": false, // 是否強制重新分析 "analysisMode": "full" // full: 完整分析並標記高價值詞彙 } Response: { "success": true, "data": { "analysisId": "uuid", "sentenceMeaning": { "translation": "他在我們的會議中提出了這件事,但沒有人同意。", "explanation": "這句話表達了在會議中有人提出某個議題或想法,但得不到其他與會者的認同。" }, "grammarCorrection": { "hasErrors": false, // 是否有語法錯誤 "originalText": "He brought this thing up during our meeting and no one agreed.", "correctedText": null, // 如無錯誤則為null "corrections": [] // 錯誤修正列表 }, "wordAnalysis": { "brought": { "word": "brought", "translation": "帶來、提出", "definition": "Past tense of bring; to take or carry something to a place", "partOfSpeech": "verb", "pronunciation": { "ipa": "/brɔːt/", "us": "/brɔːt/", "uk": "/brɔːt/" }, "synonyms": ["carried", "took", "delivered"], "antonyms": ["removed", "took away"], "isPhrase": true, "isHighValue": true, // 高學習價值標記 "learningPriority": "high", // high, medium, low "phraseInfo": { "phrase": "bring up", "meaning": "提出(話題)、養育", "warning": "在這個句子中,\"brought up\" 是片語,意思是\"提出話題\",而不是單純的\"帶來\"", "colorCode": "#F59E0B" // 片語顏色代碼 }, "examples": { "original": "He brought this thing up during our meeting", "originalTranslation": "他在會議中提出了這件事", "generated": "She brought up an interesting point", "generatedTranslation": "她提出了一個有趣的觀點", "imageUrl": "/images/examples/bring_up.png", "audioUrl": "/audio/examples/bring_up.mp3" }, "difficultyLevel": "B1" } }, "finalAnalysisText": "He brought this thing up during our meeting and no one agreed.", // 最終用於學習的文本(修正後) "highValueWords": ["brought", "up", "meeting"], // 高價值詞彙列表 "phrasesDetected": [ { "phrase": "bring up", "words": ["brought", "up"], "colorCode": "#F59E0B" } ], "usageStatistics": { "remainingAnalyses": 4, "resetTime": "2025-09-17T12:48:00Z", "costIncurred": 1 // 本次分析扣除次數 }, "cachedUntil": "2025-09-18T09:48:00Z" }, "message": "Sentence analyzed successfully" } ``` #### 2.2.2 單字點擊查詢 API ``` POST /api/ai/query-word Content-Type: application/json Request: { "word": "thing", "sentence": "He brought this thing up during our meeting and no one agreed.", "analysisId": "uuid", // 來自預分析結果 "userId": "uuid" } Response: { "success": true, "data": { "word": "thing", "isHighValue": false, // 非高價值詞彙 "wasPreAnalyzed": false, // 未在預分析中 "costIncurred": 1, // 扣除1次使用次數 "analysis": { // 完整詞彙分析資料 } } } ``` #### 2.2.3 快取管理 API ``` GET /api/ai/analysis-cache/{inputTextHash} DELETE /api/ai/analysis-cache/{analysisId} ``` ### 2.3 資料庫設計 #### 2.3.1 句子分析快取表 ```sql CREATE TABLE SentenceAnalysisCache ( Id UNIQUEIDENTIFIER PRIMARY KEY, InputTextHash NVARCHAR(64) NOT NULL, -- SHA256 hash InputText NVARCHAR(1000) NOT NULL, CorrectedText NVARCHAR(1000), -- 修正後的文本 HasGrammarErrors BIT DEFAULT 0, -- 是否有語法錯誤 GrammarCorrections NVARCHAR(MAX), -- JSON 格式,語法修正詳情 AnalysisResult NVARCHAR(MAX) NOT NULL, -- JSON 格式 HighValueWords NVARCHAR(MAX) NOT NULL, -- JSON 格式,高價值詞彙列表 PhrasesDetected NVARCHAR(MAX), -- JSON 格式,檢測到的片語 CreatedAt DATETIME2 NOT NULL, ExpiresAt DATETIME2 NOT NULL, AccessCount INT DEFAULT 0, LastAccessedAt DATETIME2 ); CREATE INDEX IX_SentenceAnalysisCache_Hash ON SentenceAnalysisCache(InputTextHash); CREATE INDEX IX_SentenceAnalysisCache_Expires ON SentenceAnalysisCache(ExpiresAt); ``` #### 2.3.2 使用統計表 ```sql CREATE TABLE WordQueryUsageStats ( Id UNIQUEIDENTIFIER PRIMARY KEY, UserId UNIQUEIDENTIFIER NOT NULL, Date DATE NOT NULL, SentenceAnalysisCount INT DEFAULT 0, -- 句子分析次數 HighValueWordClicks INT DEFAULT 0, -- 高價值詞彙點擊(免費) LowValueWordClicks INT DEFAULT 0, -- 低價值詞彙點擊(收費) TotalApiCalls INT DEFAULT 0, -- 總 API 調用次數 UniqueWordsQueried INT DEFAULT 0, CreatedAt DATETIME2 NOT NULL, UpdatedAt DATETIME2 NOT NULL ); CREATE UNIQUE INDEX IX_WordQueryUsageStats_UserDate ON WordQueryUsageStats(UserId, Date); ``` ## 3. 前端組件設計 ### 3.1 主要組件架構 ``` WordQueryPage ├── SentenceInputForm // 句子輸入表單 ├── AnalysisLoadingState // 分析中狀態 ├── GrammarCorrectionPanel // 語法修正面板 │ ├── ErrorHighlight // 錯誤標記顯示 │ ├── CorrectionSuggestion // 修正建議 │ └── UserChoiceButtons // 用戶選擇按鈕 ├── InteractiveTextDisplay // 互動式文字顯示 │ ├── ClickableWord // 可點擊單字 │ └── WordInfoPopup // 單字資訊彈窗 ├── UsageStatistics // 使用統計顯示 └── ActionButtons // 操作按鈕組 ``` ### 3.2 組件詳細設計 #### 3.2.1 GrammarCorrectionPanel 組件 ```typescript interface GrammarCorrection { hasErrors: boolean; originalText: string; correctedText: string | null; corrections: Array<{ position: { start: number; end: number }; errorType: string; original: string; corrected: string; reason: string; severity: 'high' | 'medium' | 'low'; }>; confidenceScore: number; } interface GrammarCorrectionPanelProps { correction: GrammarCorrection; onAcceptCorrection: () => void; onRejectCorrection: () => void; onManualEdit: (text: string) => void; } const GrammarCorrectionPanel: React.FC = ({ correction, onAcceptCorrection, onRejectCorrection, onManualEdit }) => { // 錯誤高亮顯示 // 修正建議卡片 // 修正原因說明 // 用戶選擇按鈕 }; ``` #### 3.2.2 SentenceInputForm 組件 ```typescript interface SentenceInputFormProps { maxLength: number; // 300 for manual input onSubmit: (text: string) => void; onModeChange: (mode: 'manual' | 'screenshot') => void; disabled: boolean; remainingAnalyses: number; } const SentenceInputForm: React.FC = ({ maxLength, onSubmit, onModeChange, disabled, remainingAnalyses }) => { // 即時字數統計 // 300字限制阻擋 // 模式切換UI // 示例句子填入 // 分析按鈕狀態 }; ``` #### 3.2.3 InteractiveTextDisplay 組件 ```typescript interface WordAnalysis { word: string; translation: string; definition: string; partOfSpeech: string; pronunciation: { ipa: string; us: string; uk: string; }; synonyms: string[]; antonyms: string[]; isPhrase: boolean; isHighValue: boolean; // 高學習價值標記 learningPriority: 'high' | 'medium' | 'low'; // 學習優先級 phraseInfo?: { phrase: string; meaning: string; warning: string; colorCode: string; // 片語顏色代碼 }; examples: { original: string; originalTranslation: string; generated: string; generatedTranslation: string; imageUrl?: string; audioUrl?: string; }; difficultyLevel: string; } interface InteractiveTextDisplayProps { text: string; analysis: Record; onWordClick: (word: string, analysis: WordAnalysis) => void; } ``` #### 3.2.4 WordInfoPopup 組件 ```typescript interface WordInfoPopupProps { word: string; analysis: WordAnalysis; position: { x: number; y: number }; onClose: () => void; onPlayAudio: (audioUrl: string) => void; } const WordInfoPopup: React.FC = ({ word, analysis, position, onClose, onPlayAudio }) => { // 片語警告顯示 // 發音播放按鈕 // 例句圖片顯示 // 同義詞/反義詞標籤 // 難度等級標示 }; ``` ## 4. 用戶介面設計 ### 4.1 頁面佈局 #### 4.1.1 輸入階段 ``` ┌─────────────────────────────────────────────────────────┐ │ DramaLing │ ├─────────────────────────────────────────────────────────┤ │ AI 智能生成詞卡 - 互動式單字查詢 │ │ │ │ ┌─ 原始例句類型 ──────────────────────────────────┐ │ │ │ [✍️ 手動輸入] [📷 影劇截圖] (訂閱功能) │ │ │ └───────────────────────────────────────────────────┘ │ │ │ │ ┌─ 輸入英文文本 ──────────────────────────────────┐ │ │ │ ┌─────────────────────────────────────────────┐ │ │ │ │ │ 輸入英文句子(最多50字)... │ │ │ │ │ │ │ │ │ │ │ └─────────────────────────────────────────────┘ │ │ │ │ 最多 50 字元 • 目前:0 字元 │ │ │ │ │ │ │ │ 💡 示例句子: │ │ │ │ [點擊使用示例:He brought this thing up...] │ │ │ └───────────────────────────────────────────────────┘ │ │ │ │ ┌─────────────────────────────────────────────────┐ │ │ │ 🔍 分析句子(點擊查詢單字) │ │ │ └─────────────────────────────────────────────────┘ │ │ │ │ 免費用戶:已使用 0/5 次 (3小時內) │ └─────────────────────────────────────────────────────────┘ ``` #### 4.1.2 分析結果階段 ``` ┌─────────────────────────────────────────────────────────┐ │ ← 返回 句子分析結果 │ ├─────────────────────────────────────────────────────────┤ │ ┌─ 原始句子 ──────────────────────────────────────┐ │ │ │ He brought this thing up during our meeting. │ │ │ │ │ │ │ │ 整句意思: │ │ │ │ 他在我們的會議中提出了這件事,但沒有人同意... │ │ │ └───────────────────────────────────────────────────┘ │ │ │ │ ┌─ 點擊查詢單字意思 ──────────────────────────────┐ │ │ │ 💡 使用說明:點擊下方句子中的任何單字,可以立即 │ │ │ │ 查看詳細意思。黃色背景表示該單字屬於片語或俚語。 │ │ │ │ │ │ │ │ ╔═══════════════════════════════════════════╗ │ │ │ │ ║ He [brought] this [thing] [up] during ║ │ │ │ │ ║ our [meeting] and no one [agreed]. ║ │ │ │ │ ╚═══════════════════════════════════════════╝ │ │ │ │ // brought 和 up 有黃色背景 │ │ │ │ // 其他單字有藍色下劃線 │ │ │ └───────────────────────────────────────────────────┘ │ │ │ │ ┌─────────────────────────────────────────────────┐ │ │ │ [🔄 分析新句子] [📖 生成詞卡] │ │ │ └─────────────────────────────────────────────────┘ │ └─────────────────────────────────────────────────────────┘ ``` #### 4.1.3 單字彈窗設計 ``` ┌─ brought ─────────────────── × ┐ │ │ │ ⚠️ 注意:這個單字屬於片語 │ │ 片語:bring up │ │ 意思:提出(話題)、養育 │ │ │ │ verb | /brɔːt/ | 🔊 │ │ │ │ 翻譯:帶來、提出 │ │ │ │ 定義:Past tense of bring; │ │ to take or carry something │ │ │ │ 同義詞:[carried] [took] │ │ 反義詞:[removed] │ │ │ │ 例句: │ │ • 原始:He brought this... │ │ 翻譯:他提出了這件事... │ │ • 生成:She brought up... │ │ 翻譯:她提出了一個... │ │ [📷 查看例句圖] [🔊 播放] │ │ │ │ 難度:B1 │ └───────────────────────────────┘ ``` ### 4.2 視覺設計規範 #### 4.2.1 顏色系統 ```css /* 主色彩 */ --primary-blue: #3B82F6; --primary-blue-hover: #2563EB; --primary-blue-light: #DBEAFE; /* 單字價值顏色系統 */ --word-high-phrase: #F59E0B; /* 高價值片語 */ --word-high-single: #10B981; /* 高價值單字 */ --word-normal: #3B82F6; /* 普通單字 */ --word-hover: #1E40AF; /* 懸停狀態 */ /* 背景顏色 */ --word-high-phrase-bg: #FEF3C7; /* 高價值片語背景 */ --word-high-single-bg: #ECFDF5; /* 高價值單字背景 */ --word-normal-bg: transparent; /* 普通單字背景 */ --word-hover-bg: #DBEAFE; /* 懸停背景 */ /* 邊框顏色 */ --border-high-phrase: #F59E0B; /* 高價值片語邊框 */ --border-high-single: #10B981; /* 高價值單字邊框 */ --border-normal: #3B82F6; /* 普通單字邊框 */ /* 狀態顏色 */ --success: #10B981; --warning: #F59E0B; --error: #EF4444; --info: #3B82F6; --premium: #8B5CF6; /* 付費功能 */ ``` #### 4.2.2 互動效果 ```css /* 可點擊單字基礎樣式 */ .clickable-word { cursor: pointer; transition: all 0.2s ease; padding: 2px 4px; border-radius: 4px; margin: 0 1px; position: relative; } /* 高價值片語樣式 */ .clickable-word.high-value.phrase { background-color: var(--word-high-phrase-bg); border: 2px solid var(--border-high-phrase); } .clickable-word.high-value.phrase::after { content: "⭐"; position: absolute; top: -8px; right: -8px; font-size: 12px; } /* 高價值單字樣式 */ .clickable-word.high-value.single { background-color: var(--word-high-single-bg); border: 2px solid var(--border-high-single); } .clickable-word.high-value.single::after { content: "⭐"; position: absolute; top: -8px; right: -8px; font-size: 12px; } /* 普通單字樣式 */ .clickable-word.normal { border-bottom: 1px solid var(--border-normal); } /* 懸停效果 */ .clickable-word:hover { background-color: var(--word-hover-bg); transform: translateY(-1px); } ``` #### 4.2.3 彈窗動畫 ```css /* 彈窗進入動畫 */ @keyframes popup-enter { from { opacity: 0; transform: translate(-50%, -100%) scale(0.9); } to { opacity: 1; transform: translate(-50%, -100%) scale(1); } } .word-popup { animation: popup-enter 0.2s ease-out; } ``` ## 5. 技術實現細節 ### 5.1 前端狀態管理 #### 5.1.1 Zustand Store 設計 ```typescript interface WordQueryStore { // 分析狀態 isAnalyzing: boolean; analysisResult: SentenceAnalysis | null; analysisError: string | null; // 互動狀態 selectedWord: string | null; popupPosition: { x: number; y: number } | null; // 使用統計 usageStats: { remainingAnalyses: number; resetTime: string; }; // 快取 analysisCache: Map; // Actions analyzeSentence: (text: string) => Promise; selectWord: (word: string, position: { x: number; y: number }) => void; closeWordPopup: () => void; clearCache: () => void; } ``` #### 5.1.2 快取策略 ```typescript // 本地快取實現 class AnalysisCache { private cache = new Map(); get(textHash: string): SentenceAnalysis | null { const item = this.cache.get(textHash); if (!item || this.isExpired(item)) { this.cache.delete(textHash); return null; } return item.data; } set(textHash: string, data: SentenceAnalysis, ttl: number): void { this.cache.set(textHash, { data, expiresAt: Date.now() + ttl }); } private isExpired(item: CacheItem): boolean { return Date.now() > item.expiresAt; } } ``` ### 5.2 後端實現細節 #### 5.2.1 句子分析服務 ```csharp public class SentenceAnalysisService : ISentenceAnalysisService { private readonly IGeminiService _geminiService; private readonly IAnalysisCacheService _cacheService; private readonly IUsageTrackingService _usageService; public async Task AnalyzeSentenceAsync( string inputText, Guid userId, bool forceRefresh = false) { // 1. 檢查使用限制 await _usageService.CheckUsageLimitAsync(userId); // 2. 檢查快取 var textHash = GenerateTextHash(inputText); if (!forceRefresh) { var cached = await _cacheService.GetAsync(textHash); if (cached != null) { await _usageService.RecordCacheHitAsync(userId); return cached; } } // 3. AI 分析 var analysis = await _geminiService.AnalyzeSentenceAsync(inputText); // 4. 存入快取 await _cacheService.SetAsync(textHash, analysis, TimeSpan.FromHours(24)); // 5. 記錄使用 await _usageService.RecordAnalysisAsync(userId); return analysis; } } ``` #### 5.2.2 Gemini Prompt 設計 ```csharp private const string SENTENCE_ANALYSIS_PROMPT = @" 請分析以下英文句子,先檢查語法錯誤並修正,然後提供完整的單字和片語解析: 句子:{inputText} 請按照以下 JSON 格式回應: { ""grammarCorrection"": { ""hasErrors"": true/false, ""originalText"": ""原始輸入句子"", ""correctedText"": ""修正後句子"" // 如無錯誤則與原始相同, ""corrections"": [ { ""position"": {""start"": 2, ""end"": 4}, ""errorType"": ""tense_mismatch"", ""original"": ""錯誤詞彙"", ""corrected"": ""修正詞彙"", ""reason"": ""修正原因說明"", ""severity"": ""high/medium/low"" } ], ""confidenceScore"": 0.95 }, ""sentenceMeaning"": { ""translation"": ""整句的繁體中文意思"", ""explanation"": ""詳細解釋"" }, ""finalAnalysisText"": ""用於後續分析的最終文本(修正後)"", ""wordAnalysis"": { ""單字原形"": { ""word"": ""單字原形"", ""translation"": ""繁體中文翻譯"", ""definition"": ""英文定義(A1-A2程度)"", ""partOfSpeech"": ""詞性(noun/verb/adjective/adverb/pronoun/preposition/conjunction/interjection)"", ""pronunciation"": { ""ipa"": ""IPA音標"", ""us"": ""美式音標"", ""uk"": ""英式音標"" }, ""synonyms"": [""同義詞1"", ""同義詞2"", ""同義詞3""], ""antonyms"": [""反義詞1"", ""反義詞2""], ""isPhrase"": true/false, ""phraseInfo"": { ""phrase"": ""完整片語"", ""meaning"": ""片語意思"", ""warning"": ""警告說明"" }, ""examples"": { ""original"": ""來自原句的例句"", ""originalTranslation"": ""原句例句翻譯"", ""generated"": ""AI生成的新例句"", ""generatedTranslation"": ""新例句翻譯"" }, ""difficultyLevel"": ""CEFR等級(A1/A2/B1/B2/C1/C2)"" } } } 分析要求: 1. **首要任務:語法檢查和修正** - 檢測語法、拼寫、時態、介詞、詞序錯誤 - 提供修正建議和詳細說明 - 後續分析基於修正後的句子進行 - 保持原句意思不變 2. 識別所有有意義的單字(忽略 a, an, the 等功能詞) 3. **重點:標記高學習價值詞彙** - 片語和俚語:isHighValue: true, learningPriority: "high" - 中級以上單字(B1+):isHighValue: true, learningPriority: "high" - 專業術語:isHighValue: true, learningPriority: "medium" - 基礎功能詞:isHighValue: false, learningPriority: "low" 4. 特別注意片語和俚語,設定 isPhrase: true 5. 為片語提供警告說明和顏色代碼 6. 英文定義保持在 A1-A2 程度 7. 提供實用的同義詞和反義詞(如適用) 8. 例句要清楚展示單字用法 9. 準確標記 CEFR 難度等級 10. **優先處理高價值詞彙**:為高價值詞彙生成完整內容詳情 "; ``` ## 6. 性能優化策略 ### 6.1 前端優化 #### 6.1.1 組件懶加載 ```typescript // 懶加載重型組件 const WordInfoPopup = lazy(() => import('./WordInfoPopup')); const ExampleImageViewer = lazy(() => import('./ExampleImageViewer')); // 使用 Suspense 包裝 }> ``` #### 6.1.2 虛擬化長文本 ```typescript // 對於長句子使用虛擬化渲染 const VirtualizedText = ({ words, analysis, onWordClick }) => { const [visibleRange, setVisibleRange] = useState({ start: 0, end: 50 }); return (
{words.slice(visibleRange.start, visibleRange.end).map((word, index) => ( ))}
); }; ``` ### 6.2 後端優化 #### 6.2.1 快取層次設計 ``` L1: 記憶體快取 (Redis) - 1小時 TTL L2: 資料庫快取 (SQLite) - 24小時 TTL L3: 磁碟快取 (File System) - 7天 TTL ``` #### 6.2.2 批量分析優化 ```csharp // 批量處理多個句子 public async Task> AnalyzeMultipleSentencesAsync( List sentences, Guid userId) { // 1. 批量檢查快取 var cacheResults = await _cacheService.GetMultipleAsync( sentences.Select(GenerateTextHash) ); // 2. 只分析未快取的句子 var uncachedSentences = sentences .Where((s, i) => cacheResults[i] == null) .ToList(); // 3. 批量調用 AI API var newAnalyses = await _geminiService.AnalyzeMultipleSentencesAsync( uncachedSentences ); // 4. 合併結果 return MergeResults(cacheResults, newAnalyses); } ``` ## 7. 測試策略 ### 7.1 單元測試 #### 7.1.1 前端組件測試 ```typescript describe('ClickableText Component', () => { it('should highlight phrase words correctly', () => { const analysis = { 'brought': { isPhrase: true, /* ... */ }, 'up': { isPhrase: true, /* ... */ } }; render(); expect(screen.getByText('brought')).toHaveClass('phrase'); expect(screen.getByText('up')).toHaveClass('phrase'); }); it('should show word popup on click', async () => { const mockOnClick = jest.fn(); render(); fireEvent.click(screen.getByText('brought')); expect(mockOnClick).toHaveBeenCalledWith('brought', expect.any(Object)); }); }); ``` #### 7.1.2 後端服務測試 ```csharp [Test] public async Task AnalyzeSentence_ShouldReturnCachedResult_WhenCacheExists() { // Arrange var inputText = "Test sentence"; var userId = Guid.NewGuid(); var cachedResult = new SentenceAnalysisResult(); _cacheService.Setup(c => c.GetAsync(It.IsAny())) .ReturnsAsync(cachedResult); // Act var result = await _analysisService.AnalyzeSentenceAsync(inputText, userId); // Assert Assert.AreEqual(cachedResult, result); _geminiService.Verify(g => g.AnalyzeSentenceAsync(It.IsAny()), Times.Never); } ``` ### 7.2 整合測試 #### 7.2.1 E2E 測試流程 ```typescript describe('Word Query Flow', () => { it('should complete full analysis and query flow', async () => { // 1. 輸入句子 await page.fill('[data-testid=sentence-input]', 'He brought this up'); await page.click('[data-testid=analyze-button]'); // 2. 等待分析完成 await page.waitForSelector('[data-testid=interactive-text]'); // 3. 點擊單字 await page.click('[data-testid=word-brought]'); // 4. 驗證彈窗顯示 await expect(page.locator('[data-testid=word-popup]')).toBeVisible(); await expect(page.locator('[data-testid=phrase-warning]')).toBeVisible(); // 5. 播放發音 await page.click('[data-testid=play-pronunciation]'); // 6. 關閉彈窗 await page.click('[data-testid=close-popup]'); await expect(page.locator('[data-testid=word-popup]')).toBeHidden(); }); }); ``` ## 8. 部署和監控 ### 8.1 部署策略 #### 8.1.1 前端部署 - **平台**:Vercel - **環境變量**:API_BASE_URL, CACHE_TTL - **CDN**:自動優化靜態資源 - **快取策略**:分析結果本地存儲 24 小時 #### 8.1.2 後端部署 - **平台**:Azure App Service / AWS Lambda - **資料庫**:Azure SQL Database / AWS RDS - **快取**:Azure Redis Cache / AWS ElastiCache - **檔案存儲**:Azure Blob Storage / AWS S3 ### 8.2 監控指標 #### 8.2.1 業務指標 - 句子分析成功率 - 平均分析響應時間 - 快取命中率 - 用戶使用次數分佈 - 單字點擊熱度排行 #### 8.2.2 技術指標 - API 響應時間 (P95 < 200ms) - Gemini API 調用延遲 - 快取效能指標 - 錯誤率 (< 1%) - 系統可用性 (> 99.9%) #### 8.2.3 成本監控 - Gemini API 調用次數和費用 - 快取存儲成本 - CDN 流量費用 - 基礎設施總成本 ## 9. 未來擴展計劃 ### 9.1 功能增強 - **多語言支持**:支援其他語言的句子分析 - **語音輸入**:整合語音識別進行句子輸入 - **個人化推薦**:基於用戶查詢歷史推薦相關詞彙 - **社交分享**:分享有趣的句子分析結果 ### 9.2 技術升級 - **AI 模型本地化**:部署本地 LLM 降低外部依賴 - **即時協作**:多用戶同時查詢同一句子 - **離線支持**:PWA 實現離線查詢基礎詞彙 - **效能優化**:WebAssembly 加速文本處理 ### 9.3 商業化功能 - **高級分析**:更深度的語法和語義分析 - **專業詞典**:整合專業領域詞典 - **學習追蹤**:詳細的學習進度和成效分析 - **導師模式**:AI 導師指導詞彙學習