diff --git a/apps/fronted/src/app/layout.tsx b/apps/fronted/src/app/layout.tsx index d6f3112..e991ea4 100644 --- a/apps/fronted/src/app/layout.tsx +++ b/apps/fronted/src/app/layout.tsx @@ -5,7 +5,7 @@ import "./globals.css"; const inter = Inter({ subsets: ["latin"] }); export const metadata: Metadata = { - title: "魔方简历", + title: "魔法简历", description: "极度自由的在线简历编辑器" }; diff --git a/apps/fronted/src/app/workbench/compoents/Editor/RichText.tsx b/apps/fronted/src/app/workbench/compoents/Editor/RichText.tsx index 1b544dd..cd19109 100644 --- a/apps/fronted/src/app/workbench/compoents/Editor/RichText.tsx +++ b/apps/fronted/src/app/workbench/compoents/Editor/RichText.tsx @@ -31,6 +31,8 @@ import { Highlighter } from "lucide-react"; import Highlight from "@tiptap/extension-highlight"; +import { useResumeStore } from "@/store/useResumeStore"; +import { cn } from "@/lib/utils"; interface RichTextEditorProps { content: string; @@ -56,23 +58,7 @@ const COLORS = [ { label: "粉色", value: "#FF00FF" } ]; -const BG_COLORS = [ - { label: "黑色", value: "#000000" }, - { label: "深灰", value: "#333333" }, - { label: "灰色", value: "#666666" }, - { label: "红色", value: "#FF0000" }, - { label: "橙色", value: "#FF4D00" }, - { label: "橙黄", value: "#FF9900" }, - { label: "黄色", value: "#FFCC00" }, - { label: "黄绿", value: "#33CC00" }, - { label: "绿色", value: "#00CC00" }, - { label: "青色", value: "#00CCCC" }, - { label: "浅蓝", value: "#0066FF" }, - { label: "蓝色", value: "#0000FF" }, - { label: "紫色", value: "#6600FF" }, - { label: "紫红", value: "#CC00FF" }, - { label: "粉色", value: "#FF00FF" } -]; +const BG_COLORS = COLORS; interface MenuButtonProps { onClick: () => void; @@ -83,6 +69,19 @@ interface MenuButtonProps { tooltip?: string; } +interface MenuButtonProps { + onClick: () => void; + isActive?: boolean; + disabled?: boolean; + children: React.ReactNode; + className?: string; + tooltip?: string; +} + +const handleToolbarClick = (e: React.MouseEvent) => { + e.stopPropagation(); +}; + const MenuButton = ({ onClick, isActive = false, @@ -90,30 +89,51 @@ const MenuButton = ({ children, className = "", tooltip -}: MenuButtonProps) => ( - -); + {children} + + {tooltip && showTooltip && ( +
+ {tooltip} +
+ )} + + ); +}; const TextColorButton = ({ editor, tooltip }) => { const [activeColor, setActiveColor] = React.useState(null); @@ -268,74 +288,91 @@ const BackgroundColorButton = ({ editor }) => { ); }; -const HeadingSelect = ({ editor }) => ( - - - + + - - - {editor.isActive("heading", { level: 1 }) - ? "标题 1" - : editor.isActive("heading", { level: 2 }) - ? "标题 2" - : editor.isActive("heading", { level: 3 }) - ? "标题 3" - : "正文"} - - - - - -
- {[ - { label: "正文", value: "p" }, - { label: "标题 1", value: "1" }, - { label: "标题 2", value: "2" }, - { label: "标题 3", value: "3" } - ].map((item) => ( - - ))} -
-
-
-); + )} + onClick={() => { + if (item.value === "p") { + editor.chain().focus().setParagraph().run(); + } else { + editor + .chain() + .focus() + .toggleHeading({ level: parseInt(item.value) }) + .run(); + } + }} + > + {item.label} + + ))} + + + + ); +}; const RichTextEditor = ({ content, onChange, placeholder }: RichTextEditorProps) => { + const theme = useResumeStore((state) => state.theme); + const editor = useEditor({ extensions: [ StarterKit.configure({ @@ -358,8 +395,21 @@ const RichTextEditor = ({ }, editorProps: { attributes: { - class: - "prose prose-sm sm:prose lg:prose-lg max-w-none focus:outline-none min-h-[150px] px-4 py-3" + class: cn( + "prose prose-sm sm:prose lg:prose-lg max-w-none focus:outline-none min-h-[150px] px-4 py-3", + theme === "dark" && [ + "prose-invert", + "prose-headings:text-neutral-200", + "prose-p:text-neutral-300", + "prose-strong:text-neutral-200", + "prose-em:text-neutral-200", + "prose-blockquote:text-neutral-300", + "prose-blockquote:border-neutral-700", + "prose-ul:text-neutral-300", + "prose-ol:text-neutral-300", + "[&_*::selection]:bg-neutral-700/50" + ] + ) } } }); @@ -369,14 +419,34 @@ const RichTextEditor = ({ } return ( -
+
{/* Toolbar */} -
+
-
+
-
+
-
+
-
+
diff --git a/apps/fronted/src/components/editor/Field.tsx b/apps/fronted/src/components/editor/Field.tsx index ba36050..5093105 100644 --- a/apps/fronted/src/components/editor/Field.tsx +++ b/apps/fronted/src/components/editor/Field.tsx @@ -5,13 +5,14 @@ import { Popover, PopoverContent, PopoverTrigger } from "../ui/popover"; import { Calendar } from "../ui/calendar"; import { CalendarIcon } from "lucide-react"; import { useResumeStore } from "@/store/useResumeStore"; +import RichTextEditor from "@/app/workbench/compoents/Editor/RichText"; // 扩展 FieldProps 类型定义 type FieldProps = { label: string; value: string; onChange: (value: string) => void; - type?: "text" | "textarea" | "date"; + type?: "text" | "textarea" | "date" | "editor"; placeholder?: string; required?: boolean; }; @@ -27,6 +28,18 @@ const Field: React.FC = ({ }) => { const theme = useResumeStore((state) => state.theme); + const renderLabel = () => ( + + {label} + {required && *} + + ); + const inputStyles = cn( "mt-1.5 block w-full transition-all duration-200", "rounded-lg px-4 py-2.5", @@ -144,6 +157,20 @@ const Field: React.FC = ({ ); } + if (type === "editor") { + return ( + + {renderLabel()} +
+ +
+
+ ); + } return (