hololake-system-architecture/product-source/guanghu-knowledge-base/src/components/Editor.tsx

105 lines
2.8 KiB
TypeScript
Raw Normal View History

import { useState, useEffect, useMemo } from 'react';
import { DocContent } from '../api';
import { marked } from 'marked';
interface Props {
doc: DocContent;
onSave: (title: string, body: string) => void;
}
export function Editor({ doc, onSave }: Props) {
const [editing, setEditing] = useState(false);
const [title, setTitle] = useState(doc.meta.title);
const [body, setBody] = useState(doc.body);
// 切换文档时重置
useEffect(() => {
setTitle(doc.meta.title);
setBody(doc.body);
setEditing(false);
}, [doc.meta.id]);
const rendered = useMemo(() => {
try {
return marked(body, { async: false }) as string;
} catch {
return '<p>渲染失败</p>';
}
}, [body]);
const handleSave = () => {
onSave(title, body);
setEditing(false);
};
const handleCancel = () => {
setTitle(doc.meta.title);
setBody(doc.body);
setEditing(false);
};
return (
<div className="kb-editor">
{/* 元信息栏 */}
<div className="kb-editor-meta">
<span className="kb-editor-path">{doc.meta.id}</span>
<span className="kb-editor-date">
{new Date(doc.meta.updatedAt).toLocaleString('zh-CN')}
</span>
<span className="kb-editor-author">by {doc.meta.author}</span>
</div>
{/* 标题 */}
{editing ? (
<input
className="kb-editor-title-input"
value={title}
onChange={e => setTitle(e.target.value)}
placeholder="文档标题"
/>
) : (
<h1 className="kb-editor-title" onClick={() => setEditing(true)}>
{doc.meta.title}
</h1>
)}
{/* 操作栏 */}
<div className="kb-editor-toolbar">
{editing ? (
<>
<button className="kb-btn-primary" onClick={handleSave}></button>
<button className="kb-btn-secondary" onClick={handleCancel}></button>
</>
) : (
<button className="kb-btn-primary" onClick={() => setEditing(true)}></button>
)}
</div>
{/* 内容区 */}
{editing ? (
<div className="kb-editor-edit-pane">
<textarea
className="kb-editor-textarea"
value={body}
onChange={e => setBody(e.target.value)}
placeholder="用 Markdown 写作..."
spellCheck={false}
/>
<div className="kb-editor-preview-pane">
<div
className="kb-markdown-render"
dangerouslySetInnerHTML={{ __html: rendered }}
/>
</div>
</div>
) : (
<div className="kb-editor-read-pane">
<div
className="kb-markdown-render"
dangerouslySetInnerHTML={{ __html: rendered }}
/>
</div>
)}
</div>
);
}