|
|
@@ -51,38 +51,49 @@ const SliceDetail: React.FC = () => {
|
|
|
const [listLoading, setListLoading] = React.useState(false);
|
|
|
|
|
|
const [editorHtml, setEditorHtml] = useState<string>(``);
|
|
|
+ // RichTextImageRight
|
|
|
const RichTextImageRight = () => {
|
|
|
const [plainText, setPlainText] = useState<string>(extractPlainText(editorHtml));
|
|
|
const [linkDataList, setLinkDataList] = useState<LinkData[]>([]);
|
|
|
const [activeImageUrl, setActiveImageUrl] = useState<string | null>(null);
|
|
|
- const editorContainerRef = useRef<HTMLDivElement>(null);
|
|
|
+
|
|
|
// 跟踪鼠标是否在链接或预览区上
|
|
|
const [isHoveringLink, setIsHoveringLink] = useState(false);
|
|
|
const [isHoveringPreview, setIsHoveringPreview] = useState(false);
|
|
|
+
|
|
|
+ const editorContainerRef = useRef<HTMLDivElement>(null);
|
|
|
+ const previewRef = useRef<HTMLDivElement>(null);
|
|
|
+
|
|
|
// 初始化链接数据
|
|
|
useEffect(() => {
|
|
|
- const parser = new DOMParser();
|
|
|
- const doc = parser.parseFromString(editorHtml, 'text/html');
|
|
|
- const links = doc.getElementsByTagName('a');
|
|
|
- const linksData: LinkData[] = [];
|
|
|
-
|
|
|
- Array.from(links).forEach((link, index) => {
|
|
|
- linksData.push({
|
|
|
- id: `link-${index}-${Date.now()}`,
|
|
|
- originalText: link.textContent || '',
|
|
|
- url: link.href,
|
|
|
- isDeleted: false
|
|
|
+ const start = async () => {
|
|
|
+ if (!params.sliceId || !params.knowledgeId) {
|
|
|
+ throw new Error('参数错误');
|
|
|
+ }
|
|
|
+ const res = await apis.fetchTakaiSliceDetail(params.sliceId, params.knowledgeId);
|
|
|
+ const info = res.data.data;
|
|
|
+ const parser = new DOMParser();
|
|
|
+ const doc = parser.parseFromString(info.slice_text, 'text/html');
|
|
|
+ const links = doc.getElementsByTagName('a');
|
|
|
+ const linksData: LinkData[] = [];
|
|
|
+ Array.from(links).forEach((link, index) => {
|
|
|
+ linksData.push({
|
|
|
+ id: `link-${index}-${Date.now()}`,
|
|
|
+ originalText: link.textContent || '',
|
|
|
+ url: link.href,
|
|
|
+ isDeleted: false
|
|
|
+ });
|
|
|
});
|
|
|
- });
|
|
|
|
|
|
- setLinkDataList(linksData);
|
|
|
+ setLinkDataList(linksData);
|
|
|
+ }
|
|
|
+ start()
|
|
|
}, []);
|
|
|
|
|
|
// 处理内容变化
|
|
|
const handleEditorChange = (html: string) => {
|
|
|
setEditorHtml(html);
|
|
|
const text = extractPlainText(html);
|
|
|
- // console.log('text---', text);
|
|
|
setPlainText(text);
|
|
|
form.setFieldsValue({ slice_text: text });
|
|
|
|
|
|
@@ -100,7 +111,7 @@ const SliceDetail: React.FC = () => {
|
|
|
useEffect(() => {
|
|
|
if (!editorContainerRef.current) return;
|
|
|
|
|
|
- const handleMouseOver = (e: MouseEvent) => {
|
|
|
+ const handleMouseOverLink = (e: MouseEvent) => {
|
|
|
const target = e.target as HTMLAnchorElement;
|
|
|
if (target.tagName === 'A') {
|
|
|
const url = target.href;
|
|
|
@@ -110,33 +121,26 @@ const SliceDetail: React.FC = () => {
|
|
|
|
|
|
if (isKnownLink) {
|
|
|
console.log('图片地址:', url);
|
|
|
- setActiveImageUrl(url); // 只设置图片地址,不计算位置
|
|
|
+ setActiveImageUrl(url);
|
|
|
setIsHoveringLink(true);
|
|
|
}
|
|
|
}
|
|
|
};
|
|
|
|
|
|
- const handleMouseOut = (e: MouseEvent) => {
|
|
|
- if ((e.target as HTMLAnchorElement).tagName === 'A') {
|
|
|
- // 延迟关闭,避免快速移动鼠标时的闪烁
|
|
|
- setTimeout(() => {
|
|
|
- const activeElement = document.activeElement as HTMLElement;
|
|
|
- if (!activeElement || activeElement.tagName !== 'A') {
|
|
|
- setActiveImageUrl(null);
|
|
|
- }
|
|
|
- }, 300);
|
|
|
- }
|
|
|
+ const handleMouseOutLink = () => {
|
|
|
+ setIsHoveringLink(false);
|
|
|
};
|
|
|
|
|
|
const container = editorContainerRef.current;
|
|
|
- container.addEventListener('mouseover', handleMouseOver);
|
|
|
- container.addEventListener('mouseout', handleMouseOut);
|
|
|
+ container.addEventListener('mouseover', handleMouseOverLink);
|
|
|
+ container.addEventListener('mouseout', handleMouseOutLink);
|
|
|
|
|
|
return () => {
|
|
|
- container.removeEventListener('mouseover', handleMouseOver);
|
|
|
- container.removeEventListener('mouseout', handleMouseOut);
|
|
|
+ container.removeEventListener('mouseover', handleMouseOverLink);
|
|
|
+ container.removeEventListener('mouseout', handleMouseOutLink);
|
|
|
};
|
|
|
}, [linkDataList]);
|
|
|
+
|
|
|
// 控制预览区显示/隐藏的核心逻辑
|
|
|
useEffect(() => {
|
|
|
// 当鼠标既不在链接上也不在预览区上时,才隐藏预览
|
|
|
@@ -144,6 +148,7 @@ const SliceDetail: React.FC = () => {
|
|
|
setActiveImageUrl(null);
|
|
|
}
|
|
|
}, [isHoveringLink, isHoveringPreview]);
|
|
|
+
|
|
|
// 配置编辑器(无工具栏)
|
|
|
const modules = {
|
|
|
toolbar: false
|
|
|
@@ -155,16 +160,15 @@ const SliceDetail: React.FC = () => {
|
|
|
<div style={{
|
|
|
display: 'flex',
|
|
|
gap: '16px',
|
|
|
- alignItems: 'flex-start',
|
|
|
+ alignItems: 'flex-start'
|
|
|
}}>
|
|
|
{/* 500x500的编辑器 */}
|
|
|
<div
|
|
|
ref={editorContainerRef}
|
|
|
style={{
|
|
|
- width: '300px',
|
|
|
- height: '400px',
|
|
|
- marginTop: '20px',
|
|
|
- marginBottom: '0px',
|
|
|
+ width: '500px',
|
|
|
+ height: '500px',
|
|
|
+ border: '1px solid #d9d9d9',
|
|
|
borderRadius: '4px',
|
|
|
overflow: 'hidden'
|
|
|
}}
|
|
|
@@ -181,6 +185,7 @@ const SliceDetail: React.FC = () => {
|
|
|
{/* 右侧图片预览区(固定位置) */}
|
|
|
{activeImageUrl && (
|
|
|
<div
|
|
|
+ ref={previewRef}
|
|
|
style={{
|
|
|
width: '300px',
|
|
|
height: '500px',
|
|
|
@@ -192,6 +197,8 @@ const SliceDetail: React.FC = () => {
|
|
|
display: 'flex',
|
|
|
flexDirection: 'column'
|
|
|
}}
|
|
|
+ onMouseOver={() => setIsHoveringPreview(true)}
|
|
|
+ onMouseOut={() => setIsHoveringPreview(false)}
|
|
|
>
|
|
|
<div style={{
|
|
|
display: 'flex',
|
|
|
@@ -205,10 +212,10 @@ const SliceDetail: React.FC = () => {
|
|
|
<EyeOutlined style={{ color: '#1890ff', marginRight: '8px' }} />
|
|
|
<span style={{ fontSize: '14px', color: '#333' }}>图片预览</span>
|
|
|
</div>
|
|
|
- {/* <CloseOutlined
|
|
|
- style={{ color: '#999', cursor: 'pointer', fontSize: '16px' }}
|
|
|
- onClick={() => setActiveImageUrl(null)}
|
|
|
- /> */}
|
|
|
+ <CloseOutlined
|
|
|
+ style={{ color: '#999', cursor: 'pointer', fontSize: '16px' }}
|
|
|
+ onClick={() => setActiveImageUrl(null)}
|
|
|
+ />
|
|
|
</div>
|
|
|
|
|
|
<div style={{
|
|
|
@@ -287,7 +294,7 @@ const SliceDetail: React.FC = () => {
|
|
|
|
|
|
return (
|
|
|
<div>
|
|
|
- {/* <ImgPre></ImgPre> */}
|
|
|
+ <ImgPre></ImgPre>
|
|
|
<div className='questionAnswerList'>
|
|
|
<div style={{ height: '100%', marginLeft: '10px' }}>
|
|
|
<Form
|