394 lines
7.5 KiB
Vue
394 lines
7.5 KiB
Vue
<template>
|
|
<div class="welcome-screen">
|
|
<!-- Logo 和标题 -->
|
|
<div class="welcome-header">
|
|
<h1 class="title">教研聊天助手</h1>
|
|
</div>
|
|
|
|
<!-- 功能卡片 -->
|
|
<div class="feature-cards">
|
|
<div
|
|
v-for="feature in features"
|
|
:key="feature.title"
|
|
class="feature-card"
|
|
>
|
|
<div class="feature-icon" :style="{ background: feature.gradient }">
|
|
<component :is="feature.icon" :size="22" />
|
|
</div>
|
|
<h3>{{ feature.title }}</h3>
|
|
<p>{{ feature.description }}</p>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 快速开始建议 -->
|
|
<div class="quick-start">
|
|
<h4>试试这些问题</h4>
|
|
<div class="suggestions-grid">
|
|
<button
|
|
v-for="suggestion in suggestions"
|
|
:key="suggestion.text"
|
|
class="suggestion-card"
|
|
@click="$emit('select', { id: suggestion.id, text: suggestion.text, systemPrompt: suggestion.systemPrompt })"
|
|
>
|
|
<component :is="suggestion.iconComponent" :size="18" class="suggestion-icon" />
|
|
<span>{{ suggestion.text }}</span>
|
|
<ChevronRight :size="16" class="arrow-icon" />
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 底部提示 -->
|
|
<div class="welcome-footer">
|
|
<div class="tip">
|
|
<Keyboard :size="14" />
|
|
<span>按 <kbd>Ctrl</kbd> + <kbd>/</kbd> 聚焦输入框</span>
|
|
</div>
|
|
<div class="tip">
|
|
<Zap :size="14" />
|
|
<span>支持 Markdown、代码高亮、LaTeX 公式</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import { computed } from "vue";
|
|
import {
|
|
MessageSquare,
|
|
Code,
|
|
Image,
|
|
FileText,
|
|
ChevronRight,
|
|
Keyboard,
|
|
Zap,
|
|
Globe,
|
|
Lightbulb,
|
|
PenTool,
|
|
} from "@/components/icons";
|
|
import promptData from "@/assets/prompt.json";
|
|
import type { Suggestion } from "@/types/chat";
|
|
|
|
defineEmits<{
|
|
select: [suggestion: Suggestion];
|
|
}>();
|
|
|
|
const features = computed(() => [
|
|
{
|
|
icon: MessageSquare,
|
|
title: "智能对话",
|
|
description: "自然流畅的对话体验,理解上下文",
|
|
gradient: "linear-gradient(135deg, #3b82f6 0%, #2563eb 100%)",
|
|
},
|
|
{
|
|
icon: Code,
|
|
title: "代码助手",
|
|
description: "编写、解释、优化各种编程语言代码",
|
|
gradient: "linear-gradient(135deg, #8b5cf6 0%, #6366f1 100%)",
|
|
},
|
|
{
|
|
icon: Image,
|
|
title: "图像理解",
|
|
description: "分析图片内容,提取关键信息",
|
|
gradient: "linear-gradient(135deg, #ec4899 0%, #d946ef 100%)",
|
|
},
|
|
{
|
|
icon: FileText,
|
|
title: "文档处理",
|
|
description: "阅读、总结、翻译各类文档",
|
|
gradient: "linear-gradient(135deg, #f59e0b 0%, #f97316 100%)",
|
|
},
|
|
]);
|
|
|
|
// 图标映射,根据文本内容选择合适的图标
|
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
const iconMap: Record<string, any> = {
|
|
学习: Lightbulb,
|
|
调试: Code,
|
|
写作: PenTool,
|
|
语言: Globe,
|
|
职业: Globe,
|
|
学术: FileText,
|
|
};
|
|
|
|
const suggestions = computed(() => {
|
|
// 内部类型,包含 icon 组件用于渲染
|
|
type SuggestionWithIcon = Suggestion & { iconComponent: typeof Code };
|
|
|
|
const allSuggestions: SuggestionWithIcon[] = [];
|
|
|
|
// 遍历 prompt.json 的分类和条目
|
|
for (const category of Object.values(promptData)) {
|
|
for (const [text, systemPrompt] of Object.entries(category)) {
|
|
// 根据文本关键词选择图标
|
|
let iconComponent = Code; // 默认图标
|
|
for (const [keyword, icon] of Object.entries(iconMap)) {
|
|
if (text.includes(keyword)) {
|
|
iconComponent = icon;
|
|
break;
|
|
}
|
|
}
|
|
allSuggestions.push({
|
|
id: text,
|
|
text,
|
|
systemPrompt,
|
|
iconComponent,
|
|
});
|
|
}
|
|
}
|
|
|
|
return allSuggestions;
|
|
});
|
|
</script>
|
|
|
|
<style lang="scss" scoped>
|
|
.welcome-screen {
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
justify-content: center;
|
|
min-height: 100%;
|
|
padding: 40px 24px;
|
|
animation: fadeIn 0.5s ease;
|
|
}
|
|
|
|
.welcome-header {
|
|
text-align: center;
|
|
margin-bottom: 48px;
|
|
}
|
|
|
|
.logo-wrapper {
|
|
position: relative;
|
|
display: inline-flex;
|
|
margin-bottom: 20px;
|
|
}
|
|
|
|
.logo-icon {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
width: 80px;
|
|
height: 80px;
|
|
background: linear-gradient(135deg, #3b82f6 0%, #8b5cf6 100%);
|
|
border-radius: 24px;
|
|
color: white;
|
|
box-shadow: 0 20px 40px -12px rgba(59, 130, 246, 0.35);
|
|
}
|
|
|
|
.logo-glow {
|
|
position: absolute;
|
|
inset: -20px;
|
|
background: radial-gradient(
|
|
circle,
|
|
rgba(59, 130, 246, 0.2) 0%,
|
|
transparent 70%
|
|
);
|
|
pointer-events: none;
|
|
}
|
|
|
|
.title {
|
|
margin: 0 0 12px;
|
|
font-size: 32px;
|
|
font-weight: 700;
|
|
color: #1f2937;
|
|
|
|
.dark & {
|
|
color: #f3f4f6;
|
|
}
|
|
}
|
|
|
|
.subtitle {
|
|
margin: 0;
|
|
font-size: 16px;
|
|
color: #6b7280;
|
|
|
|
.dark & {
|
|
color: #9ca3af;
|
|
}
|
|
}
|
|
|
|
.feature-cards {
|
|
display: grid;
|
|
grid-template-columns: repeat(4, 1fr);
|
|
gap: 20px;
|
|
max-width: 900px;
|
|
width: 100%;
|
|
margin-bottom: 48px;
|
|
|
|
@media (max-width: 900px) {
|
|
grid-template-columns: repeat(2, 1fr);
|
|
}
|
|
|
|
@media (max-width: 500px) {
|
|
grid-template-columns: 1fr;
|
|
}
|
|
}
|
|
|
|
.feature-card {
|
|
padding: 24px;
|
|
background: white;
|
|
border: 1px solid #e2e8f0;
|
|
border-radius: 16px;
|
|
text-align: center;
|
|
transition: all 0.3s ease;
|
|
|
|
.dark & {
|
|
background: #1e1e2e;
|
|
border-color: #2d2d3d;
|
|
}
|
|
|
|
&:hover {
|
|
transform: translateY(-4px);
|
|
box-shadow: 0 12px 24px -8px rgba(0, 0, 0, 0.1);
|
|
|
|
.dark & {
|
|
box-shadow: 0 12px 24px -8px rgba(0, 0, 0, 0.4);
|
|
}
|
|
}
|
|
|
|
.feature-icon {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
width: 48px;
|
|
height: 48px;
|
|
border-radius: 14px;
|
|
color: white;
|
|
margin-bottom: 16px;
|
|
}
|
|
|
|
h3 {
|
|
margin: 0 0 8px;
|
|
font-size: 16px;
|
|
font-weight: 600;
|
|
color: #1f2937;
|
|
|
|
.dark & {
|
|
color: #f3f4f6;
|
|
}
|
|
}
|
|
|
|
p {
|
|
margin: 0;
|
|
font-size: 13px;
|
|
color: #6b7280;
|
|
line-height: 1.5;
|
|
|
|
.dark & {
|
|
color: #9ca3af;
|
|
}
|
|
}
|
|
}
|
|
|
|
.quick-start {
|
|
max-width: 710px;
|
|
width: 100%;
|
|
margin-bottom: 40px;
|
|
|
|
h4 {
|
|
margin: 0 0 16px;
|
|
font-size: 14px;
|
|
font-weight: 600;
|
|
color: #6b7280;
|
|
text-align: center;
|
|
|
|
.dark & {
|
|
color: #9ca3af;
|
|
}
|
|
}
|
|
}
|
|
|
|
.suggestions-grid {
|
|
display: grid;
|
|
grid-template-columns: repeat(2, 1fr);
|
|
gap: 12px;
|
|
|
|
@media (max-width: 600px) {
|
|
grid-template-columns: 1fr;
|
|
}
|
|
}
|
|
|
|
.suggestion-card {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 12px;
|
|
padding: 16px 20px;
|
|
background: white;
|
|
border: 1px solid #e2e8f0;
|
|
border-radius: 14px;
|
|
color: #374151;
|
|
font-size: 14px;
|
|
text-align: left;
|
|
cursor: pointer;
|
|
transition: all 0.2s ease;
|
|
|
|
.dark & {
|
|
background: #1e1e2e;
|
|
border-color: #2d2d3d;
|
|
color: #e5e7eb;
|
|
}
|
|
|
|
&:hover {
|
|
border-color: #3b82f6;
|
|
background: rgba(59, 130, 246, 0.05);
|
|
|
|
.arrow-icon {
|
|
transform: translateX(4px);
|
|
color: #3b82f6;
|
|
}
|
|
}
|
|
|
|
.suggestion-icon {
|
|
flex-shrink: 0;
|
|
color: #3b82f6;
|
|
}
|
|
|
|
span {
|
|
flex: 1;
|
|
}
|
|
|
|
.arrow-icon {
|
|
flex-shrink: 0;
|
|
color: #9ca3af;
|
|
transition: all 0.2s ease;
|
|
}
|
|
}
|
|
|
|
.welcome-footer {
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
align-items: center;
|
|
justify-content: center;
|
|
gap: 24px;
|
|
}
|
|
|
|
.tip {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 8px;
|
|
font-size: 13px;
|
|
color: #9ca3af;
|
|
|
|
kbd {
|
|
padding: 2px 8px;
|
|
background: #f3f4f6;
|
|
border-radius: 4px;
|
|
font-size: 12px;
|
|
|
|
.dark & {
|
|
background: #374151;
|
|
}
|
|
}
|
|
}
|
|
|
|
@keyframes fadeIn {
|
|
from {
|
|
opacity: 0;
|
|
transform: translateY(20px);
|
|
}
|
|
to {
|
|
opacity: 1;
|
|
transform: translateY(0);
|
|
}
|
|
}
|
|
</style>
|