mirror of
https://github.com/JOYCEQL/magic-resume.git
synced 2026-07-03 14:07:11 +02:00
feat: add new feature images and update localization strings
This commit is contained in:
@@ -1,68 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="600" height="400" viewBox="0 0 600 400" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<style>
|
||||
@media (prefers-color-scheme: dark) {
|
||||
.bg { fill: #0F172A !important; }
|
||||
.card { fill: #1E293B !important; stroke: #475569 !important; }
|
||||
.toolbar { fill: #2D3B55 !important; }
|
||||
.text-block { fill: #475569 !important; }
|
||||
.error-bg { fill: #FCA5A5 !important; opacity: 0.15 !important; }
|
||||
.error-text { fill: #FCA5A5 !important; }
|
||||
.suggestion-bg { fill: #FCA5A5 !important; opacity: 0.1 !important; }
|
||||
.ai-circle { fill: #60A5FA !important; }
|
||||
.ai-text { fill: #EFF6FF !important; }
|
||||
.error-mark { stroke: #FCA5A5 !important; }
|
||||
}
|
||||
@keyframes pulse {
|
||||
0% { opacity: 0.6; }
|
||||
50% { opacity: 1; }
|
||||
100% { opacity: 0.6; }
|
||||
}
|
||||
@keyframes slideIn {
|
||||
from { transform: translateX(20px); opacity: 0; }
|
||||
to { transform: translateX(0); opacity: 1; }
|
||||
}
|
||||
@keyframes highlight {
|
||||
0% { stroke-dashoffset: 100; }
|
||||
100% { stroke-dashoffset: 0; }
|
||||
}
|
||||
.ai-icon { animation: pulse 2s infinite; }
|
||||
.suggestion { animation: slideIn 0.5s ease-out; }
|
||||
.error-mark {
|
||||
stroke-dasharray: 100;
|
||||
animation: highlight 1.5s ease-in-out infinite;
|
||||
}
|
||||
.glow {
|
||||
filter: drop-shadow(0 0 8px rgba(96, 165, 250, 0.3));
|
||||
}
|
||||
</style>
|
||||
|
||||
<!-- 背景 -->
|
||||
<rect class="bg" width="600" height="400" fill="#F0F9FF"/>
|
||||
|
||||
<!-- 编辑器界面模拟 -->
|
||||
<rect class="card glow" x="50" y="50" width="500" height="300" rx="8" fill="white" stroke="#93C5FD" stroke-width="2"/>
|
||||
|
||||
<!-- 工具栏 -->
|
||||
<rect class="toolbar" x="50" y="50" width="500" height="40" rx="8" fill="#EFF6FF"/>
|
||||
|
||||
<!-- 文本区域 -->
|
||||
<rect class="text-block" x="70" y="110" width="460" height="20" rx="4" fill="#E0F2FE"/>
|
||||
<rect class="text-block" x="70" y="140" width="380" height="20" rx="4" fill="#E0F2FE"/>
|
||||
|
||||
<!-- AI 纠错标记 -->
|
||||
<rect class="error-bg" x="70" y="180" width="200" height="20" rx="4" fill="#FEE2E2"/>
|
||||
<path class="error-mark" d="M260 190 L280 200 L260 210" stroke="#F87171" stroke-width="2"/>
|
||||
|
||||
<!-- AI 建议气泡 -->
|
||||
<g class="suggestion">
|
||||
<rect class="suggestion-bg" x="300" y="170" width="200" height="60" rx="8" fill="#F87171" opacity="0.1"/>
|
||||
<text class="error-text" x="320" y="200" fill="#F87171" font-family="Arial" font-size="12">建议修改:表达更专业</text>
|
||||
</g>
|
||||
|
||||
<!-- AI 图标 -->
|
||||
<g class="ai-icon glow">
|
||||
<circle class="ai-circle" cx="550" cy="70" r="15" fill="#60A5FA"/>
|
||||
<text class="ai-text" x="540" y="75" fill="white" font-family="Arial" font-size="12">AI</text>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 2.6 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 137 KiB |
@@ -1,64 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="600" height="400" viewBox="0 0 600 400" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<style>
|
||||
@media (prefers-color-scheme: dark) {
|
||||
.bg { fill: #0F172A !important; }
|
||||
.device { fill: #1E293B !important; stroke: #A855F7 !important; }
|
||||
.screen { fill: #2D3B55 !important; }
|
||||
.storage-circle { fill: #7C3AED !important; opacity: 0.2 !important; }
|
||||
.storage-icon { stroke: #C4B5FD !important; }
|
||||
.lock-bg { fill: #7C3AED !important; }
|
||||
.lock-fg { fill: #EDE9FE !important; }
|
||||
.data-flow { stroke: #A855F7 !important; }
|
||||
.data-point { fill: #A855F7 !important; }
|
||||
}
|
||||
@keyframes secure {
|
||||
0% { transform: scale(1); }
|
||||
50% { transform: scale(1.1); }
|
||||
100% { transform: scale(1); }
|
||||
}
|
||||
@keyframes flow {
|
||||
0% { stroke-dashoffset: 24; }
|
||||
100% { stroke-dashoffset: 0; }
|
||||
}
|
||||
@keyframes fade {
|
||||
0% { opacity: 0.4; }
|
||||
50% { opacity: 0.8; }
|
||||
100% { opacity: 0.4; }
|
||||
}
|
||||
.secure-icon { animation: secure 2s ease-in-out infinite; }
|
||||
.data-flow { animation: flow 1.5s linear infinite; }
|
||||
.storage-indicator { animation: fade 2s ease-in-out infinite; }
|
||||
.glow {
|
||||
filter: drop-shadow(0 0 8px rgba(167, 139, 250, 0.3));
|
||||
}
|
||||
</style>
|
||||
|
||||
<!-- 背景 -->
|
||||
<rect class="bg" width="600" height="400" fill="#F5F3FF"/>
|
||||
|
||||
<!-- 设备图标 -->
|
||||
<rect class="device glow" x="150" y="100" width="300" height="200" rx="20" fill="white" stroke="#A855F7" stroke-width="2"/>
|
||||
|
||||
<!-- 屏幕 -->
|
||||
<rect class="screen" x="170" y="120" width="260" height="140" rx="8" fill="#EEF2FF"/>
|
||||
|
||||
<!-- 本地存储图标 -->
|
||||
<g class="storage-indicator glow">
|
||||
<circle class="storage-circle" cx="300" cy="180" r="40" fill="#A855F7" opacity="0.1"/>
|
||||
<path class="storage-icon" d="M280 180 L320 180 M300 160 L300 200" stroke="#8B5CF6" stroke-width="3"/>
|
||||
</g>
|
||||
|
||||
<!-- 锁图标 -->
|
||||
<g class="secure-icon glow">
|
||||
<circle class="lock-bg" cx="300" cy="280" r="15" fill="#8B5CF6"/>
|
||||
<rect class="lock-fg" x="293" y="275" width="14" height="12" rx="2" fill="white"/>
|
||||
<rect class="lock-fg" x="298" y="272" width="4" height="6" rx="1" fill="white"/>
|
||||
</g>
|
||||
|
||||
<!-- 数据流动效果 -->
|
||||
<path class="data-flow glow" d="M200 320 C200 350, 400 350, 400 320"
|
||||
stroke="#8B5CF6" stroke-width="2" stroke-dasharray="4 4"/>
|
||||
<circle class="data-point glow" cx="200" cy="320" r="4" fill="#8B5CF6"/>
|
||||
<circle class="data-point glow" cx="400" cy="320" r="4" fill="#8B5CF6"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 2.5 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 215 KiB |
@@ -1,89 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="600" height="400" viewBox="0 0 600 400" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<defs>
|
||||
<clipPath id="typing-clip">
|
||||
<rect x="40" y="70" width="230" height="50" />
|
||||
</clipPath>
|
||||
</defs>
|
||||
|
||||
<style>
|
||||
@media (prefers-color-scheme: dark) {
|
||||
.bg { fill: #0F172A !important; }
|
||||
.editor { fill: #1E293B !important; stroke: #34D399 !important; }
|
||||
.text-block { fill: #475569 !important; }
|
||||
.preview-block { fill: #059669 !important; opacity: 0.15 !important; }
|
||||
.sync-arrow { stroke: #6EE7B7 !important; }
|
||||
.eye-bg { fill: #059669 !important; }
|
||||
.eye-fg { fill: #D1FAE5 !important; }
|
||||
}
|
||||
@keyframes typing {
|
||||
0% { transform: translateX(-100%); }
|
||||
40% { transform: translateX(0); }
|
||||
60% { transform: translateX(0); }
|
||||
100% { transform: translateX(-100%); }
|
||||
}
|
||||
@keyframes preview {
|
||||
0% { transform: translateX(20px); opacity: 0; }
|
||||
20% { transform: translateX(0); opacity: 1; }
|
||||
80% { transform: translateX(0); opacity: 1; }
|
||||
100% { transform: translateX(20px); opacity: 0; }
|
||||
}
|
||||
@keyframes sync {
|
||||
0% { transform: translateX(-3px); }
|
||||
50% { transform: translateX(3px); }
|
||||
100% { transform: translateX(-3px); }
|
||||
}
|
||||
@keyframes eye-blink {
|
||||
0%, 90%, 100% { transform: scaleY(1); }
|
||||
95% { transform: scaleY(0.1); }
|
||||
}
|
||||
.typing-content {
|
||||
animation: typing 4s linear infinite;
|
||||
}
|
||||
.preview-content {
|
||||
animation: preview 4s linear infinite;
|
||||
}
|
||||
.sync-arrow {
|
||||
animation: sync 1s ease-in-out infinite;
|
||||
}
|
||||
.eye-icon {
|
||||
animation: eye-blink 2.5s linear infinite;
|
||||
}
|
||||
.glow {
|
||||
filter: drop-shadow(0 0 8px rgba(52, 211, 153, 0.3));
|
||||
}
|
||||
</style>
|
||||
|
||||
<!-- 背景 -->
|
||||
<rect class="bg" width="600" height="400" fill="#ECFDF5"/>
|
||||
|
||||
<!-- 分屏效果 -->
|
||||
<rect class="editor glow" x="20" y="50" width="270" height="300" rx="8" fill="white" stroke="#34D399" stroke-width="2"/>
|
||||
<rect class="editor glow" x="310" y="50" width="270" height="300" rx="8" fill="white" stroke="#34D399" stroke-width="2"/>
|
||||
|
||||
<!-- 编辑区域 -->
|
||||
<g clip-path="url(#typing-clip)">
|
||||
<g class="typing-content">
|
||||
<rect class="text-block" x="40" y="70" width="200" height="20" rx="4" fill="#D1FAE5"/>
|
||||
<rect class="text-block" x="40" y="100" width="150" height="20" rx="4" fill="#D1FAE5"/>
|
||||
</g>
|
||||
</g>
|
||||
|
||||
<!-- 预览区域 -->
|
||||
<g class="preview-content">
|
||||
<rect class="preview-block" x="330" y="70" width="200" height="20" rx="4" fill="#34D399" opacity="0.2"/>
|
||||
<rect class="preview-block" x="330" y="100" width="150" height="20" rx="4" fill="#34D399" opacity="0.2"/>
|
||||
</g>
|
||||
|
||||
<!-- 同步指示箭头 -->
|
||||
<g class="sync-arrow glow">
|
||||
<path d="M290 200 L310 200" stroke="#10B981" stroke-width="2"/>
|
||||
<path d="M305 195 L310 200 L305 205" stroke="#10B981" stroke-width="2"/>
|
||||
</g>
|
||||
|
||||
<!-- 实时预览图标 -->
|
||||
<circle class="eye-bg glow" cx="300" cy="200" r="15" fill="#10B981"/>
|
||||
<g class="eye-icon">
|
||||
<text class="eye-fg" x="293" y="205" fill="white" font-family="Arial" font-size="12">👁️</text>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 3.1 KiB |
@@ -19,14 +19,15 @@ export async function POST(req: NextRequest) {
|
||||
body: JSON.stringify({
|
||||
model: modelConfig.requiresModelId ? model : modelConfig.defaultModel,
|
||||
response_format: {
|
||||
type: "json_object",
|
||||
type: "json_object"
|
||||
},
|
||||
messages: [
|
||||
{
|
||||
role: "system",
|
||||
content: `你是一个专业的中文简历错别字检查助手。请帮助检查以下文本,以下是要求:
|
||||
1.仅需考虑组词中的错别字,不要考虑语法和格式错误。
|
||||
2.对每个发现的问题,请按JSON格式返回
|
||||
content: `你是一个专业的中文简历错别字检查助手。请完整检查以下文本,不要遗漏,以下是要求:
|
||||
1.所有考虑中文语境下的语法组词错误,包括拼写错误,语境用词错误,专业术语错误。
|
||||
2.验证是否有遗漏文字未检查
|
||||
3.对每个发现的问题,请按JSON格式返回
|
||||
|
||||
以下是示例格式:
|
||||
{
|
||||
@@ -40,14 +41,14 @@ export async function POST(req: NextRequest) {
|
||||
]
|
||||
}
|
||||
|
||||
请确保返回的格式可以正常解析`,
|
||||
请确保返回的格式可以正常解析`
|
||||
},
|
||||
{
|
||||
role: "user",
|
||||
content: content,
|
||||
},
|
||||
],
|
||||
}),
|
||||
content: content
|
||||
}
|
||||
]
|
||||
})
|
||||
});
|
||||
|
||||
const data = await response.json();
|
||||
|
||||
@@ -1,37 +1,37 @@
|
||||
"use client";
|
||||
|
||||
import { CheckCircle2 } from "lucide-react";
|
||||
import { useTranslations } from "next-intl";
|
||||
import Image from "next/image";
|
||||
import { useState } from "react";
|
||||
import AnimatedFeature from "./client/AnimatedFeature";
|
||||
|
||||
const features = [
|
||||
{
|
||||
title: "features.ai.title",
|
||||
description: "features.ai.description",
|
||||
items: ["features.ai.item1", "features.ai.item2", "features.ai.item3"],
|
||||
},
|
||||
{
|
||||
title: "features.storage.title",
|
||||
description: "features.storage.description",
|
||||
items: [
|
||||
"features.storage.item1",
|
||||
"features.storage.item2",
|
||||
"features.storage.item3",
|
||||
],
|
||||
},
|
||||
{
|
||||
title: "features.preview.title",
|
||||
description: "features.preview.description",
|
||||
items: ["features.preview.item1", "features.preview.item2"],
|
||||
},
|
||||
];
|
||||
{
|
||||
title: "features.ai.item1",
|
||||
image: "/features/polish.png"
|
||||
},
|
||||
{
|
||||
title: "features.ai.item2",
|
||||
image: "/features/grammar.png"
|
||||
}
|
||||
]
|
||||
}
|
||||
] as const;
|
||||
|
||||
export default function FeaturesSection() {
|
||||
const t = useTranslations("home");
|
||||
const [activeFeature, setActiveFeature] = useState(0);
|
||||
|
||||
return (
|
||||
<section className="py-20 md:py-32 bg-gradient-to-b from-background to-primary/5">
|
||||
<div className="mx-auto max-w-[1200px] px-4">
|
||||
<AnimatedFeature>
|
||||
<div className="text-center mb-12 md:mb-20">
|
||||
<div className="text-center mb-16 md:mb-24">
|
||||
<h2 className="text-3xl md:text-4xl font-bold mb-4 md:mb-6">
|
||||
{t("features.title")}
|
||||
</h2>
|
||||
@@ -41,28 +41,52 @@ export default function FeaturesSection() {
|
||||
</div>
|
||||
</AnimatedFeature>
|
||||
|
||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-6 md:gap-12">
|
||||
{features.map((feature, index) => (
|
||||
<AnimatedFeature key={index} delay={index * 0.2}>
|
||||
<div className="relative group">
|
||||
<div className="absolute inset-0 bg-gradient-to-b from-primary/5 to-transparent rounded-2xl -z-10 transition-transform duration-300 group-hover:scale-105" />
|
||||
<div className="h-[360px] p-8 bg-white dark:bg-gray-900 rounded-2xl border border-gray-100 dark:border-gray-800 shadow-[0_0_18px_1px_rgba(140,140,140,0.12)] transition-all duration-300 group-hover:border-[#A700FF] dark:group-hover:border-[#A700FF] flex flex-col">
|
||||
<h3 className="text-2xl font-bold mb-12">
|
||||
{t(feature.title)}
|
||||
</h3>
|
||||
|
||||
<ul className="space-y-3">
|
||||
{feature.items.map((item, i) => (
|
||||
<li key={i} className="flex items-start gap-3">
|
||||
<CheckCircle2 className="w-5 h-5 text-primary mt-1" />
|
||||
<span>{t(item)}</span>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
<div className="space-y-24 md:space-y-32">
|
||||
<div className="flex flex-col md:flex-row gap-8 md:gap-16 items-center">
|
||||
<div className="w-full md:w-[400px] space-y-6 md:mr-16">
|
||||
<h3 className="text-2xl md:text-3xl font-bold text-center md:text-left">
|
||||
{t(features[0].title)}
|
||||
</h3>
|
||||
<ul className="space-y-4">
|
||||
{features[0].items.map((item, index) => (
|
||||
<li
|
||||
key={index}
|
||||
onClick={() => setActiveFeature(index)}
|
||||
className={`flex items-center gap-3 cursor-pointer relative p-2 rounded-lg transition-all ${
|
||||
activeFeature === index ? "bg-primary/10" : ""
|
||||
}`}
|
||||
>
|
||||
<span className="text-sm font-medium text-muted-foreground w-6">
|
||||
{String(index + 1).padStart(2, "0")}
|
||||
</span>
|
||||
<span
|
||||
className={`${
|
||||
activeFeature === index
|
||||
? "text-primary font-medium"
|
||||
: "text-muted-foreground"
|
||||
}`}
|
||||
>
|
||||
{t(item.title)}
|
||||
</span>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
<div className="flex-1 w-full md:w-auto relative">
|
||||
<AnimatedFeature key={activeFeature}>
|
||||
<div className="relative aspect-[3/2] w-full overflow-hidden rounded-xl border border-gray-100 dark:border-gray-800 bg-white dark:bg-gray-900">
|
||||
<Image
|
||||
src={features[0].items[activeFeature].image}
|
||||
alt={t(features[0].items[activeFeature].title)}
|
||||
fill
|
||||
className="object-contain p-4 md:p-8"
|
||||
sizes="(max-width: 768px) 100vw, 50vw"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</AnimatedFeature>
|
||||
))}
|
||||
<div className="absolute inset-0 bg-gradient-to-tr from-primary/5 via-blue-500/5 to-purple-500/5 rounded-xl -z-10 blur-2xl" />
|
||||
</AnimatedFeature>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
@@ -32,8 +32,7 @@
|
||||
"badge": "AI Smart Check",
|
||||
"title": "Smart Detection, Professional Advice",
|
||||
"item1": "Intelligent enhancement recommendations",
|
||||
"item2": "Automatic error correction and grammar check",
|
||||
"item3": "Personalized content recommendations"
|
||||
"item2": "Automatic error correction and grammar check"
|
||||
},
|
||||
"storage": {
|
||||
"badge": "Local Storage",
|
||||
|
||||
@@ -32,9 +32,8 @@
|
||||
"badge": "AI 智能纠错",
|
||||
"title": "智能识别,专业建议",
|
||||
"description": "内置智能语法检查,自动识别不恰当的表达,提供专业的修改建议,让您的简历更加出色。",
|
||||
"item1": "智能润色和优化建议",
|
||||
"item2": "自动纠错和语法检查",
|
||||
"item3": "个性化内容推荐"
|
||||
"item1": "智能润色",
|
||||
"item2": "语法检查"
|
||||
},
|
||||
"storage": {
|
||||
"badge": "本地存储",
|
||||
|
||||
Reference in New Issue
Block a user