From 54991dc2e395a910c81e0caac770e46b6e50023f Mon Sep 17 00:00:00 2001 From: siyue Date: Sun, 27 Oct 2024 22:57:15 +0800 Subject: [PATCH] feat: project drag style --- .../src/components/editor/PreviewPanel.tsx | 606 ++++++++---------- .../components/editor/project/ProjectItem.tsx | 10 + apps/fronted/src/store/useResumeStore.ts | 4 + 3 files changed, 279 insertions(+), 341 deletions(-) diff --git a/apps/fronted/src/components/editor/PreviewPanel.tsx b/apps/fronted/src/components/editor/PreviewPanel.tsx index 129b134..11b3fa5 100644 --- a/apps/fronted/src/components/editor/PreviewPanel.tsx +++ b/apps/fronted/src/components/editor/PreviewPanel.tsx @@ -2,8 +2,8 @@ import { AnimatePresence, motion } from "framer-motion"; import { useResumeStore } from "@/store/useResumeStore"; -import { getThemeConfig } from "@/theme/themeConfig"; import { cn } from "@/lib/utils"; +import React, { useEffect } from "react"; const getFontFamilyClass = (fontFamily: string) => { switch (fontFamily) { @@ -24,336 +24,248 @@ export function PreviewPanel() { experience, menuSections, globalSettings, - projects + projects, + draggingProjectId } = useResumeStore(); - console.log(projects, 111); const fontFamilyClass = getFontFamilyClass( globalSettings?.fontFamily || "sans" ); + useEffect(() => { + console.log(draggingProjectId, "draggingProjectId"); + }, [draggingProjectId]); + + const renderProjects = () => ( + +

+ 项目经历 +

+ + {projects.map((project) => ( + + {/* 拖拽时的高光效果 */} + {draggingProjectId === project.id && ( + +
+
+
+ + )} + + + + + {project.name || "未命名项目"} + + + {project.role} + + + + {project.date} + + + + {project.description && ( + + {project.description} + + )} + + {project.technologies && ( + + + 技术栈: + + + {project.technologies} + + + )} + + {project.responsibilities && ( + + + 主要职责: + + + {project.responsibilities} + + + )} + + {project.achievements && ( + + + 项目成就: + + + {project.achievements} + + + )} + + ))} + + + ); + + // 其他 section 的渲染函数保持不变... + const renderSection = (sectionId: string) => { switch (sectionId) { - case "basic": - return ( - -

- 个人简介 -

-

- {basic.summary} -

-
- ); - - case "education": - return ( - -

- 教育经历 -

- {education.map((edu) => ( -
-
-
-

- {edu.school} -

-

- {edu.degree} -

-
- - {edu.date} - -
-

- {edu.details} -

-
- ))} -
- ); - - case "experience": - return ( - -

- 工作经验 -

- {experience.map((exp) => ( -
-
-
-

- {exp.company} -

-

- {exp.position} -

-
- - {exp.date} - -
-

- {exp.details} -

-
- ))} -
- ); case "projects": - return ( - -

- 项目经历 -

- - {projects.map((project) => ( - - - - - {project.name} - - - {project.role} - - - - {project.date} - - - - {/* 项目描述 */} - {project.description && ( - - {project.description} - - )} - - {/* 技术栈 */} - {project.technologies && ( - - - 技术栈: - - - {project.technologies} - - - )} - - {/* 主要职责 */} - {project.responsibilities && ( - - - 主要职责: - - - {project.responsibilities} - - - )} - - {/* 项目成就 */} - {project.achievements && ( - - - 项目成就: - - - {project.achievements} - - - )} - - ))} - -
- ); + return renderProjects(); + // 其他 case 保持不变... default: return null; } @@ -365,11 +277,10 @@ export function PreviewPanel() { "flex-1 overflow-y-auto", theme === "dark" ? "bg-neutral-900" : "bg-gray-100" )} - initial={{ x: 100, opacity: 0 }} - animate={{ x: 0, opacity: 1 }} + initial={{ opacity: 0 }} + animate={{ opacity: 1 }} >
- {/* A4 纸张容器 */} - {/* 内容区域 */}
- {basic.email} - - {basic.phone} - - {basic.location} - - - {basic.birthDate + {[ + basic.email, + basic.phone, + basic.location, + basic.birthDate ? new Date(basic.birthDate).toLocaleDateString() - : ""} - + : "" + ] + .filter(Boolean) + .map((item, index, array) => ( + + {item} + {index < array.length - 1 && } + + ))}
diff --git a/apps/fronted/src/components/editor/project/ProjectItem.tsx b/apps/fronted/src/components/editor/project/ProjectItem.tsx index d447b13..4fa6adf 100644 --- a/apps/fronted/src/components/editor/project/ProjectItem.tsx +++ b/apps/fronted/src/components/editor/project/ProjectItem.tsx @@ -136,6 +136,9 @@ const ProjectItem = ({ project }: { project: Project }) => { value={project} dragListener={false} dragControls={dragControls} + onDragEnd={() => { + useResumeStore.getState().setDraggingProjectId(null); + }} className={cn( "rounded-lg border overflow-hidden flex group", theme === "dark" @@ -148,6 +151,13 @@ const ProjectItem = ({ project }: { project: Project }) => { onPointerDown={(event) => { if (expandedId === project.id) return; dragControls.start(event); + useResumeStore.getState().setDraggingProjectId(project.id); + }} + onPointerUp={() => { + useResumeStore.getState().setDraggingProjectId(null); + }} + onPointerCancel={() => { + useResumeStore.getState().setDraggingProjectId(null); }} className={cn( "w-12 flex items-center justify-center border-r shrink-0 touch-none", diff --git a/apps/fronted/src/store/useResumeStore.ts b/apps/fronted/src/store/useResumeStore.ts index a7c7905..2501afb 100644 --- a/apps/fronted/src/store/useResumeStore.ts +++ b/apps/fronted/src/store/useResumeStore.ts @@ -46,9 +46,12 @@ interface ResumeStore { projects: Project[]; updateProjects: (project: Project) => void; deleteProject: (id: string) => void; + draggingProjectId: string | null; + setDraggingProjectId: (id: string | null) => void; } const initialState = { + draggingProjectId: null, basic: { name: "张三", title: "高级前端工程师", @@ -123,6 +126,7 @@ export const useResumeStore = create()( persist( (set) => ({ ...initialState, + setDraggingProjectId: (id) => set({ draggingProjectId: id }), updateBasicInfo: (data) => set((state) => ({ basic: { ...state.basic, ...data } })),