parent
faf4222020
commit
b98abe886f
@ -1,109 +0,0 @@
|
|||||||
import React, { useState, useEffect } from 'react';
|
|
||||||
import styles from './styles.module.css';
|
|
||||||
|
|
||||||
const Comments = () => {
|
|
||||||
const [comments, setComments] = useState([]);
|
|
||||||
const [newComment, setNewComment] = useState('');
|
|
||||||
const [name, setName] = useState('');
|
|
||||||
const [mounted, setMounted] = useState(false);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
setMounted(true);
|
|
||||||
const savedComments = localStorage.getItem('docComments');
|
|
||||||
if (savedComments) {
|
|
||||||
try {
|
|
||||||
setComments(JSON.parse(savedComments));
|
|
||||||
} catch (e) {
|
|
||||||
console.error('Failed to parse comments:', e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
const saveComments = (newComments) => {
|
|
||||||
try {
|
|
||||||
localStorage.setItem('docComments', JSON.stringify(newComments));
|
|
||||||
} catch (e) {
|
|
||||||
console.error('Failed to save comments:', e);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleSubmit = (e) => {
|
|
||||||
e.preventDefault();
|
|
||||||
if (!newComment.trim() || !name.trim()) return;
|
|
||||||
|
|
||||||
const comment = {
|
|
||||||
id: Date.now(),
|
|
||||||
name,
|
|
||||||
content: newComment,
|
|
||||||
date: new Date().toLocaleString(),
|
|
||||||
};
|
|
||||||
|
|
||||||
const updatedComments = [...comments, comment];
|
|
||||||
setComments(updatedComments);
|
|
||||||
saveComments(updatedComments);
|
|
||||||
setNewComment('');
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleDelete = (commentId) => {
|
|
||||||
const updatedComments = comments.filter(comment => comment.id !== commentId);
|
|
||||||
setComments(updatedComments);
|
|
||||||
saveComments(updatedComments);
|
|
||||||
};
|
|
||||||
|
|
||||||
if (!mounted) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className={styles.commentsContainer}>
|
|
||||||
<h2 className={styles.title}>评论</h2>
|
|
||||||
|
|
||||||
<form onSubmit={handleSubmit} className={styles.form}>
|
|
||||||
<div className={styles.inputGroup}>
|
|
||||||
<input
|
|
||||||
type="text"
|
|
||||||
value={name}
|
|
||||||
onChange={(e) => setName(e.target.value)}
|
|
||||||
placeholder="您的名字"
|
|
||||||
className={styles.input}
|
|
||||||
required
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div className={styles.inputGroup}>
|
|
||||||
<textarea
|
|
||||||
value={newComment}
|
|
||||||
onChange={(e) => setNewComment(e.target.value)}
|
|
||||||
placeholder="写下您的评论..."
|
|
||||||
className={styles.textarea}
|
|
||||||
required
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<button type="submit" className={styles.submitButton}>
|
|
||||||
发表评论
|
|
||||||
</button>
|
|
||||||
</form>
|
|
||||||
|
|
||||||
<div className={styles.commentsList}>
|
|
||||||
{comments.map((comment) => (
|
|
||||||
<div key={comment.id} className={styles.comment}>
|
|
||||||
<div className={styles.commentHeader}>
|
|
||||||
<span className={styles.commentName}>{comment.name}</span>
|
|
||||||
<div className={styles.commentActions}>
|
|
||||||
<span className={styles.commentDate}>{comment.date}</span>
|
|
||||||
<button
|
|
||||||
onClick={() => handleDelete(comment.id)}
|
|
||||||
className={styles.deleteButton}
|
|
||||||
>
|
|
||||||
删除
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<p className={styles.commentContent}>{comment.content}</p>
|
|
||||||
</div>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default Comments;
|
|
@ -1,114 +0,0 @@
|
|||||||
.commentsContainer {
|
|
||||||
margin: 2rem 0;
|
|
||||||
padding: 1rem;
|
|
||||||
border-radius: 8px;
|
|
||||||
background-color: var(--ifm-background-color);
|
|
||||||
}
|
|
||||||
|
|
||||||
.title {
|
|
||||||
font-size: 1.5rem;
|
|
||||||
margin-bottom: 1.5rem;
|
|
||||||
color: var(--ifm-color-primary);
|
|
||||||
}
|
|
||||||
|
|
||||||
.form {
|
|
||||||
margin-bottom: 2rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.inputGroup {
|
|
||||||
margin-bottom: 1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.input,
|
|
||||||
.textarea {
|
|
||||||
width: 100%;
|
|
||||||
padding: 0.75rem;
|
|
||||||
border: 1px solid var(--ifm-color-emphasis-300);
|
|
||||||
border-radius: 4px;
|
|
||||||
background-color: var(--ifm-background-color);
|
|
||||||
color: var(--ifm-color-emphasis-900);
|
|
||||||
font-size: 1rem;
|
|
||||||
transition: border-color 0.2s ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
.input:focus,
|
|
||||||
.textarea:focus {
|
|
||||||
outline: none;
|
|
||||||
border-color: var(--ifm-color-primary);
|
|
||||||
}
|
|
||||||
|
|
||||||
.textarea {
|
|
||||||
min-height: 100px;
|
|
||||||
resize: vertical;
|
|
||||||
}
|
|
||||||
|
|
||||||
.submitButton {
|
|
||||||
padding: 0.75rem 1.5rem;
|
|
||||||
background-color: var(--ifm-color-primary);
|
|
||||||
color: white;
|
|
||||||
border: none;
|
|
||||||
border-radius: 4px;
|
|
||||||
font-size: 1rem;
|
|
||||||
cursor: pointer;
|
|
||||||
transition: background-color 0.2s ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
.submitButton:hover {
|
|
||||||
background-color: var(--ifm-color-primary-darker);
|
|
||||||
}
|
|
||||||
|
|
||||||
.commentsList {
|
|
||||||
margin-top: 2rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.comment {
|
|
||||||
padding: 1rem;
|
|
||||||
margin-bottom: 1rem;
|
|
||||||
border: 1px solid var(--ifm-color-emphasis-300);
|
|
||||||
border-radius: 4px;
|
|
||||||
background-color: var(--ifm-background-color);
|
|
||||||
}
|
|
||||||
|
|
||||||
.commentHeader {
|
|
||||||
display: flex;
|
|
||||||
justify-content: space-between;
|
|
||||||
align-items: center;
|
|
||||||
margin-bottom: 0.5rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.commentName {
|
|
||||||
font-weight: bold;
|
|
||||||
color: var(--ifm-color-primary);
|
|
||||||
}
|
|
||||||
|
|
||||||
.commentActions {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: 1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.commentDate {
|
|
||||||
font-size: 0.875rem;
|
|
||||||
color: var(--ifm-color-emphasis-600);
|
|
||||||
}
|
|
||||||
|
|
||||||
.deleteButton {
|
|
||||||
padding: 0.25rem 0.5rem;
|
|
||||||
background-color: var(--ifm-color-danger);
|
|
||||||
color: white;
|
|
||||||
border: none;
|
|
||||||
border-radius: 4px;
|
|
||||||
font-size: 0.875rem;
|
|
||||||
cursor: pointer;
|
|
||||||
transition: background-color 0.2s ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
.deleteButton:hover {
|
|
||||||
background-color: var(--ifm-color-danger-darker);
|
|
||||||
}
|
|
||||||
|
|
||||||
.commentContent {
|
|
||||||
margin: 0;
|
|
||||||
line-height: 1.5;
|
|
||||||
color: var(--ifm-color-emphasis-900);
|
|
||||||
}
|
|
@ -1,55 +0,0 @@
|
|||||||
import React from 'react';
|
|
||||||
import clsx from 'clsx';
|
|
||||||
import {useDoc} from '@docusaurus/theme-common/internal';
|
|
||||||
import DocItemContent from '@theme-original/DocItem/Content';
|
|
||||||
import DocItemFooter from '@theme-original/DocItem/Footer';
|
|
||||||
import DocItemPaginator from '@theme-original/DocItem/Paginator';
|
|
||||||
import DocItemTOCMobile from '@theme-original/DocItem/TOC/Mobile';
|
|
||||||
import DocItemTOCDesktop from '@theme-original/DocItem/TOC/Desktop';
|
|
||||||
import DocVersionBadge from '@theme-original/DocVersionBadge';
|
|
||||||
import DocVersionBanner from '@theme-original/DocVersionBanner';
|
|
||||||
import DocBreadcrumbs from '@theme-original/DocBreadcrumbs';
|
|
||||||
import styles from './styles.module.css';
|
|
||||||
import Comments from '@site/src/components/Comments';
|
|
||||||
|
|
||||||
export default function DocItem(props) {
|
|
||||||
const {metadata, frontMatter, assets} = useDoc();
|
|
||||||
const {
|
|
||||||
hide_table_of_contents: hideTableOfContents,
|
|
||||||
toc_min_heading_level: tocMinHeadingLevel,
|
|
||||||
toc_max_heading_level: tocMaxHeadingLevel,
|
|
||||||
} = frontMatter;
|
|
||||||
const {hide_comment_section: hideCommentSection} = frontMatter;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className={clsx(styles.docItemContainer, 'container')}>
|
|
||||||
<div className={styles.docItemCol}>
|
|
||||||
<DocVersionBanner />
|
|
||||||
<div className={styles.docItemMain}>
|
|
||||||
<DocBreadcrumbs />
|
|
||||||
<DocVersionBadge />
|
|
||||||
<DocItemContent>
|
|
||||||
<DocItemTOCMobile
|
|
||||||
toc={props.toc}
|
|
||||||
minHeadingLevel={tocMinHeadingLevel}
|
|
||||||
maxHeadingLevel={tocMaxHeadingLevel}
|
|
||||||
/>
|
|
||||||
<DocItemContent {...props} />
|
|
||||||
{!hideCommentSection && <Comments />}
|
|
||||||
</DocItemContent>
|
|
||||||
<DocItemFooter {...props} />
|
|
||||||
</div>
|
|
||||||
<DocItemPaginator />
|
|
||||||
</div>
|
|
||||||
{!hideTableOfContents && props.toc && (
|
|
||||||
<div className="col col--3">
|
|
||||||
<DocItemTOCDesktop
|
|
||||||
toc={props.toc}
|
|
||||||
minHeadingLevel={tocMinHeadingLevel}
|
|
||||||
maxHeadingLevel={tocMaxHeadingLevel}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
@ -1,19 +0,0 @@
|
|||||||
.docItemContainer {
|
|
||||||
margin: 0 auto;
|
|
||||||
padding: 0 1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.docItemCol {
|
|
||||||
flex: 1 0 75%;
|
|
||||||
max-width: 75%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.docItemMain {
|
|
||||||
flex: 1 0 auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (max-width: 996px) {
|
|
||||||
.docItemCol {
|
|
||||||
max-width: 100%;
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in new issue