470 lines
16 KiB
HTML
470 lines
16 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="zh-TW">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||
<title>Drama Ling - 口說練習 第2+關 (v3.0原型)</title>
|
||
<link rel="stylesheet" href="../assets/style.css">
|
||
<style>
|
||
.speaking-container {
|
||
max-width: 900px;
|
||
margin: 0 auto;
|
||
padding: 20px;
|
||
}
|
||
|
||
.premium-header {
|
||
background: linear-gradient(135deg, #60A5FA, #3B82F6);
|
||
color: white;
|
||
padding: 25px;
|
||
border-radius: 12px;
|
||
text-align: center;
|
||
margin-bottom: 30px;
|
||
position: relative;
|
||
}
|
||
|
||
.premium-badge {
|
||
position: absolute;
|
||
top: -10px;
|
||
right: 20px;
|
||
background: #F59E0B;
|
||
color: white;
|
||
padding: 5px 12px;
|
||
border-radius: 15px;
|
||
font-size: 12px;
|
||
font-weight: bold;
|
||
}
|
||
|
||
.diamond-cost {
|
||
position: fixed;
|
||
top: 20px;
|
||
right: 20px;
|
||
background: white;
|
||
border: 2px solid #60A5FA;
|
||
border-radius: 12px;
|
||
padding: 12px 16px;
|
||
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
|
||
text-align: center;
|
||
}
|
||
|
||
.diamond-icon {
|
||
color: #60A5FA;
|
||
font-size: 24px;
|
||
}
|
||
|
||
.recording-section {
|
||
background: white;
|
||
border-radius: 12px;
|
||
padding: 30px;
|
||
margin-bottom: 25px;
|
||
border: 2px solid #e0e0e0;
|
||
text-align: center;
|
||
}
|
||
|
||
.microphone-area {
|
||
width: 120px;
|
||
height: 120px;
|
||
border-radius: 50%;
|
||
background: linear-gradient(45deg, #60A5FA, #3B82F6);
|
||
margin: 20px auto;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
cursor: pointer;
|
||
transition: all 0.3s ease;
|
||
box-shadow: 0 4px 15px rgba(96, 165, 250, 0.3);
|
||
}
|
||
|
||
.microphone-area:hover {
|
||
transform: scale(1.05);
|
||
box-shadow: 0 6px 20px rgba(96, 165, 250, 0.4);
|
||
}
|
||
|
||
.microphone-area.recording {
|
||
animation: pulse 1.5s infinite;
|
||
background: linear-gradient(45deg, #EF4444, #DC2626);
|
||
}
|
||
|
||
@keyframes pulse {
|
||
0%, 100% { transform: scale(1); }
|
||
50% { transform: scale(1.1); }
|
||
}
|
||
|
||
.mic-icon {
|
||
font-size: 48px;
|
||
color: white;
|
||
}
|
||
|
||
.vocabulary-display {
|
||
background: #f8fafc;
|
||
border: 2px solid #e2e8f0;
|
||
border-radius: 12px;
|
||
padding: 25px;
|
||
margin-bottom: 25px;
|
||
}
|
||
|
||
.word-card {
|
||
background: white;
|
||
border-radius: 8px;
|
||
padding: 20px;
|
||
margin-bottom: 15px;
|
||
border-left: 4px solid #60A5FA;
|
||
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
|
||
}
|
||
|
||
.ai-analysis {
|
||
background: #f0fdf4;
|
||
border: 2px solid #10B981;
|
||
border-radius: 12px;
|
||
padding: 25px;
|
||
margin-bottom: 25px;
|
||
}
|
||
|
||
.score-grid {
|
||
display: grid;
|
||
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
|
||
gap: 15px;
|
||
margin: 20px 0;
|
||
}
|
||
|
||
.score-item {
|
||
background: white;
|
||
border-radius: 8px;
|
||
padding: 15px;
|
||
text-align: center;
|
||
border: 1px solid #e0e0e0;
|
||
}
|
||
|
||
.score-value {
|
||
font-size: 24px;
|
||
font-weight: bold;
|
||
color: #10B981;
|
||
margin: 5px 0;
|
||
}
|
||
|
||
.score-label {
|
||
font-size: 12px;
|
||
color: #666;
|
||
text-transform: uppercase;
|
||
}
|
||
|
||
.feedback-section {
|
||
background: #fffbeb;
|
||
border: 2px solid #F59E0B;
|
||
border-radius: 12px;
|
||
padding: 25px;
|
||
margin-bottom: 25px;
|
||
}
|
||
|
||
.feedback-item {
|
||
background: white;
|
||
border-radius: 8px;
|
||
padding: 15px;
|
||
margin-bottom: 10px;
|
||
border-left: 4px solid #F59E0B;
|
||
}
|
||
|
||
.action-buttons {
|
||
display: flex;
|
||
gap: 15px;
|
||
justify-content: center;
|
||
margin-top: 30px;
|
||
}
|
||
|
||
.btn {
|
||
padding: 12px 24px;
|
||
border: none;
|
||
border-radius: 8px;
|
||
font-weight: bold;
|
||
cursor: pointer;
|
||
transition: all 0.3s ease;
|
||
}
|
||
|
||
.btn-premium {
|
||
background: #60A5FA;
|
||
color: white;
|
||
}
|
||
|
||
.btn-premium:hover {
|
||
background: #3B82F6;
|
||
}
|
||
|
||
.btn-secondary {
|
||
background: #e0e0e0;
|
||
color: #666;
|
||
}
|
||
|
||
.back-nav {
|
||
position: fixed;
|
||
top: 20px;
|
||
left: 20px;
|
||
background: #60A5FA;
|
||
color: white;
|
||
padding: 10px 15px;
|
||
border-radius: 8px;
|
||
text-decoration: none;
|
||
font-weight: bold;
|
||
}
|
||
|
||
.v3-prototype-notice {
|
||
background: #f0f9ff;
|
||
border: 1px solid #0ea5e9;
|
||
border-radius: 8px;
|
||
padding: 15px;
|
||
margin-bottom: 20px;
|
||
}
|
||
|
||
.recording-status {
|
||
background: #fee2e2;
|
||
border: 1px solid #fecaca;
|
||
border-radius: 8px;
|
||
padding: 10px;
|
||
margin: 15px 0;
|
||
text-align: center;
|
||
font-weight: bold;
|
||
}
|
||
|
||
.recording-status.ready {
|
||
background: #f0fdf4;
|
||
border-color: #bbf7d0;
|
||
color: #059669;
|
||
}
|
||
|
||
.recording-status.recording {
|
||
background: #fee2e2;
|
||
border-color: #fecaca;
|
||
color: #dc2626;
|
||
}
|
||
</style>
|
||
</head>
|
||
<body>
|
||
<a href="../index.html" class="back-nav">← 返回導航</a>
|
||
|
||
<div class="diamond-cost">
|
||
<div class="diamond-icon">💎</div>
|
||
<div style="font-weight: bold; margin: 5px 0;">消耗5鑽石</div>
|
||
<div style="font-size: 12px; color: #666;">剩餘: 23顆</div>
|
||
</div>
|
||
|
||
<div class="speaking-container">
|
||
<div class="v3-prototype-notice">
|
||
<h3>🔄 v3.0原型通知</h3>
|
||
<p>本頁面展示<strong>第2+關:口說練習</strong>,基於AI算法規格的五維度口說評分系統原型。</p>
|
||
<p>📋 <strong>對應規格</strong>: <a href="../../function-specs/common/speaking-evaluation-specs.md" target="_blank">口說評分系統</a></p>
|
||
</div>
|
||
|
||
<div class="premium-header">
|
||
<div class="premium-badge">💎 付費功能</div>
|
||
<div style="display: flex; align-items: center; justify-content: center; gap: 10px; margin-bottom: 10px;">
|
||
<div style="background: rgba(255,255,255,0.2); border-radius: 50%; width: 45px; height: 45px; display: flex; align-items: center; justify-content: center; font-weight: bold;">2+</div>
|
||
<h1>第2+關:AI口說練習</h1>
|
||
</div>
|
||
<p>劇本:餐廳點餐 | AI五維度評分 | 即時發音改善</p>
|
||
</div>
|
||
|
||
<div class="vocabulary-display">
|
||
<h3>📝 練習詞彙</h3>
|
||
<div class="word-card">
|
||
<div style="display: flex; justify-content: space-between; align-items: center;">
|
||
<div>
|
||
<h4 style="margin: 0; color: #60A5FA;">menu</h4>
|
||
<p style="margin: 5px 0; color: #666;">/ˈmenjuː/ 菜單</p>
|
||
</div>
|
||
<button class="btn btn-secondary" onclick="playAudio('menu')">🔊 示範發音</button>
|
||
</div>
|
||
</div>
|
||
<div class="word-card">
|
||
<div style="display: flex; justify-content: space-between; align-items: center;">
|
||
<div>
|
||
<h4 style="margin: 0; color: #60A5FA;">order</h4>
|
||
<p style="margin: 5px 0; color: #666;">/ˈɔːrdər/ 點餐</p>
|
||
</div>
|
||
<button class="btn btn-secondary" onclick="playAudio('order')">🔊 示範發音</button>
|
||
</div>
|
||
</div>
|
||
<div class="word-card">
|
||
<div style="display: flex; justify-content: space-between; align-items: center;">
|
||
<div>
|
||
<h4 style="margin: 0; color: #60A5FA;">Can I have the menu, please?</h4>
|
||
<p style="margin: 5px 0; color: #666;">請給我菜單,謝謝。</p>
|
||
</div>
|
||
<button class="btn btn-secondary" onclick="playAudio('sentence')">🔊 示範發音</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="recording-section">
|
||
<h3>🎤 AI語音評分</h3>
|
||
<p>點擊麥克風開始錄製,說出:<strong>"Can I have the menu, please?"</strong></p>
|
||
|
||
<div class="microphone-area" id="micButton" onclick="toggleRecording()">
|
||
<div class="mic-icon">🎤</div>
|
||
</div>
|
||
|
||
<div class="recording-status ready" id="recordingStatus">
|
||
準備開始錄製 - 點擊麥克風開始
|
||
</div>
|
||
</div>
|
||
|
||
<div class="ai-analysis" id="aiAnalysis" style="display: none;">
|
||
<h3>🤖 AI五維度分析結果</h3>
|
||
<div class="score-grid">
|
||
<div class="score-item">
|
||
<div class="score-label">流暢度</div>
|
||
<div class="score-value">85</div>
|
||
<div style="font-size: 12px; color: #10B981;">優秀</div>
|
||
</div>
|
||
<div class="score-item">
|
||
<div class="score-label">準確度</div>
|
||
<div class="score-value">92</div>
|
||
<div style="font-size: 12px; color: #10B981;">優秀</div>
|
||
</div>
|
||
<div class="score-item">
|
||
<div class="score-label">發音</div>
|
||
<div class="score-value">78</div>
|
||
<div style="font-size: 12px; color: #F59E0B;">良好</div>
|
||
</div>
|
||
<div class="score-item">
|
||
<div class="score-label">語調</div>
|
||
<div class="score-value">88</div>
|
||
<div style="font-size: 12px; color: #10B981;">優秀</div>
|
||
</div>
|
||
<div class="score-item">
|
||
<div class="score-label">語速</div>
|
||
<div class="score-value">82</div>
|
||
<div style="font-size: 12px; color: #10B981;">優秀</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div style="text-align: center; margin-top: 20px;">
|
||
<div style="font-size: 24px; font-weight: bold; color: #10B981;">⭐⭐⭐</div>
|
||
<div style="margin: 10px 0; font-weight: bold;">總評分:85分 (三星)</div>
|
||
<div style="color: #666;">恭喜!已達到通關標準</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="feedback-section" id="feedbackSection" style="display: none;">
|
||
<h3>💡 AI改善建議</h3>
|
||
<div class="feedback-item">
|
||
<h4>🎯 發音改善重點</h4>
|
||
<p><strong>"menu"</strong> 的 /u/ 音可以更圓潤一些,嘴型要更圓</p>
|
||
</div>
|
||
<div class="feedback-item">
|
||
<h4>✅ 表現良好</h4>
|
||
<p>語調自然,語速適中,整體流暢度很好</p>
|
||
</div>
|
||
<div class="feedback-item">
|
||
<h4>📈 下次練習建議</h4>
|
||
<p>可以嘗試更自信的語調,模擬真實餐廳場景</p>
|
||
</div>
|
||
</div>
|
||
|
||
<div style="background: #f0fdf4; border: 2px solid #10B981; border-radius: 8px; padding: 20px; text-align: center;">
|
||
<h3>✅ 通關條件</h3>
|
||
<p><strong>總分要求</strong>:70分以上 (目前:85分)</p>
|
||
<p><strong>星級獎勵</strong>:⭐⭐⭐ 三星通關</p>
|
||
<p style="margin-top: 15px; color: #059669;">
|
||
<strong>獲得獎勵</strong>:發音練習經驗值 +50,解鎖高級發音教學
|
||
</p>
|
||
</div>
|
||
|
||
<div class="action-buttons">
|
||
<button class="btn btn-secondary" onclick="retryRecording()">重新錄製</button>
|
||
<button class="btn btn-premium" onclick="completeStage()">完成關卡</button>
|
||
<button class="btn btn-secondary" onclick="skipStage()">跳過此關 (2💎)</button>
|
||
</div>
|
||
</div>
|
||
|
||
<script>
|
||
let isRecording = false;
|
||
let recordingTimer = null;
|
||
|
||
function toggleRecording() {
|
||
const micButton = document.getElementById('micButton');
|
||
const status = document.getElementById('recordingStatus');
|
||
|
||
if (!isRecording) {
|
||
startRecording();
|
||
} else {
|
||
stopRecording();
|
||
}
|
||
}
|
||
|
||
function startRecording() {
|
||
isRecording = true;
|
||
const micButton = document.getElementById('micButton');
|
||
const status = document.getElementById('recordingStatus');
|
||
|
||
micButton.classList.add('recording');
|
||
status.className = 'recording-status recording';
|
||
status.textContent = '🔴 錄製中... (最多30秒)';
|
||
|
||
// 模擬錄製3秒後自動停止
|
||
recordingTimer = setTimeout(() => {
|
||
stopRecording();
|
||
}, 3000);
|
||
}
|
||
|
||
function stopRecording() {
|
||
isRecording = false;
|
||
clearTimeout(recordingTimer);
|
||
|
||
const micButton = document.getElementById('micButton');
|
||
const status = document.getElementById('recordingStatus');
|
||
|
||
micButton.classList.remove('recording');
|
||
status.className = 'recording-status ready';
|
||
status.textContent = '🔄 正在分析中...';
|
||
|
||
// 模擬AI分析
|
||
setTimeout(() => {
|
||
showAnalysisResults();
|
||
}, 2000);
|
||
}
|
||
|
||
function showAnalysisResults() {
|
||
const status = document.getElementById('recordingStatus');
|
||
const aiAnalysis = document.getElementById('aiAnalysis');
|
||
const feedbackSection = document.getElementById('feedbackSection');
|
||
|
||
status.textContent = '✅ 分析完成 - 查看下方結果';
|
||
aiAnalysis.style.display = 'block';
|
||
feedbackSection.style.display = 'block';
|
||
|
||
// 滾動到結果區域
|
||
aiAnalysis.scrollIntoView({ behavior: 'smooth' });
|
||
}
|
||
|
||
function playAudio(word) {
|
||
alert(`🔊 播放 "${word}" 的示範發音`);
|
||
}
|
||
|
||
function retryRecording() {
|
||
const aiAnalysis = document.getElementById('aiAnalysis');
|
||
const feedbackSection = document.getElementById('feedbackSection');
|
||
const status = document.getElementById('recordingStatus');
|
||
|
||
aiAnalysis.style.display = 'none';
|
||
feedbackSection.style.display = 'none';
|
||
status.className = 'recording-status ready';
|
||
status.textContent = '準備開始錄製 - 點擊麥克風開始';
|
||
}
|
||
|
||
function completeStage() {
|
||
alert('🎉 恭喜!第2+關:口說練習 完成!\\n\\n獲得:\\n⭐⭐⭐ 三星評分\\n+50 發音經驗值\\n🔓 解鎖高級發音教學\\n💎 消耗5鑽石');
|
||
}
|
||
|
||
function skipStage() {
|
||
if (confirm('確定要花費2鑽石跳過此關嗎?\\n跳過後將無法獲得經驗值和星級評分。')) {
|
||
alert('✅ 已跳過第2+關,消耗2鑽石');
|
||
}
|
||
}
|
||
|
||
console.log('🎤 第2+關:AI口說練習原型載入');
|
||
console.log('💎 v3.0特色:');
|
||
console.log(' - 五維度AI評分系統');
|
||
console.log(' - 鑽石消耗機制 (5顆)');
|
||
console.log(' - 即時發音分析和改善建議');
|
||
console.log(' - 符合口說評分系統規格');
|
||
</script>
|
||
</body>
|
||
</html> |