mirror of
https://github.com/JOYCEQL/magic-resume.git
synced 2026-07-03 14:07:11 +02:00
feat: add initial English resume data with detailed sections for profile, skills, experience, and education
This commit is contained in:
@@ -167,3 +167,162 @@ export const initialResumeState = {
|
||||
activeSection: "basic",
|
||||
globalSettings: initialGlobalSettings,
|
||||
};
|
||||
|
||||
export const initialResumeStateEn = {
|
||||
title: "New Resume",
|
||||
basic: {
|
||||
name: "John Smith",
|
||||
title: "Senior Frontend Engineer",
|
||||
employementStatus: "Available",
|
||||
email: "john.smith@123.com",
|
||||
phone: "555-123-4567",
|
||||
location: "San Francisco, CA",
|
||||
birthDate: "",
|
||||
fieldOrder: DEFAULT_FIELD_ORDER,
|
||||
icons: {
|
||||
email: "Mail",
|
||||
phone: "Phone",
|
||||
birthDate: "CalendarRange",
|
||||
employementStatus: "Briefcase",
|
||||
location: "MapPin",
|
||||
},
|
||||
photoConfig: DEFAULT_CONFIG,
|
||||
customFields: [],
|
||||
photo: "/avatar.png",
|
||||
githubKey: "",
|
||||
githubUseName: "",
|
||||
githubContributionsVisible: false,
|
||||
},
|
||||
education: [
|
||||
{
|
||||
id: "1",
|
||||
school: "Stanford University",
|
||||
major: "Computer Science",
|
||||
degree: "",
|
||||
startDate: "2013-09",
|
||||
endDate: "2017-06",
|
||||
visible: true,
|
||||
gpa: "",
|
||||
description: `<ul class="custom-list">
|
||||
<li>Core courses: Data Structures, Algorithms, Operating Systems, Computer Networks, Web Development</li>
|
||||
<li>Top 5% of class, received Dean's List honors for three consecutive years</li>
|
||||
<li>Served as Technical Director of the Computer Science Association, organized multiple tech workshops</li>
|
||||
<li>Contributed to open-source projects, earned GitHub Campus Expert certification</li>
|
||||
</ul>`,
|
||||
},
|
||||
],
|
||||
skillContent: `<div class="skill-content">
|
||||
<ul class="custom-list">
|
||||
<li>Frontend Frameworks: React, Vue.js, Next.js, Nuxt.js and other SSR frameworks</li>
|
||||
<li>Languages: TypeScript, JavaScript(ES6+), HTML5, CSS3</li>
|
||||
<li>UI/Styling: TailwindCSS, Sass/Less, CSS Modules, Styled-components</li>
|
||||
<li>State Management: Redux, Vuex, Zustand, Jotai, React Query</li>
|
||||
<li>Build Tools: Webpack, Vite, Rollup, Babel, ESLint</li>
|
||||
<li>Testing: Jest, React Testing Library, Cypress</li>
|
||||
<li>Performance: Browser rendering principles, performance metrics monitoring, code splitting, lazy loading</li>
|
||||
<li>Version Control: Git, SVN</li>
|
||||
<li>Technical Leadership: Team management experience, led technology selection and architecture design for large projects</li>
|
||||
</ul>
|
||||
</div>`,
|
||||
experience: [
|
||||
{
|
||||
id: "1",
|
||||
company: "ByteDance",
|
||||
position: "Senior Frontend Engineer",
|
||||
date: "2021/7 - Present",
|
||||
visible: true,
|
||||
details: `<ul class="custom-list">
|
||||
<li>Responsible for development and maintenance of TikTok Creator Platform, leading technical solution design for core features</li>
|
||||
<li>Optimized build configuration, reducing build time from 8 minutes to 2 minutes, improving team development efficiency</li>
|
||||
<li>Designed and implemented component library, increasing code reuse by 70%, significantly reducing development time</li>
|
||||
<li>Led performance optimization project, reducing platform first-screen loading time by 50%, integrated APM monitoring system</li>
|
||||
<li>Mentored junior engineers, organized technical sharing sessions to improve overall team technical capabilities</li>
|
||||
</ul>`,
|
||||
},
|
||||
],
|
||||
draggingProjectId: null,
|
||||
projects: [
|
||||
{
|
||||
id: "p1",
|
||||
name: "TikTok Creator Platform",
|
||||
role: "Frontend Lead",
|
||||
date: "2022/6 - 2023/12",
|
||||
description: `<ul class="custom-list">
|
||||
<li>React-based analytics and content management platform serving millions of creators</li>
|
||||
<li>Includes data analytics, content management, and revenue management subsystems</li>
|
||||
<li>Implemented Redux for state management, enabling efficient handling of complex data flows</li>
|
||||
<li>Used Ant Design component library to ensure UI consistency and user experience</li>
|
||||
<li>Implemented code splitting and lazy loading strategies to optimize loading performance</li>
|
||||
</ul>`,
|
||||
visible: true,
|
||||
},
|
||||
{
|
||||
id: "p2",
|
||||
name: "WeChat Mini Program Developer Tools",
|
||||
role: "Core Developer",
|
||||
date: "2020/3 - 2021/6",
|
||||
description: `<ul class="custom-list">
|
||||
<li>All-in-one solution for mini program development, debugging, and publishing</li>
|
||||
<li>Cross-platform desktop application built with Electron</li>
|
||||
<li>Supports multiple platforms including Windows, macOS, and Linux</li>
|
||||
<li>Provides real-time error logging and performance analysis tools</li>
|
||||
<li>Integrates third-party plugins and SDKs for custom functionality</li>
|
||||
</ul>`,
|
||||
visible: true,
|
||||
},
|
||||
{
|
||||
id: "p3",
|
||||
name: "Frontend Monitoring Platform",
|
||||
role: "Technical Lead",
|
||||
date: "9/2021 - 5/2022",
|
||||
description: `<ul class="custom-list">
|
||||
<li>Complete frontend monitoring solution including error tracking, performance monitoring, and user behavior analysis</li>
|
||||
<li>Built with Vue and Element UI, providing real-time monitoring data and visualization tools</li>
|
||||
<li>Supports various monitoring metrics including error logs, performance indicators, and user behavior analysis</li>
|
||||
<li>Provides detailed error logs and performance analysis tools to help developers identify and optimize issues</li>
|
||||
<li>Integrates third-party plugins and SDKs for custom functionality</li>
|
||||
</ul>`,
|
||||
visible: true,
|
||||
},
|
||||
],
|
||||
menuSections: [
|
||||
{
|
||||
id: "basic",
|
||||
title: "Profile",
|
||||
icon: "👤",
|
||||
enabled: true,
|
||||
order: 0,
|
||||
},
|
||||
{
|
||||
id: "skills",
|
||||
title: "Skills",
|
||||
icon: "⚡",
|
||||
enabled: true,
|
||||
order: 1,
|
||||
},
|
||||
{
|
||||
id: "experience",
|
||||
title: "Experience",
|
||||
icon: "💼",
|
||||
enabled: true,
|
||||
order: 2,
|
||||
},
|
||||
{
|
||||
id: "projects",
|
||||
title: "Experience",
|
||||
icon: "🚀",
|
||||
enabled: true,
|
||||
order: 3,
|
||||
},
|
||||
{
|
||||
id: "education",
|
||||
title: "Education",
|
||||
icon: "🎓",
|
||||
enabled: true,
|
||||
order: 4,
|
||||
},
|
||||
],
|
||||
customData: {},
|
||||
activeSection: "basic",
|
||||
globalSettings: initialGlobalSettings,
|
||||
};
|
||||
|
||||
+57
-43
@@ -9,11 +9,15 @@ import {
|
||||
Project,
|
||||
CustomItem,
|
||||
ResumeData,
|
||||
MenuSection
|
||||
MenuSection,
|
||||
} from "../types/resume";
|
||||
import { DEFAULT_TEMPLATES } from "@/config";
|
||||
import { initialResumeState } from "@/config/initialResumeData";
|
||||
import {
|
||||
initialResumeState,
|
||||
initialResumeStateEn,
|
||||
} from "@/config/initialResumeData";
|
||||
import { generateUUID } from "@/utils/uuid";
|
||||
import { getLocale } from "next-intl/server";
|
||||
interface ResumeStore {
|
||||
resumes: Record<string, ResumeData>;
|
||||
activeResumeId: string | null;
|
||||
@@ -93,7 +97,7 @@ const syncResumeToFile = async (
|
||||
|
||||
const fileName = `${resumeData.title}.json`;
|
||||
const fileHandle = await dirHandle.getFileHandle(fileName, {
|
||||
create: true
|
||||
create: true,
|
||||
});
|
||||
const writable = await fileHandle.createWritable();
|
||||
await writable.write(JSON.stringify(resumeData, null, 2));
|
||||
@@ -111,27 +115,37 @@ export const useResumeStore = create(
|
||||
activeResume: null,
|
||||
|
||||
createResume: (templateId = null) => {
|
||||
// 判断当前语言环境
|
||||
const locale =
|
||||
typeof window !== "undefined"
|
||||
? window.navigator.language.split("-")[0]
|
||||
: "en";
|
||||
console.log("locale", locale);
|
||||
|
||||
const initialResumeData =
|
||||
locale === "en" ? initialResumeStateEn : initialResumeState;
|
||||
|
||||
const id = generateUUID();
|
||||
const template = templateId
|
||||
? DEFAULT_TEMPLATES.find((t) => t.id === templateId)
|
||||
: DEFAULT_TEMPLATES[0];
|
||||
|
||||
const newResume: ResumeData = {
|
||||
...initialResumeState,
|
||||
...initialResumeData,
|
||||
id,
|
||||
createdAt: new Date().toISOString(),
|
||||
updatedAt: new Date().toISOString(),
|
||||
templateId: template?.id,
|
||||
title: `新建简历 ${id.slice(0, 6)}`
|
||||
title: `新建简历 ${id.slice(0, 6)}`,
|
||||
};
|
||||
|
||||
set((state) => ({
|
||||
resumes: {
|
||||
...state.resumes,
|
||||
[id]: newResume
|
||||
[id]: newResume,
|
||||
},
|
||||
activeResumeId: id,
|
||||
activeResume: newResume
|
||||
activeResume: newResume,
|
||||
}));
|
||||
|
||||
syncResumeToFile(newResume);
|
||||
@@ -146,7 +160,7 @@ export const useResumeStore = create(
|
||||
|
||||
const updatedResume = {
|
||||
...resume,
|
||||
...data
|
||||
...data,
|
||||
};
|
||||
|
||||
syncResumeToFile(updatedResume, resume);
|
||||
@@ -154,12 +168,12 @@ export const useResumeStore = create(
|
||||
return {
|
||||
resumes: {
|
||||
...state.resumes,
|
||||
[resumeId]: updatedResume
|
||||
[resumeId]: updatedResume,
|
||||
},
|
||||
activeResume:
|
||||
state.activeResumeId === resumeId
|
||||
? updatedResume
|
||||
: state.activeResume
|
||||
: state.activeResume,
|
||||
};
|
||||
});
|
||||
},
|
||||
@@ -169,8 +183,8 @@ export const useResumeStore = create(
|
||||
set((state) => ({
|
||||
resumes: {
|
||||
...state.resumes,
|
||||
[resume.id]: resume
|
||||
}
|
||||
[resume.id]: resume,
|
||||
},
|
||||
}));
|
||||
},
|
||||
|
||||
@@ -188,7 +202,7 @@ export const useResumeStore = create(
|
||||
return {
|
||||
resumes: rest,
|
||||
activeResumeId: null,
|
||||
activeResume: null
|
||||
activeResume: null,
|
||||
};
|
||||
});
|
||||
|
||||
@@ -218,7 +232,7 @@ export const useResumeStore = create(
|
||||
id: newId,
|
||||
title: `${originalResume.title} (复制)`,
|
||||
createdAt: new Date().toISOString(),
|
||||
updatedAt: new Date().toISOString()
|
||||
updatedAt: new Date().toISOString(),
|
||||
};
|
||||
get().updateResume(newId, duplicatedResume);
|
||||
get().setActiveResume(newId);
|
||||
@@ -239,16 +253,16 @@ export const useResumeStore = create(
|
||||
...state.activeResume,
|
||||
basic: {
|
||||
...state.activeResume.basic,
|
||||
...data
|
||||
}
|
||||
...data,
|
||||
},
|
||||
};
|
||||
|
||||
const newState = {
|
||||
resumes: {
|
||||
...state.resumes,
|
||||
[state.activeResume.id]: updatedResume
|
||||
[state.activeResume.id]: updatedResume,
|
||||
},
|
||||
activeResume: updatedResume
|
||||
activeResume: updatedResume,
|
||||
};
|
||||
|
||||
syncResumeToFile(updatedResume, state.activeResume);
|
||||
@@ -380,13 +394,13 @@ export const useResumeStore = create(
|
||||
);
|
||||
const reorderedSections = [
|
||||
basicInfoSection,
|
||||
...newOrder.filter((section) => section.id !== "basic")
|
||||
...newOrder.filter((section) => section.id !== "basic"),
|
||||
].map((section, index) => ({
|
||||
...section,
|
||||
order: index
|
||||
order: index,
|
||||
}));
|
||||
get().updateResume(activeResumeId, {
|
||||
menuSections: reorderedSections as MenuSection[]
|
||||
menuSections: reorderedSections as MenuSection[],
|
||||
});
|
||||
}
|
||||
},
|
||||
@@ -431,9 +445,9 @@ export const useResumeStore = create(
|
||||
subtitle: "",
|
||||
dateRange: "",
|
||||
description: "",
|
||||
visible: true
|
||||
}
|
||||
]
|
||||
visible: true,
|
||||
},
|
||||
],
|
||||
};
|
||||
get().updateResume(activeResumeId, { customData: updatedCustomData });
|
||||
}
|
||||
@@ -445,7 +459,7 @@ export const useResumeStore = create(
|
||||
const currentResume = get().resumes[activeResumeId];
|
||||
const updatedCustomData = {
|
||||
...currentResume.customData,
|
||||
[sectionId]: items
|
||||
[sectionId]: items,
|
||||
};
|
||||
get().updateResume(activeResumeId, { customData: updatedCustomData });
|
||||
}
|
||||
@@ -474,9 +488,9 @@ export const useResumeStore = create(
|
||||
subtitle: "",
|
||||
dateRange: "",
|
||||
description: "",
|
||||
visible: true
|
||||
}
|
||||
]
|
||||
visible: true,
|
||||
},
|
||||
],
|
||||
};
|
||||
get().updateResume(activeResumeId, { customData: updatedCustomData });
|
||||
}
|
||||
@@ -490,7 +504,7 @@ export const useResumeStore = create(
|
||||
...currentResume.customData,
|
||||
[sectionId]: currentResume.customData[sectionId].map((item) =>
|
||||
item.id === itemId ? { ...item, ...updates } : item
|
||||
)
|
||||
),
|
||||
};
|
||||
get().updateResume(activeResumeId, { customData: updatedCustomData });
|
||||
}
|
||||
@@ -504,7 +518,7 @@ export const useResumeStore = create(
|
||||
...currentResume.customData,
|
||||
[sectionId]: currentResume.customData[sectionId].filter(
|
||||
(item) => item.id !== itemId
|
||||
)
|
||||
),
|
||||
};
|
||||
get().updateResume(activeResumeId, { customData: updatedCustomData });
|
||||
}
|
||||
@@ -516,8 +530,8 @@ export const useResumeStore = create(
|
||||
updateResume(activeResumeId, {
|
||||
globalSettings: {
|
||||
...activeResume?.globalSettings,
|
||||
...settings
|
||||
}
|
||||
...settings,
|
||||
},
|
||||
});
|
||||
}
|
||||
},
|
||||
@@ -528,8 +542,8 @@ export const useResumeStore = create(
|
||||
updateResume(activeResumeId, {
|
||||
globalSettings: {
|
||||
...get().activeResume?.globalSettings,
|
||||
themeColor: color
|
||||
}
|
||||
themeColor: color,
|
||||
},
|
||||
});
|
||||
}
|
||||
},
|
||||
@@ -549,37 +563,37 @@ export const useResumeStore = create(
|
||||
themeColor: template.colorScheme.primary,
|
||||
sectionSpacing: template.spacing.sectionGap,
|
||||
paragraphSpacing: template.spacing.itemGap,
|
||||
pagePadding: template.spacing.contentPadding
|
||||
pagePadding: template.spacing.contentPadding,
|
||||
},
|
||||
basic: {
|
||||
...resumes[activeResumeId].basic,
|
||||
layout: template.basic.layout
|
||||
}
|
||||
layout: template.basic.layout,
|
||||
},
|
||||
};
|
||||
|
||||
set({
|
||||
resumes: {
|
||||
...resumes,
|
||||
[activeResumeId]: updatedResume
|
||||
[activeResumeId]: updatedResume,
|
||||
},
|
||||
activeResume: updatedResume
|
||||
activeResume: updatedResume,
|
||||
});
|
||||
},
|
||||
addResume: (resume: ResumeData) => {
|
||||
set((state) => ({
|
||||
resumes: {
|
||||
...state.resumes,
|
||||
[resume.id]: resume
|
||||
[resume.id]: resume,
|
||||
},
|
||||
activeResumeId: resume.id
|
||||
activeResumeId: resume.id,
|
||||
}));
|
||||
|
||||
syncResumeToFile(resume);
|
||||
return resume.id;
|
||||
}
|
||||
},
|
||||
}),
|
||||
{
|
||||
name: "resume-storage"
|
||||
name: "resume-storage",
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user