editor.tsx 3.2 KB
import React, { useEffect, useRef, useState } from "react";
import { Editor } from "@tinymce/tinymce-react";
import tinymce from "tinymce";
import { message } from "antd";
import { cosUploadImage } from "@/app/utils/tencentCos";
import { Path } from "@/app/constant";

export function EditorComponent(props: {
  htmlCode: string;
  setHtmlCode: React.Dispatch<React.SetStateAction<string>>;
}) {
  const editorRef = useRef<tinymce.Editor | null>(null);
  const [editorValue, setEditorValue] = useState(props.htmlCode);
  useEffect(() => {
    setEditorValue(props.htmlCode);
  }, [props.htmlCode]);
  return (
    <Editor
      apiKey="l4kgoxhh8dtkv4thb22g4wskoq4obivan58l38asxk32an6f"
      onInit={(evt: any, editor: tinymce.Editor) => {
        editorRef.current = editor;
      }}
      initialValue={props.htmlCode}
      init={{
        height: "100%",
        width: "100%",
        menubar: false,
        branding: false,
        plugins: [
          "advlist",
          "autolink",
          "lists",
          "link",
          "image",
          "charmap",
          "preview",
          "anchor",
          "searchreplace",
          "visualblocks",
          "code",
          "fullscreen",
          "insertdatetime",
          "media",
          "table",
        ],
        toolbar:
          "undo redo | blocks fontsize | saveHtml uploadImage table underline " +
          "bold italic forecolor backcolor | alignleft aligncenter " +
          "alignright alignjustify | bullist numlist outdent indent fullscreen preview emoticons copy cut paste",
        toolbar_mode: "wrap",
        content_style:
          "body { font-family:Helvetica,Arial,sans-serif; font-size:14px }",
        setup: (editor: tinymce.Editor) => {
          editor.ui.registry.addButton("saveHtml", {
            text: "保存",
            icon: "save",
            onAction: () => {
              const content = editorRef.current?.getContent();
              if (content && content !== props.htmlCode)
                props.setHtmlCode(content);
            },
          });
          editor.ui.registry.addButton("uploadImage", {
            text: "上传图片",
            icon: "image",
            onAction: () => {
              const input = document.createElement("input");
              input.setAttribute("type", "file");
              input.setAttribute("accept", "image/*");
              input.addEventListener("change", async (e) => {
                const file = (e.target as HTMLInputElement).files?.[0];
                if (!file) return;
                if (!file.type.startsWith("image/")) {
                  message.error("请选择有效的图片文件");
                  return;
                }
                try {
                  const imageUrl = await cosUploadImage(file, Path.Writing);
                  editor.insertContent(
                    `<img src="https://${imageUrl}" alt="上传的图片"/>`,
                  );
                } catch (error) {
                  alert(
                    `图片上传失败: ${
                      error instanceof Error ? error.message : error
                    }`,
                  );
                }
              });
              input.click();
            },
          });
        },
      }}
    />
  );
}