AI.Demo/src/components/HomePage.vue

327 lines
10 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.

<script setup>
import { ref, onMounted, onUnmounted } from 'vue'
import { useRouter } from 'vue-router'
const router = useRouter()
const features = ref([
{
id: 1,
title: 'AI听力考试音频生成',
desc: '基于先进TTS技术根据文本快速合成全真模拟的英语听力考试音频。',
class: 'card-1',
icon: 'audio',
url: 'https://jz5k88k7vv.coze.site'
},
{
id: 2,
title: 'AI口语对话',
desc: '全天候1对1外教级对练实时纠正发音与语法快速提升口语表达。',
class: 'card-2',
icon: 'mic',
route: null
},
{
id: 3,
title: 'AI作文原图批改',
desc: '一键上传手写作文图片AI智能OCR识别并提供词汇、语法深度批改。',
class: 'card-3',
icon: 'edit',
route: null
},
{
id: 4,
title: '英语试题AI分析',
desc: '深度解析长难句、阅读理解及语法考点,为您提供专属错题讲解。',
class: 'card-4',
icon: 'analytics',
route: null
},
{
id: 5,
title: 'AI单词听写',
desc: '自适应发音报词,智能追踪拼写薄弱点,让词汇记忆更高效。',
class: 'card-5',
icon: 'spell',
route: null
},
{
id: 6,
title: 'AI英语发音',
desc: '输入英语单词或长难句一键调用AI为您进行标准地道的语音朗读示范。',
class: 'card-6',
icon: 'speaker',
route: '/pronunciation'
}
])
// Hover effect for glassmorphism glare
const handleMouseMove = (e) => {
const cards = document.querySelectorAll('.homepage-feature-card')
for (const card of cards) {
const rect = card.getBoundingClientRect()
const x = e.clientX - rect.left
const y = e.clientY - rect.top
card.style.setProperty('--mouse-x', `${x}px`)
card.style.setProperty('--mouse-y', `${y}px`)
}
}
const handleCardClick = (feature) => {
if (feature.url) {
window.open(feature.url, '_blank')
} else if (feature.route) {
router.push(feature.route)
}
}
onMounted(() => {
const container = document.querySelector('.homepage-container')
if (container) {
container.addEventListener('mousemove', handleMouseMove)
}
})
onUnmounted(() => {
const container = document.querySelector('.homepage-container')
if (container) {
container.removeEventListener('mousemove', handleMouseMove)
}
})
</script>
<template>
<div class="homepage-container">
<header>
<h1>AI 英语学习辅助平台</h1>
<p class="subtitle">全方位智能化辅助让英语学习更加简单高效</p>
</header>
<main class="grid-container">
<div v-for="feature in features" :key="feature.id" @click="handleCardClick(feature)" class="homepage-feature-card" :class="feature.class">
<div class="icon-wrapper">
<!-- Audio Icon (Headphones) -->
<svg v-if="feature.icon === 'audio'" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" d="M12 21a9.004 9.004 0 0 0 8.716-6.747M12 21a9.004 9.004 0 0 1-8.716-6.747M12 21c2.485 0 4.5-4.03 4.5-9S14.485 3 12 3m0 18c-2.485 0-4.5-4.03-4.5-9S9.515 3 12 3m0 0a8.997 8.997 0 0 1 7.843 4.582M12 3a8.997 8.997 0 0 0-7.843 4.582m15.686 0A11.953 11.953 0 0 1 12 10.5c-2.998 0-5.74-1.1-7.843-2.918m15.686 0A8.959 8.959 0 0 1 21 12c0 .778-.099 1.533-.284 2.253m0 0A17.919 17.919 0 0 1 12 16.5c-3.162 0-6.133-.815-8.716-2.247m0 0A9.015 9.015 0 0 1 3 12c0-1.605.42-3.113 1.157-4.418" />
</svg>
<!-- Mic Icon (Chat/Mic) -->
<svg v-else-if="feature.icon === 'mic'" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" d="M12 18.75a6 6 0 0 0 6-6v-1.5m-6 7.5a6 6 0 0 1-6-6v-1.5m6 7.5v3.75m-3.75 0h7.5M12 15.75a3 3 0 0 1-3-3V4.5a3 3 0 1 1 6 0v8.25a3 3 0 0 1-3 3Z" />
</svg>
<!-- Edit Icon (Document Text / Pen) -->
<svg v-else-if="feature.icon === 'edit'" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" d="m16.862 4.487 1.687-1.688a1.875 1.875 0 1 1 2.652 2.652L6.832 19.82a4.5 4.5 0 0 1-1.897 1.13l-2.685.8.8-2.685a4.5 4.5 0 0 1 1.13-1.897L16.863 4.487Zm0 0L19.5 7.125" />
</svg>
<!-- Analytics Icon (Chart/Sparkles) -->
<svg v-else-if="feature.icon === 'analytics'" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" d="M3 13.125C3 12.504 3.504 12 4.125 12h2.25c.621 0 1.125.504 1.125 1.125v6.75C7.5 20.496 6.996 21 6.375 21h-2.25A1.125 1.125 0 0 1 3 19.875v-6.75ZM9.75 8.625c0-.621.504-1.125 1.125-1.125h2.25c.621 0 1.125.504 1.125 1.125v11.25c0 .621-.504 1.125-1.125 1.125h-2.25a1.125 1.125 0 0 1-1.125-1.125V8.625ZM16.5 4.125c0-.621.504-1.125 1.125-1.125h2.25C20.496 3 21 3.504 21 4.125v15.75c0 .621-.504 1.125-1.125 1.125h-2.25a1.125 1.125 0 0 1-1.125-1.125V4.125Z" />
</svg>
<!-- Spell Icon (Book Open) -->
<svg v-else-if="feature.icon === 'spell'" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" d="M12 6.042A8.967 8.967 0 0 0 6 3.75c-1.052 0-2.062.18-3 .512v14.25A8.987 8.987 0 0 1 6 18c2.305 0 4.408.867 6 2.292m0-14.25a8.966 8.966 0 0 1 6-2.292c1.052 0 2.062.18 3 .512v14.25A8.987 8.987 0 0 0 18 18a8.967 8.967 0 0 0-6 2.292m0-14.25v14.25" />
</svg>
<!-- Speaker Icon (Megaphone/Speaker) -->
<svg v-else-if="feature.icon === 'speaker'" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" d="M19.114 5.636a9 9 0 0 1 0 12.728M16.463 8.288a5.25 5.25 0 0 1 0 7.424M6.75 8.25l4.72-4.72a.75.75 0 0 1 1.28.53v15.88a.75.75 0 0 1-1.28.53l-4.72-4.72H4.51c-.88 0-1.704-.507-1.938-1.354A9.009 9.009 0 0 1 2.25 12c0-.83.112-1.633.322-2.396C2.806 8.756 3.63 8.25 4.51 8.25H6.75Z" />
</svg>
</div>
<h2 class="card-title">{{ feature.title }}</h2>
<p class="card-desc">{{ feature.desc }}</p>
<svg class="arrow-icon" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" d="M13.5 4.5L21 12m0 0l-7.5 7.5M21 12H3" />
</svg>
</div>
</main>
</div>
</template>
<style scoped>
.homepage-container {
width: 100%;
max-width: 1200px;
margin: 0 auto;
padding: 4rem 2rem;
box-sizing: border-box;
}
header {
text-align: center;
margin-bottom: 4rem;
}
h1 {
font-size: 3.5rem;
font-weight: 800;
letter-spacing: -0.05em;
margin: 0;
background: linear-gradient(135deg, #fff 0%, #a5b4fc 100%);
-webkit-background-clip: text;
background-clip: text;
-webkit-text-fill-color: transparent;
text-shadow: 0 0 40px rgba(99, 102, 241, 0.3);
}
.subtitle {
font-size: 1.25rem;
color: #94a3b8;
margin-top: 1rem;
font-weight: 400;
}
.grid-container {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
gap: 2rem;
}
.homepage-feature-card {
background: rgba(255, 255, 255, 0.03);
border: 1px solid rgba(255, 255, 255, 0.08);
border-radius: 20px;
padding: 2.5rem 2rem;
transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1);
position: relative;
overflow: hidden;
cursor: pointer;
backdrop-filter: blur(12px);
-webkit-backdrop-filter: blur(12px);
display: flex;
flex-direction: column;
align-items: flex-start;
text-decoration: none;
color: inherit;
}
.homepage-feature-card::before {
content: '';
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: radial-gradient(800px circle at var(--mouse-x, 50%) var(--mouse-y, 50%), rgba(255, 255, 255, 0.06), transparent 40%);
opacity: 0;
transition: opacity 0.4s;
z-index: 1;
pointer-events: none;
}
.homepage-feature-card:hover::before {
opacity: 1;
}
.homepage-feature-card:hover {
transform: translateY(-8px);
background: rgba(255, 255, 255, 0.06);
border-color: rgba(255, 255, 255, 0.15);
box-shadow: 0 20px 40px -15px rgba(0, 0, 0, 0.5);
}
.icon-wrapper {
width: 60px;
height: 60px;
border-radius: 16px;
display: flex;
align-items: center;
justify-content: center;
margin-bottom: 1.5rem;
font-size: 1.75rem;
color: #fff;
position: relative;
z-index: 2;
transition: transform 0.3s ease;
}
.homepage-feature-card:hover .icon-wrapper {
transform: scale(1.1) rotate(5deg);
}
.icon-wrapper svg {
width: 32px;
height: 32px;
}
/* Colors for specific cards */
.card-1 .icon-wrapper {
background: linear-gradient(135deg, #6366f1, #4f46e5);
box-shadow: 0 8px 20px -6px rgba(99, 102, 241, 0.5);
}
.card-2 .icon-wrapper {
background: linear-gradient(135deg, #8b5cf6, #7c3aed);
box-shadow: 0 8px 20px -6px rgba(139, 92, 246, 0.5);
}
.card-3 .icon-wrapper {
background: linear-gradient(135deg, #ec4899, #db2777);
box-shadow: 0 8px 20px -6px rgba(236, 72, 153, 0.5);
}
.card-4 .icon-wrapper {
background: linear-gradient(135deg, #14b8a6, #0d9488);
box-shadow: 0 8px 20px -6px rgba(20, 184, 166, 0.5);
}
.card-5 .icon-wrapper {
background: linear-gradient(135deg, #f59e0b, #d97706);
box-shadow: 0 8px 20px -6px rgba(245, 158, 11, 0.5);
}
.card-6 .icon-wrapper {
background: linear-gradient(135deg, #ef4444, #dc2626);
box-shadow: 0 8px 20px -6px rgba(239, 68, 68, 0.5);
}
.card-title {
font-size: 1.5rem;
font-weight: 600;
margin: 0 0 0.75rem 0;
color: #f8fafc;
z-index: 2;
}
.card-desc {
font-size: 1rem;
color: #94a3b8;
line-height: 1.6;
margin: 0;
z-index: 2;
}
.arrow-icon {
position: absolute;
bottom: 2rem;
right: 2rem;
width: 24px;
height: 24px;
color: rgba(255, 255, 255, 0.2);
transition: all 0.3s ease;
z-index: 2;
}
.homepage-feature-card:hover .arrow-icon {
color: #fff;
transform: translateX(4px);
}
@media (max-width: 768px) {
h1 {
font-size: 2.5rem;
}
.homepage-container {
padding: 2rem 1rem;
}
.homepage-feature-card {
padding: 2rem 1.5rem;
}
}
</style>