AI.Demo/src/views/HomePage.vue

524 lines
16 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";
import { LISTENING_AUDIO_URL } from "@/config/index.js";
const router = useRouter();
const features = ref([
{
id: 1,
title: "听力考试音频生成",
desc: "输入听力文本或上传Word一键调用 AI 合成标准英语考试音频,支持多种题型场景,快速生成可用于备考的模拟听力材料。",
class: "card-1",
icon: "audio",
url: LISTENING_AUDIO_URL,
},
{
id: 2,
title: "口语对话",
desc: "提供校园生活、兴趣爱好、英语考试、影视讨论、旅游英语五大场景,与 AI 外教实时对话,每条回复自动语音朗读,支持英语音色切换。",
class: "card-2",
icon: "mic",
route: "/speaking",
},
{
id: 3,
title: "作文原图批改",
desc: "上传手写英语作文的 JPG/PNG 图片AI 自动识别内容并在原图上标注语法、拼写及表达问题,并排对比原图与批改结果,一目了然。",
class: "card-3",
icon: "edit",
route: "/essay-correction",
},
{
id: 4,
title: "英语试题AI分析",
desc: "支持文本粘贴或图片上传两种方式AI 流式输出题干理解、考点识别、解题思路、正确答案、详细解析五个维度,全面拆解每道英语题目。",
class: "card-4",
icon: "analytics",
route: "/exam-analysis",
},
{
id: 5,
title: "单词听写",
desc: "自适应发音报词,智能追踪拼写薄弱点,让词汇记忆更高效。",
class: "card-5",
icon: "spell",
route: "/spell-practice",
},
{
id: 6,
title: "英语发音",
desc: "输入英语单词或句子,从 36 种音色(含美音、英音)中自由选择,一键合成标准发音并支持在线播放与下载保存。",
class: "card-6",
icon: "speaker",
route: "/pronunciation",
},
{
id: 7,
title: "AI引导解题",
desc: "支持文本或图片上传题目AI 以对话方式一步步引导思考,卡片式展示解题步骤,让解题过程清晰易懂,支持多学科通用解题。",
class: "card-7",
icon: "puzzle",
route: "/problem-solving",
},
{
id: 8,
title: "AI试题生成",
desc: "智能生成英语试题,支持选择题、填空题、翻译题和阅读理解,可自定义难度、数量和知识点,快速创建高质量题库。",
class: "card-8",
icon: "document",
route: "/question-generator",
},
{
id: 9,
title: "题目变式生成",
desc: "输入原始试题AI 深度分析后生成同类变式题,保持题型不变,可调整难度,快速扩展题库,提升出题效率。",
class: "card-9",
icon: "variant",
route: "/question-variant",
},
]);
// 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="card-header">
<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>
<!-- Video Icon (Play Button) -->
<svg
v-else-if="feature.icon === 'video'"
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="M5.25 5.653c0-.856.917-1.398 1.667-.986l11.54 6.347a1.125 1.125 0 0 1 0 1.972l-11.54 6.347a1.125 1.125 0 0 1-1.667-.986V5.653Z"
/>
</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>
<!-- Puzzle Icon (Brain/Puzzle) -->
<svg
v-else-if="feature.icon === 'puzzle'"
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 6v6h4.5m4.5 0a9 9 0 1 1-18 0 9 9 0 0 1 18 0Z"
/>
</svg>
<!-- Document Icon (File/Document) -->
<svg
v-else-if="feature.icon === 'document'"
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.5 14.25v-2.625a3.375 3.375 0 0 0-3.375-3.375h-1.5A1.125 1.125 0 0 1 13.5 7.125v-1.5a3.375 3.375 0 0 0-3.375-3.375H8.25m0 12.75h7.5m-7.5 3H12M10.5 2.25H5.625c-.621 0-1.125.504-1.125 1.125v17.25c0 .621.504 1.125 1.125 1.125h12.75c.621 0 1.125-.504 1.125-1.125V11.25a9 9 0 0 0-9-9Z"
/>
</svg>
<!-- Variant Icon (Copy/Clone) -->
<svg
v-else-if="feature.icon === 'variant'"
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="M15.75 17.25v3.375c0 .621-.504 1.125-1.125 1.125h-9.75a1.125 1.125 0 0 1-1.125-1.125V7.875c0-.621.504-1.125 1.125-1.125H6.75a9.06 9.06 0 0 1 1.5.124m7.5 10.376h3.375c.621 0 1.125-.504 1.125-1.125V11.25c0-4.46-3.243-8.161-7.5-8.876v9.004c0 .621-.504 1.125-1.125 1.125h-3.75c-.621 0-1.125.504-1.125 1.125v3.876c0 .621.504 1.125 1.125 1.125h3.75c.621 0 1.125-.504 1.125-1.125Z"
/>
</svg>
</div>
<h2 class="card-title">{{ feature.title }}</h2>
</div>
<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);
}
.card-header {
display: flex;
align-items: center;
gap: 1rem;
margin-bottom: 1.5rem;
z-index: 2;
position: relative;
}
.icon-wrapper {
width: 60px;
height: 60px;
flex-shrink: 0;
border-radius: 16px;
display: flex;
align-items: center;
justify-content: center;
font-size: 1.75rem;
color: #fff;
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-7 .icon-wrapper {
background: linear-gradient(135deg, #8b5cf6, #7c3aed);
box-shadow: 0 8px 20px -6px rgba(139, 92, 246, 0.5);
}
.card-8 .icon-wrapper {
background: linear-gradient(135deg, #10b981, #059669);
box-shadow: 0 8px 20px -6px rgba(16, 185, 129, 0.5);
}
.card-9 .icon-wrapper {
background: linear-gradient(135deg, #6366f1, #8b5cf6);
box-shadow: 0 8px 20px -6px rgba(99, 102, 241, 0.5);
}
.card-title {
font-size: 1.5rem;
font-weight: 600;
margin: 0;
color: #f8fafc;
}
.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>