修复bug
parent
b3f5fb00b7
commit
fef17e59e4
|
|
@ -28,6 +28,33 @@
|
|||
height: 100%;
|
||||
}
|
||||
|
||||
/* 侧栏收起时:左侧悬浮展开按钮 */
|
||||
.docs-sider-expand-btn {
|
||||
position: fixed;
|
||||
left: 12px;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
z-index: 30;
|
||||
width: 32px;
|
||||
height: 48px;
|
||||
border-radius: 8px;
|
||||
border: 1px solid var(--border-color);
|
||||
background: var(--header-bg);
|
||||
color: var(--text-color-secondary);
|
||||
font-size: 16px;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.12);
|
||||
transition: color 0.2s ease, border-color 0.2s ease;
|
||||
}
|
||||
|
||||
.docs-sider-expand-btn:hover {
|
||||
color: var(--link-color);
|
||||
border-color: var(--link-color);
|
||||
}
|
||||
|
||||
.docs-sider-header {
|
||||
padding: 12px 10px 12px;
|
||||
border-bottom: 1px solid var(--border-color);
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { useState, useEffect, useRef, useMemo } from 'react'
|
||||
import { useParams, useNavigate, useSearchParams } from 'react-router-dom'
|
||||
import { Layout, Spin, Button, Tooltip, Modal, Input, Space, Dropdown, Empty, Switch, Select, TreeSelect, Radio, Alert } from 'antd'
|
||||
import { ShareAltOutlined, FileTextOutlined, FolderOutlined, FolderOpenOutlined, FilePdfOutlined, CopyOutlined, CloudDownloadOutlined, CloudUploadOutlined, ArrowLeftOutlined, ReloadOutlined, VerticalAlignTopOutlined } from '@ant-design/icons'
|
||||
import { ShareAltOutlined, FileTextOutlined, FolderOutlined, FolderOpenOutlined, FilePdfOutlined, CopyOutlined, CloudDownloadOutlined, CloudUploadOutlined, ArrowLeftOutlined, ReloadOutlined, VerticalAlignTopOutlined, MenuUnfoldOutlined } from '@ant-design/icons'
|
||||
import ReactMarkdown from 'react-markdown'
|
||||
import remarkGfm from 'remark-gfm'
|
||||
import rehypeRaw from 'rehype-raw'
|
||||
|
|
@ -61,6 +61,7 @@ function DocumentPage() {
|
|||
const [pdfUrl, setPdfUrl] = useState('')
|
||||
const [pdfFilename, setPdfFilename] = useState('')
|
||||
const [viewMode, setViewMode] = useState('markdown')
|
||||
const [siderCollapsed, setSiderCollapsed] = useState(false)
|
||||
const [gitRepos, setGitRepos] = useState([])
|
||||
// Git 同步范围弹窗状态
|
||||
const [gitSyncModalVisible, setGitSyncModalVisible] = useState(false)
|
||||
|
|
@ -131,6 +132,7 @@ function DocumentPage() {
|
|||
setMarkdownContent('')
|
||||
setTocItems([])
|
||||
setViewMode('folder')
|
||||
setSiderCollapsed(true)
|
||||
expandParentFolders(`${folderPath}/placeholder`)
|
||||
|
||||
// 从内容区点击进入子文件夹时,同时展开自身,保证与左侧文件树同步
|
||||
|
|
@ -149,6 +151,7 @@ function DocumentPage() {
|
|||
setMarkdownContent('')
|
||||
setTocItems([])
|
||||
setViewMode('folder')
|
||||
setSiderCollapsed(true)
|
||||
setOpenKeys([])
|
||||
|
||||
if (syncUrl) {
|
||||
|
|
@ -1259,7 +1262,7 @@ function DocumentPage() {
|
|||
<div className="project-docs-page">
|
||||
<Layout className="docs-layout">
|
||||
{/* 左侧目录 */}
|
||||
<Sider width={280} className="docs-sider" theme="light">
|
||||
<Sider width={280} className="docs-sider" theme="light" collapsed={siderCollapsed} collapsedWidth={0}>
|
||||
<div className="docs-sider-header">
|
||||
<div className="docs-sider-title-row">
|
||||
<button
|
||||
|
|
@ -1339,6 +1342,19 @@ function DocumentPage() {
|
|||
/>
|
||||
</Sider>
|
||||
|
||||
{/* 侧栏收起时:悬浮展开按钮 */}
|
||||
{siderCollapsed && (
|
||||
<button
|
||||
type="button"
|
||||
className="docs-sider-expand-btn"
|
||||
onClick={() => setSiderCollapsed(false)}
|
||||
aria-label="展开目录"
|
||||
title="展开目录"
|
||||
>
|
||||
<MenuUnfoldOutlined />
|
||||
</button>
|
||||
)}
|
||||
|
||||
{/* 右侧内容区 */}
|
||||
<Layout className="docs-content-layout">
|
||||
<Content className="docs-content" ref={contentRef}>
|
||||
|
|
|
|||
|
|
@ -37,6 +37,32 @@ function FileSharePage() {
|
|||
const contentRef = useRef(null)
|
||||
const largeMarkdownRef = useRef(null)
|
||||
const [headerVisible, setHeaderVisible] = useState(false)
|
||||
const headerHoveringRef = useRef(false)
|
||||
const headerHideTimerRef = useRef(null)
|
||||
const clearHeaderHideTimer = () => {
|
||||
if (headerHideTimerRef.current) {
|
||||
clearTimeout(headerHideTimerRef.current)
|
||||
headerHideTimerRef.current = null
|
||||
}
|
||||
}
|
||||
// 延迟隐藏 Header(鼠标悬停时保持显示)
|
||||
const scheduleHeaderHide = () => {
|
||||
clearHeaderHideTimer()
|
||||
if (headerHoveringRef.current) return
|
||||
headerHideTimerRef.current = setTimeout(() => setHeaderVisible(false), 1200)
|
||||
}
|
||||
// 鼠标进入 Header:取消隐藏计时,保持显示
|
||||
const handleHeaderMouseEnter = () => {
|
||||
headerHoveringRef.current = true
|
||||
clearHeaderHideTimer()
|
||||
}
|
||||
// 鼠标离开 Header:若已滚动则重新计时隐藏
|
||||
const handleHeaderMouseLeave = () => {
|
||||
headerHoveringRef.current = false
|
||||
const root = contentRef.current
|
||||
const target = root ? findScrollableEl(root) : null
|
||||
if (target && target.scrollTop > 8) scheduleHeaderHide()
|
||||
}
|
||||
const [pdfToolbarTarget, setPdfToolbarTarget] = useState(null)
|
||||
const [shareInfo, setShareInfo] = useState(null)
|
||||
const [contentInfo, setContentInfo] = useState(null)
|
||||
|
|
@ -60,30 +86,22 @@ function FileSharePage() {
|
|||
return () => window.removeEventListener('resize', checkMobile)
|
||||
}, [])
|
||||
|
||||
// 内容区 Header:仅在滚动时显示,滚动停止后延迟隐藏(含 PDF/大文档内部滚动)
|
||||
// 内容区 Header:仅在滚动时显示,滚动停止后延迟隐藏;鼠标悬停时保持显示
|
||||
useEffect(() => {
|
||||
const root = contentRef.current
|
||||
if (!root) return
|
||||
const hideTimer = { current: null }
|
||||
const clearHideTimer = () => {
|
||||
if (hideTimer.current) {
|
||||
clearTimeout(hideTimer.current)
|
||||
hideTimer.current = null
|
||||
}
|
||||
}
|
||||
const sync = (scrollEl = null) => {
|
||||
const target = scrollEl || findScrollableEl(root)
|
||||
if (!target) {
|
||||
clearHideTimer()
|
||||
clearHeaderHideTimer()
|
||||
setHeaderVisible(true)
|
||||
return
|
||||
}
|
||||
if (target.scrollTop > 8) {
|
||||
setHeaderVisible(true)
|
||||
clearHideTimer()
|
||||
hideTimer.current = setTimeout(() => setHeaderVisible(false), 1200)
|
||||
scheduleHeaderHide()
|
||||
} else {
|
||||
clearHideTimer()
|
||||
clearHeaderHideTimer()
|
||||
setHeaderVisible(false)
|
||||
}
|
||||
}
|
||||
|
|
@ -92,7 +110,7 @@ function FileSharePage() {
|
|||
sync()
|
||||
return () => {
|
||||
root.removeEventListener('scroll', onScroll, true)
|
||||
clearHideTimer()
|
||||
clearHeaderHideTimer()
|
||||
}
|
||||
}, [contentInfo?.type, isLargeMarkdown, loading])
|
||||
|
||||
|
|
@ -222,7 +240,10 @@ function FileSharePage() {
|
|||
<div className="file-share-shell">
|
||||
<Layout className="file-share-content-layout">
|
||||
<Content className="file-share-content" ref={contentRef}>
|
||||
<div className={`preview-content-header file-share-content-header${headerVisible ? '' : ' preview-header-hidden'}`}>
|
||||
<div
|
||||
onMouseEnter={handleHeaderMouseEnter}
|
||||
onMouseLeave={handleHeaderMouseLeave}
|
||||
className={`preview-content-header file-share-content-header${headerVisible ? '' : ' preview-header-hidden'}`}>
|
||||
<button
|
||||
type="button"
|
||||
className="project-back-button"
|
||||
|
|
|
|||
|
|
@ -77,6 +77,32 @@ function ProjectSharePage() {
|
|||
const contentRef = useRef(null)
|
||||
const viewerRef = useRef(null)
|
||||
const [headerVisible, setHeaderVisible] = useState(false)
|
||||
const headerHoveringRef = useRef(false)
|
||||
const headerHideTimerRef = useRef(null)
|
||||
const clearHeaderHideTimer = () => {
|
||||
if (headerHideTimerRef.current) {
|
||||
clearTimeout(headerHideTimerRef.current)
|
||||
headerHideTimerRef.current = null
|
||||
}
|
||||
}
|
||||
// 延迟隐藏 Header(鼠标悬停时保持显示)
|
||||
const scheduleHeaderHide = () => {
|
||||
clearHeaderHideTimer()
|
||||
if (headerHoveringRef.current) return
|
||||
headerHideTimerRef.current = setTimeout(() => setHeaderVisible(false), 1200)
|
||||
}
|
||||
// 鼠标进入 Header:取消隐藏计时,保持显示
|
||||
const handleHeaderMouseEnter = () => {
|
||||
headerHoveringRef.current = true
|
||||
clearHeaderHideTimer()
|
||||
}
|
||||
// 鼠标离开 Header:若已滚动则重新计时隐藏
|
||||
const handleHeaderMouseLeave = () => {
|
||||
headerHoveringRef.current = false
|
||||
const root = contentRef.current
|
||||
const target = root ? findScrollableEl(root) : null
|
||||
if (target && target.scrollTop > 8) scheduleHeaderHide()
|
||||
}
|
||||
const largeMarkdownRef = useRef(null)
|
||||
const [pdfToolbarTarget, setPdfToolbarTarget] = useState(null)
|
||||
const isLargeMarkdown = isLargeMarkdownContent(markdownContent)
|
||||
|
|
@ -96,30 +122,22 @@ function ProjectSharePage() {
|
|||
return () => window.removeEventListener('resize', checkMobile)
|
||||
}, [])
|
||||
|
||||
// 内容区 Header:仅在滚动时显示,滚动停止后延迟隐藏(含 PDF/大文档内部滚动)
|
||||
// 内容区 Header:仅在滚动时显示,滚动停止后延迟隐藏;鼠标悬停时保持显示
|
||||
useEffect(() => {
|
||||
const root = contentRef.current
|
||||
if (!root) return
|
||||
const hideTimer = { current: null }
|
||||
const clearHideTimer = () => {
|
||||
if (hideTimer.current) {
|
||||
clearTimeout(hideTimer.current)
|
||||
hideTimer.current = null
|
||||
}
|
||||
}
|
||||
const sync = (scrollEl = null) => {
|
||||
const target = scrollEl || findScrollableEl(root)
|
||||
if (!target) {
|
||||
clearHideTimer()
|
||||
clearHeaderHideTimer()
|
||||
setHeaderVisible(true)
|
||||
return
|
||||
}
|
||||
if (target.scrollTop > 8) {
|
||||
setHeaderVisible(true)
|
||||
clearHideTimer()
|
||||
hideTimer.current = setTimeout(() => setHeaderVisible(false), 1200)
|
||||
scheduleHeaderHide()
|
||||
} else {
|
||||
clearHideTimer()
|
||||
clearHeaderHideTimer()
|
||||
setHeaderVisible(false)
|
||||
}
|
||||
}
|
||||
|
|
@ -128,7 +146,7 @@ function ProjectSharePage() {
|
|||
sync()
|
||||
return () => {
|
||||
root.removeEventListener('scroll', onScroll, true)
|
||||
clearHideTimer()
|
||||
clearHeaderHideTimer()
|
||||
}
|
||||
}, [viewMode, isLargeMarkdown, loading])
|
||||
|
||||
|
|
@ -711,7 +729,10 @@ function ProjectSharePage() {
|
|||
|
||||
<Layout className="preview-content-layout">
|
||||
<Content className="preview-content" ref={contentRef}>
|
||||
<div className={`preview-content-header${headerVisible ? '' : ' preview-header-hidden'}`}>
|
||||
<div
|
||||
onMouseEnter={handleHeaderMouseEnter}
|
||||
onMouseLeave={handleHeaderMouseLeave}
|
||||
className={`preview-content-header${headerVisible ? '' : ' preview-header-hidden'}`}>
|
||||
{isMobile && (
|
||||
<div className="preview-header-leading-actions">
|
||||
<Tooltip title="关闭">
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ function ProjectList({ type = 'my' }) {
|
|||
|
||||
// 参与项目角色 -> 显示名称
|
||||
const projectRoleLabel = (role) => {
|
||||
const roleMap = { admin: '管理者', editor: '编辑者', viewer: '查看者' }
|
||||
const roleMap = { admin: '管理员', editor: '编辑者', viewer: '查看者' }
|
||||
return roleMap[role] || role || '查看者'
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue