feat: add initial English resume data with detailed sections for profile, skills, experience, and education

This commit is contained in:
JOYCEQL
2025-03-03 13:19:53 +08:00
committed by qingchen
parent f0e656cf99
commit e1c01ac8eb
2 changed files with 216 additions and 43 deletions
+159
View File
@@ -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
View File
@@ -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",
}
)
);