dramaling-app/apps/web/src/views/learning/PronunciationView.vue

175 lines
4.3 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div class="pronunciation-view">
<q-page class="q-pa-md">
<div class="text-center q-mb-lg">
<h1 class="text-h4 q-mb-sm">發音練習</h1>
<p class="text-body1 text-grey-7">AI 輔助發音矯正練習</p>
</div>
<div class="row justify-center">
<div class="col-12 col-md-8">
<q-card class="pronunciation-card">
<q-card-section>
<div class="text-h6">練習詞彙: {{ pronunciationId }}</div>
<div class="pronunciation-target">
<div class="target-word">"Restaurant"</div>
<div class="phonetic">/ˈrɛstərɑnt/</div>
</div>
</q-card-section>
<q-card-section class="recording-section">
<div class="recording-area">
<q-btn
round
size="xl"
:color="isRecording ? 'negative' : 'primary'"
:icon="isRecording ? 'stop' : 'mic'"
@click="toggleRecording"
class="recording-btn"
/>
<div class="recording-status">
{{ isRecording ? '錄音中...' : '點擊開始錄音' }}
</div>
<div v-if="hasRecording" class="playback-controls q-mt-md">
<q-btn
icon="play_arrow"
label="播放我的發音"
@click="playRecording"
class="q-mr-sm"
/>
<q-btn
icon="volume_up"
label="播放標準發音"
@click="playTarget"
/>
</div>
</div>
</q-card-section>
<q-card-section v-if="feedback">
<div class="feedback-section">
<div class="text-h6 q-mb-sm">發音評估</div>
<q-linear-progress
:value="feedback.accuracy"
color="positive"
class="q-mb-sm"
/>
<div class="text-body2">準確度: {{ Math.round(feedback.accuracy * 100) }}%</div>
<div class="feedback-tips q-mt-sm">
<strong>建議:</strong> {{ feedback.tip }}
</div>
</div>
</q-card-section>
<q-card-actions class="justify-center">
<q-btn color="primary" label="下一個詞彙" />
<q-btn flat label="重新練習" />
</q-card-actions>
</q-card>
</div>
</div>
</q-page>
</div>
</template>
<script setup lang="ts">
import { ref, computed } from 'vue'
import { useRoute } from 'vue-router'
const route = useRoute()
const pronunciationId = computed(() => route.params.id)
const isRecording = ref(false)
const hasRecording = ref(false)
const feedback = ref(null as any)
const toggleRecording = () => {
isRecording.value = !isRecording.value
if (!isRecording.value) {
hasRecording.value = true
// 模擬AI評估
setTimeout(() => {
feedback.value = {
accuracy: 0.85,
tip: '注意 "au" 的發音,可以更圓潤一些'
}
}, 1000)
}
}
const playRecording = () => {
// 播放用戶錄音
}
const playTarget = () => {
// 播放標準發音
}
</script>
<style scoped>
.pronunciation-view {
min-height: 100vh;
}
.pronunciation-card {
max-width: 700px;
margin: 0 auto;
}
.pronunciation-target {
text-align: center;
padding: 24px;
background: #f8f9fa;
border-radius: 12px;
margin: 16px 0;
}
.target-word {
font-size: 2.5em;
font-weight: bold;
color: #1976d2;
margin-bottom: 8px;
}
.phonetic {
font-size: 1.2em;
color: #666;
font-family: 'Courier New', monospace;
}
.recording-section {
text-align: center;
padding: 32px;
}
.recording-area {
display: flex;
flex-direction: column;
align-items: center;
}
.recording-btn {
margin-bottom: 16px;
box-shadow: 0 8px 16px rgba(0,0,0,0.1);
}
.recording-status {
font-size: 1.1em;
color: #666;
}
.feedback-section {
background: #e8f5e8;
padding: 20px;
border-radius: 8px;
border-left: 4px solid #4caf50;
}
.feedback-tips {
background: #fff;
padding: 12px;
border-radius: 6px;
margin-top: 12px;
}
</style>