diff --git a/apps/fronted/src/components/editor/PreviewPanel.tsx b/apps/fronted/src/components/editor/PreviewPanel.tsx index c99956a..39735d4 100644 --- a/apps/fronted/src/components/editor/PreviewPanel.tsx +++ b/apps/fronted/src/components/editor/PreviewPanel.tsx @@ -1,10 +1,11 @@ "use client"; -import React from "react"; +import React, { useMemo } from "react"; import { AnimatePresence, motion } from "framer-motion"; import { useResumeStore } from "@/store/useResumeStore"; import { cn } from "@/lib/utils"; import { throttle } from "lodash"; +import { THEME_COLORS } from "@/types/resume"; const getFontFamilyClass = (fontFamily: string) => { switch (fontFamily) { @@ -26,7 +27,8 @@ export function PreviewPanel() { menuSections, globalSettings, projects, - draggingProjectId + draggingProjectId, + colorTheme } = useResumeStore(); const previewRef = React.useRef(null); const [scrollBehavior, setScrollBehavior] = @@ -36,6 +38,18 @@ export function PreviewPanel() { globalSettings?.fontFamily || "sans" ); + // 获取当前主题色 + const currentThemeColor = useMemo(() => { + return colorTheme || THEME_COLORS[0]; + }, [colorTheme]); + + // 标题样式的公共配置 + const sectionTitleStyles = { + fontSize: `${globalSettings?.headerSize || 18}px`, + borderColor: currentThemeColor, // 使用主题色作为下边框颜色 + color: currentThemeColor // 使用主题色作为文字颜色 + }; + // 处理自动滚动 const handleScroll = React.useCallback( throttle((offset: number) => { @@ -101,9 +115,7 @@ export function PreviewPanel() { >

项目经历

@@ -180,7 +192,7 @@ export function PreviewPanel() { layout className={cn("text-gray-600")} style={{ - fontSize: `${globalSettings?.contentFontSize || 14}px` + fontSize: `${globalSettings?.baseFontSize || 14}px` }} > {project.role} @@ -190,7 +202,7 @@ export function PreviewPanel() { layout className={cn("text-gray-600")} style={{ - fontSize: `${globalSettings?.contentFontSize || 14}px` + fontSize: `${globalSettings?.baseFontSize || 14}px` }} > {project.date} @@ -203,7 +215,7 @@ export function PreviewPanel() { layout className={cn("whitespace-pre-wrap", "text-gray-600")} style={{ - fontSize: `${globalSettings?.contentFontSize || 14}px`, + fontSize: `${globalSettings?.baseFontSize || 14}px`, lineHeight: globalSettings?.lineHeight || 1.6 }} > @@ -220,7 +232,7 @@ export function PreviewPanel() { layout className={cn("font-medium", "text-gray-800")} style={{ - fontSize: `${globalSettings?.contentFontSize || 14}px` + fontSize: `${globalSettings?.baseFontSize || 14}px` }} > 技术栈: @@ -229,7 +241,7 @@ export function PreviewPanel() { layout className={cn("whitespace-pre-wrap", "text-gray-600")} style={{ - fontSize: `${globalSettings?.contentFontSize || 14}px`, + fontSize: `${globalSettings?.baseFontSize || 14}px`, lineHeight: globalSettings?.lineHeight || 1.6 }} > @@ -245,7 +257,7 @@ export function PreviewPanel() { layout className={cn("font-medium", "text-gray-800")} style={{ - fontSize: `${globalSettings?.contentFontSize || 14}px` + fontSize: `${globalSettings?.baseFontSize || 14}px` }} > 主要职责: @@ -254,7 +266,7 @@ export function PreviewPanel() { layout className={cn("whitespace-pre-wrap", "text-gray-600")} style={{ - fontSize: `${globalSettings?.contentFontSize || 14}px`, + fontSize: `${globalSettings?.baseFontSize || 14}px`, lineHeight: globalSettings?.lineHeight || 1.6 }} > @@ -270,7 +282,7 @@ export function PreviewPanel() { layout className={cn("font-medium", "text-gray-800")} style={{ - fontSize: `${globalSettings?.contentFontSize || 14}px` + fontSize: `${globalSettings?.baseFontSize || 14}px` }} > 项目成就: @@ -279,7 +291,7 @@ export function PreviewPanel() { layout className={cn("whitespace-pre-wrap", "text-gray-600")} style={{ - fontSize: `${globalSettings?.contentFontSize || 14}px`, + fontSize: `${globalSettings?.baseFontSize || 14}px`, lineHeight: globalSettings?.lineHeight || 1.6 }} > @@ -293,8 +305,6 @@ export function PreviewPanel() { ); - // ... 其他 section 渲染函数 ... - const renderSection = (sectionId: string) => { switch (sectionId) { case "basic": @@ -302,16 +312,14 @@ export function PreviewPanel() {

个人简介

@@ -331,9 +339,7 @@ export function PreviewPanel() { >

教育经历

@@ -358,7 +364,7 @@ export function PreviewPanel() {

{edu.degree} @@ -367,7 +373,7 @@ export function PreviewPanel() { {edu.date} @@ -376,7 +382,7 @@ export function PreviewPanel() {

@@ -398,9 +404,7 @@ export function PreviewPanel() { >

工作经验

@@ -425,7 +429,7 @@ export function PreviewPanel() {

{exp.position} @@ -434,7 +438,7 @@ export function PreviewPanel() { {exp.date} @@ -443,7 +447,7 @@ export function PreviewPanel() {

@@ -455,7 +459,6 @@ export function PreviewPanel() { ); case "projects": return renderProjects(); - // ... 其他 case default: return null; } @@ -512,7 +515,7 @@ export function PreviewPanel() { layout="position" className="flex justify-center items-center space-x-4 flex-wrap" style={{ - fontSize: `${globalSettings?.contentFontSize || 14}px`, + fontSize: `${globalSettings?.baseFontSize || 14}px`, color: "rgb(75, 85, 99)" }} > diff --git a/apps/fronted/src/components/editor/SidePanel.tsx b/apps/fronted/src/components/editor/SidePanel.tsx index 943af02..a8071ec 100644 --- a/apps/fronted/src/components/editor/SidePanel.tsx +++ b/apps/fronted/src/components/editor/SidePanel.tsx @@ -7,7 +7,9 @@ import { EyeOff, Layout, Type, - SpaceIcon + SpaceIcon, + Palette, + Plus } from "lucide-react"; import { useResumeStore } from "@/store/useResumeStore"; import { getThemeConfig } from "@/theme/themeConfig"; @@ -22,6 +24,9 @@ import { Slider } from "@/components/ui/slider"; import { Label } from "@/components/ui/label"; import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; import { cn } from "@/lib/utils"; +import { THEME_COLORS } from "@/types/resume"; +import debounce from "lodash/debounce"; +import { useMemo } from "react"; const fontOptions = [ { value: "sans", label: "无衬线体" }, @@ -79,9 +84,19 @@ export function SidePanel() { toggleSectionVisibility, setActiveSection, globalSettings, - updateGlobalSettings + updateGlobalSettings, + colorTheme, + setColorTheme } = useResumeStore(); + const debouncedSetColor = useMemo( + () => + debounce((value) => { + setColorTheme(value); + }, 100), + [] + ); + return ( + {/* 主题色设置 */} + + +

+
+ {THEME_COLORS.map((presetTheme) => ( + + ))} +
+ +
+
+ 自定义 +
+ debouncedSetColor(e.target.value)} + className="w-[40px] h-[40px] rounded-lg cursor-pointer overflow-hidden hover:scale-105 transition-transform" + /> +
+
+ + {/* 排版设置 */}
diff --git a/apps/fronted/src/store/useResumeStore.ts b/apps/fronted/src/store/useResumeStore.ts index cbdb6e4..2623cdf 100644 --- a/apps/fronted/src/store/useResumeStore.ts +++ b/apps/fronted/src/store/useResumeStore.ts @@ -7,7 +7,8 @@ import { Education, Experience, GlobalSettings, - Project + Project, + ResumeTheme } from "../types/resume"; interface ResumeStore { @@ -29,6 +30,11 @@ interface ResumeStore { theme: "light" | "dark"; activeSection: string; + colorTheme: string; // 当前使用的主题色 ID + + // 新增 Actions + setColorTheme: (colorTheme: string) => void; + // Actions updateBasicInfo: (data: Partial) => void; updateEducation: (id: string, data: Partial) => void; @@ -93,6 +99,10 @@ const initialState = { { id: "projects", title: "项目经历", icon: "🚀", enabled: true, order: 4 } ], theme: "light" as const, + + // 主题色 + colorTheme: "#2563eb", // 默认使用经典蓝主题 + activeSection: "basic", projects: [ { @@ -128,6 +138,11 @@ export const useResumeStore = create()( persist( (set) => ({ ...initialState, + setColorTheme: (colorTheme) => { + console.log(colorTheme, "colorTheme"); + set({ colorTheme }); + }, + setDraggingProjectId: (id) => set({ draggingProjectId: id }), updateBasicInfo: (data) => diff --git a/apps/fronted/src/types/resume.ts b/apps/fronted/src/types/resume.ts index c9e45cf..731f1e2 100644 --- a/apps/fronted/src/types/resume.ts +++ b/apps/fronted/src/types/resume.ts @@ -68,3 +68,45 @@ export type GlobalSettings = { pagePadding: number; paragraphSpacing: number; }; + +export interface ThemeColors { + primary: string; // 主色 + secondary: string; // 次要色 + text: { + primary: string; // 主要文字颜色 + secondary: string; // 次要文字颜色 + accent: string; // 强调文字颜色 + }; + background: { + primary: string; // 主要背景色 + secondary: string; // 次要背景色 + accent: string; // 强调背景色 + }; + border: string; // 边框颜色 + divider: string; // 分割线颜色 +} + +export interface ResumeTheme { + id: string; + name: string; + color: string; +} + +export const THEME_COLORS = [ + "#2563eb", // 经典蓝 + "#059669", // 翡翠绿 + "#7c3aed", // 优雅紫 + "#e11d48", // 玫瑰红 + "#d97706", // 琥珀金 + "#0891b2", // 青碧蓝 + "#4f46e5", // 靛青蓝 + "#0d9488", // 青蓝绿 + "#0284c7", // 天际蓝 + "#6d28d9", // 雅致紫 + "#c026d3", // 绯紫红 + "#db2777", // 粉红色 + "#ea580c", // 活力橙 + "#65a30d", // 青柠绿 + "#475569", // 岩石灰 + "#dc2626" // 中国红 +];