import React, { useState, useEffect } from "react";
import { Alert, Button, Row, Col, Space, Input, Tooltip, } from "antd";
import "@wangeditor/editor/dist/css/style.css"; // 引入 css
import { Editor, Toolbar } from "@wangeditor/editor-for-react";
import { SlateNode } from "@wangeditor/editor";
import { generateNewId } from "oak-domain/lib/utils/uuid";
import classNames from "classnames";
import Prompt from "../../../components/common/prompt";
import Style from "./web.module.less";
import { CloseOutlined, EyeOutlined, MenuOutlined, CaretDownOutlined } from "@ant-design/icons";
// 工具栏配置
const toolbarConfig = {
excludeKeys: ["fullScreen"],
}; // TS 语法
// 自定义校验图片
function customCheckImageFn(src, alt, url) {
// TS 语法
if (!src) {
return;
}
if (src.indexOf("http") !== 0) {
return "图片网址必须以 http/https 开头";
}
return true;
// 返回值有三种选择:
// 1. 返回 true ,说明检查通过,编辑器将正常插入图片
// 2. 返回一个字符串,说明检查未通过,编辑器会阻止插入。会 alert 出错误信息(即返回的字符串)
// 3. 返回 undefined(即没有任何返回),说明检查未通过,编辑器会阻止插入。但不会提示任何信息
}
function TocView(props) {
const { toc, showToc, tocPosition, setShowToc, highlightBgColor, scrollId } = props;
useEffect(() => {
document.documentElement.style.setProperty('--highlight-bg-color', highlightBgColor);
}, [highlightBgColor]);
const generateTocList = (items, currentLevel = 1, parentId = null) => {
//递归生成嵌套列表
const result = [];
let lastId = parentId;
while (items.length > 0) {
const item = items[0];
//有无子级标题,有则显示展开图标
const hasChildren = items.length > 1 && items[1].level > item.level;
if (item.level > currentLevel) {
// 递归生成子列表
const sublist = generateTocList(items, item.level, item.id);
result.push(
);
}
else if (item.level < currentLevel) {
// 结束当前层级
break;
}
else {
// 添加当前层级的
result.push(
{
const iconElem = document.getElementById(`icon-${item.id}`);
const ulElem = document.getElementById(`ul-${item.id}`);
const isFolded = iconElem?.className.includes('iconFold') || ulElem?.className.includes('fold');
if (isFolded) {
iconElem?.classList.remove(Style.iconFold);
ulElem?.classList.remove(Style.fold);
}
else {
iconElem?.classList.add(Style.iconFold);
ulElem?.classList.add(Style.fold);
}
}}/>
{
// editor.scrollToElem(item.id);
//编辑器滚动到对应元素
const elem = document.getElementById(item.id);
const elemTop = elem?.getBoundingClientRect().top;
const scrollContainer = document.getElementById(scrollId || 'article-upsert-editorContainer');
const containerTop = scrollContainer?.getBoundingClientRect().top;
scrollContainer?.scrollBy({
top: elemTop - containerTop,
behavior: 'smooth',
});
//添加背景色
elem?.classList.add(Style.highlight);
//移除背景色类名
setTimeout(function () {
elem?.classList.remove(Style.highlight);
}, 1000);
event.preventDefault();
event.stopPropagation();
}}>
{item.text}
);
items.shift(); // 移除已处理的项
lastId = item.id;
}
}
return result;
};
return (
{showToc ? (<>
{(toc && toc.length > 0) ? (
{generateTocList([...toc])}
) : (
)}
>) : (
} onClick={() => setShowToc(true)}/>
)}
);
}
export default function Render(props) {
const { methods, data } = props;
const { t, setEditor, check, uploadFile, update, setHtml, gotoPreview, clearContentTip, } = methods;
const { id, content, editor, origin = 'qiniu', oakFullpath, html, tocPosition = 'none', highlightBgColor = 'none', scrollId } = data;
const [articleId, setArticleId] = useState('');
const [toc, setToc] = useState([]);
const [showToc, setShowToc] = useState(false);
useEffect(() => {
if (id) {
setArticleId(id);
}
}, [id]);
useEffect(() => {
if (tocPosition !== 'none') {
setShowToc(true);
}
}, [tocPosition]);
return (
{tocPosition === 'left' ? (
) : null}
{data.contentTip && (
clearContentTip()}/>)}
update({ name: e.target.value })} value={data.name} placeholder={'请输入文章标题'} size="large" maxLength={32} suffix={`${[...(data.name || '')].length}/32`} className={Style.titleInput}/>
{
setHtml(editor.getHtml());
const headers = editor.getElemsByTypePrefix('header');
const tocItems = headers.map((header) => {
const text = SlateNode.string(header);
const { id, type } = header;
return {
text,
level: parseInt(type.substring(6)),
id,
};
});
setToc([...tocItems]);
}} style={{
minHeight: 440,
}} mode="default"/>
{tocPosition === 'right' ? (
) : null}
);
}