import { useEffect, useRef, useState } from "react"; import { Tooltip } from "antd"; import cls from "classnames"; import styles from "./index.module.scss"; import { useDeepCompareEffect, useHover } from "ahooks"; import IconFont from "@/components/icon-font"; import { downloadFileUseAScript } from "@/utils/download"; import { MD_DRIVE_PDF } from "@/constant/event"; import { useIntl } from "react-intl"; import LazyUrlMarkdown from "../url-markdown"; import exitFullScreenSvg from "@/assets/pdf/exitFullScreen.svg"; import fullScreenSvg from "@/assets/pdf/fullScreen.svg"; import { MD_PREVIEW_TYPE } from "@/types/extract-task-type"; import _ from "lodash"; import { TaskIdResItem } from "@/api/extract"; import useMdStore from "@/store/mdStore"; import CodeMirror from "@/components/code-mirror"; import { useParams } from "react-router-dom"; import SaveStatus, { SaveStatusRef } from "@/components/SaveStatus"; interface IMdViewerProps { md?: string; className?: string; filename?: string; url?: string; taskInfo: TaskIdResItem; curPage: number; fullScreen?: boolean; setFullScreen?: (value?: boolean) => void; } const MdViewer: React.FC = ({ fullScreen, setFullScreen, taskInfo, className = "", curPage, }) => { const mdViewerPef = useRef(null); const url = taskInfo?.fullMdLink || ""; const containerRef = useRef(null); const isHovering = useHover(containerRef); const { formatMessage } = useIntl(); const [displayType, setDisplayType] = useState(MD_PREVIEW_TYPE.preview); const params = useParams(); const { setAllMdContentWithAnchor, allMdContentWithAnchor, setMdUrlArr, mdContents, updateMdContent, } = useMdStore(); const [lineWrap, setLineWrap] = useState(false); const threshold = 562 - 427; const statusRef = useRef(null); const menuList = [ { name: formatMessage({ id: "extractor.markdown.preview" }), code: MD_PREVIEW_TYPE.preview, }, { name: formatMessage({ id: "extractor.markdown.code" }), code: MD_PREVIEW_TYPE.code, }, ]; const getVisibleFromType = (str: string, type: string) => { return str === type ? "relative w-full h-full" : "w-0 h-0 overflow-hidden hidden"; }; const pushMdViewerScroll = (scrollType?: "instant" | "smooth") => { const container = document.getElementById(`md-container`); // md渲染的时候用一个元素包括anchor const element = displayType === MD_PREVIEW_TYPE.preview ? document.getElementById(`md-anchor-${curPage - 1}`)?.parentElement : document.getElementById(`code-${curPage - 1}`); if (element && container) { container.scrollTo({ top: element.offsetTop - 124, behavior: scrollType || "smooth", }); } }; useEffect(() => { if (isHovering) return; pushMdViewerScroll(); }, [curPage, isHovering]); useEffect(() => { pushMdViewerScroll("instant"); }, [displayType]); useEffect(() => { if (!isHovering) return; const handleScroll = () => { if (!containerRef.current) return; taskInfo?.markdownUrl?.forEach((page, index) => { const element = displayType === MD_PREVIEW_TYPE.preview ? document.getElementById(`md-anchor-${index}`)?.parentElement : document.getElementById(`code-${index}`); if (element) { const rect = element.getBoundingClientRect(); if (rect.top <= threshold) { document.dispatchEvent( new CustomEvent(MD_DRIVE_PDF, { detail: index, }) ); } } }); }; const container = containerRef.current; if (container) { container.addEventListener("scroll", handleScroll); } return () => { if (container) { container?.removeEventListener("scroll", handleScroll); } }; }, [taskInfo, isHovering, displayType]); useDeepCompareEffect(() => { if (taskInfo?.markdownUrl) { setMdUrlArr(taskInfo?.markdownUrl); } statusRef?.current?.reset(); }, [taskInfo?.markdownUrl, params?.jobID]); const handleContentChange = (val: string, index: number) => { setAllMdContentWithAnchor(val); statusRef?.current?.triggerSave(); if (taskInfo?.file_key) { updateMdContent(taskInfo.file_key!, index, val); } }; return (
    {menuList.map((item) => (
  • setDisplayType(item.code)} > {item.name}
  • ))}
{displayType === "code" && ( <> setLineWrap?.(!lineWrap)} /> )} setFullScreen?.(!fullScreen)} > {!fullScreen ? ( ) : ( )} downloadFileUseAScript( url, `${_(taskInfo?.fileName).split(".").slice(0, -1).join(".")}.md` ) } />
{taskInfo?.markdownUrl?.map((url: string, index: number) => { const md = mdContents[url]?.content || ""; if (!md) return null; return (
handleContentChange(val, index)} editable className="w-full h-full" />
); })}
); }; export default MdViewer;