Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
C
center-book
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
图表
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
图像
聊天
创建新问题
作业
提交
问题看板
Open sidebar
EzijingWeb
center-book
Commits
4069d643
提交
4069d643
authored
3月 02, 2026
作者:
王鹏飞
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
feat: 添加侧边栏宽度调整功能
上级
b978b149
隐藏空白字符变更
内嵌
并排
正在显示
2 个修改的文件
包含
109 行增加
和
33 行删除
+109
-33
index.jsx
src/pages/books/section/index.jsx
+72
-33
index.less
src/pages/books/section/index.less
+37
-0
没有找到文件。
src/pages/books/section/index.jsx
浏览文件 @
4069d643
import
{
useState
,
useEffect
,
useRef
}
from
'react'
import
{
useState
,
useEffect
,
useRef
,
useCallback
}
from
'react'
import
{
Button
,
Row
,
Col
,
Descriptions
,
Tree
,
Dropdown
,
Modal
,
Spin
,
App
}
from
'antd'
import
{
EllipsisOutlined
,
DiffOutlined
,
MenuFoldOutlined
,
MenuUnfoldOutlined
}
from
'@ant-design/icons'
import
WangEditorCustomer
from
'@/common/wangeditor-customer'
...
...
@@ -18,7 +18,7 @@ import {
findFirstNotHasChildren
,
findParentLevelOne
,
findTreeToIndex
,
findNodeById
findNodeById
,
}
from
'@/utils/common'
import
{
getAllList
,
getInfoByChapterId
,
sectionEdit
,
chapterDel
,
dragOrder
}
from
'./request'
import
'./index.less'
...
...
@@ -30,7 +30,7 @@ const Examine = () => {
const
id
=
get
(
location
,
'state.id'
,
''
)
const
isAdminOrCreator
=
get
(
location
,
'state.isAdminOrCreator'
,
false
)
const
{
treeChapter
,
userInfo
}
=
useSelector
(
state
=>
state
.
user
)
const
{
treeChapter
,
userInfo
}
=
useSelector
(
(
state
)
=>
state
.
user
)
const
navigate
=
useNavigate
()
const
dispatch
=
useDispatch
()
...
...
@@ -44,6 +44,9 @@ const Examine = () => {
const
[
nowTitle
,
setNowTitle
]
=
useState
(
''
)
// 编辑操作
const
[
isCollapse
,
setisCollapse
]
=
useState
(
false
)
const
[
sidebarWidth
,
setSidebarWidth
]
=
useState
(
280
)
const
isResizing
=
useRef
(
false
)
const
sidebarRef
=
useRef
(
null
)
const
[
editKey
,
setEditKey
]
=
useState
(
null
)
const
[
parentId
,
setParentId
]
=
useState
(
null
)
const
[
editValue
,
setEditValue
]
=
useState
(
''
)
...
...
@@ -60,6 +63,38 @@ const Examine = () => {
// 关联知识图谱
const
[
bindKnowledgeGraphIsOpen
,
setBindKnowledgeGraphIsOpen
]
=
useState
(
false
)
// 拖拽改变侧边栏宽度
const
handleMouseDown
=
useCallback
(
(
e
)
=>
{
e
.
preventDefault
()
isResizing
.
current
=
true
document
.
body
.
style
.
cursor
=
'col-resize'
document
.
body
.
style
.
userSelect
=
'none'
const
startX
=
e
.
clientX
const
startWidth
=
sidebarWidth
const
handleMouseMove
=
(
e
)
=>
{
if
(
!
isResizing
.
current
)
return
const
delta
=
e
.
clientX
-
startX
const
newWidth
=
Math
.
min
(
Math
.
max
(
startWidth
+
delta
,
200
),
600
)
setSidebarWidth
(
newWidth
)
}
const
handleMouseUp
=
()
=>
{
isResizing
.
current
=
false
document
.
body
.
style
.
cursor
=
''
document
.
body
.
style
.
userSelect
=
''
document
.
removeEventListener
(
'mousemove'
,
handleMouseMove
)
document
.
removeEventListener
(
'mouseup'
,
handleMouseUp
)
}
document
.
addEventListener
(
'mousemove'
,
handleMouseMove
)
document
.
addEventListener
(
'mouseup'
,
handleMouseUp
)
},
[
sidebarWidth
],
)
// 编辑器内容
const
editorRef
=
useRef
()
const
saveInterRef
=
useRef
()
...
...
@@ -81,7 +116,7 @@ const Examine = () => {
return
}
const
uniqueBookList
=
[...
new
Set
(
data
.
map
(
item
=>
item
.
book_id
))][
0
]
const
uniqueBookList
=
[...
new
Set
(
data
.
map
(
(
item
)
=>
item
.
book_id
))][
0
]
setBookId
(
uniqueBookList
)
const
arr
=
convertToAntdTreeData
(
data
,
'name'
)
setGData
(
arr
)
...
...
@@ -123,9 +158,9 @@ const Examine = () => {
setNowTitle
(
title
)
}
// 递归函数,获取所有节点的key
const
getAllNodeKeys
=
nodes
=>
{
const
getAllNodeKeys
=
(
nodes
)
=>
{
let
keys
=
[]
nodes
.
forEach
(
node
=>
{
nodes
.
forEach
(
(
node
)
=>
{
keys
.
push
(
node
.
key
)
if
(
node
.
children
&&
node
.
children
.
length
>
0
)
{
keys
=
keys
.
concat
(
getAllNodeKeys
(
node
.
children
))
...
...
@@ -153,7 +188,7 @@ const Examine = () => {
setLoading
(
false
)
}
const
onExpand
=
expandedKeys
=>
{
const
onExpand
=
(
expandedKeys
)
=>
{
setExpandedKeys
(
expandedKeys
)
}
const
handleSelect
=
async
(
selectedKeys
,
info
)
=>
{
...
...
@@ -205,7 +240,7 @@ const Examine = () => {
const
data
=
await
sectionEdit
({
id
:
contentId
,
content
:
contentHtml
,
word_count
word_count
,
})
if
(
data
)
{
if
((
data
.
code
&&
data
.
code
===
3000
)
||
data
.
code
===
'3000'
)
{
...
...
@@ -233,7 +268,7 @@ const Examine = () => {
setParentId
(
-
1
)
}
const
delChapter
=
async
node
=>
{
const
delChapter
=
async
(
node
)
=>
{
const
childInKey
=
findParentLevelOne
(
gData
,
'key'
,
node
.
key
)
let
current
=
null
if
(
childInKey
&&
childInKey
.
children
&&
childInKey
.
children
.
length
>
0
)
{
...
...
@@ -296,11 +331,11 @@ const Examine = () => {
label
:
'一键AI'
,
children
:
[
{
key
:
'61'
,
label
:
'一键AI创作课件'
,
disabled
:
true
},
{
key
:
'62'
,
label
:
'一键AI创作教案'
,
disabled
:
true
}
]
{
key
:
'62'
,
label
:
'一键AI创作教案'
,
disabled
:
true
}
,
]
,
},
{
key
:
'3'
,
label
:
'编辑'
},
{
key
:
'4'
,
label
:
'删除'
}
{
key
:
'4'
,
label
:
'删除'
}
,
]
if
(
!
isAdminOrCreator
)
{
chapterMenuItems
=
[{
key
:
'1'
,
label
:
'展开全部'
}]
...
...
@@ -330,7 +365,7 @@ const Examine = () => {
content
:
`确认删除子节【
${
node
.
title
}
】?`
,
onOk
()
{
delChapter
(
node
)
}
}
,
})
}
else
if
(
e
.
key
==
5
)
{
setEditChapterEditorsIsOpen
(
true
)
...
...
@@ -340,18 +375,18 @@ const Examine = () => {
}
// 章节名称
const
chapterTitleRender
=
node
=>
{
const
chapterTitleRender
=
(
node
)
=>
{
return
(
<
div
className=
"chapter-tree-item"
>
<
p
className=
"title"
>
{
node
.
title
}
</
p
>
<
Dropdown
trigger=
{
[
'click'
]
}
menu=
{
{
items
:
chapterMenuItems
,
onClick
:
e
=>
handleMenuClick
(
e
,
node
)
}
}
>
<
EllipsisOutlined
onClick=
{
e
=>
e
.
stopPropagation
()
}
/>
<
Dropdown
trigger=
{
[
'click'
]
}
menu=
{
{
items
:
chapterMenuItems
,
onClick
:
(
e
)
=>
handleMenuClick
(
e
,
node
)
}
}
>
<
EllipsisOutlined
onClick=
{
(
e
)
=>
e
.
stopPropagation
()
}
/>
</
Dropdown
>
</
div
>
)
}
const
onDrop
=
async
info
=>
{
const
onDrop
=
async
(
info
)
=>
{
const
dropToGap
=
info
.
dropToGap
// true 为同级或最大级 false 为子级
const
nowDropNode
=
info
.
dragNode
.
key
const
sideDropNode
=
info
.
node
.
key
...
...
@@ -369,7 +404,7 @@ const Examine = () => {
book_id
:
id
,
drag_node
:
nowDropNode
,
position_node
:
sideDropNode
,
drop_type
:
'after'
drop_type
:
'after'
,
})
}
else
{
if
(
dragOverGapTop
)
{
...
...
@@ -378,14 +413,14 @@ const Examine = () => {
book_id
:
id
,
drag_node
:
nowDropNode
,
position_node
:
sideDropNode
,
drop_type
:
'before'
drop_type
:
'before'
,
})
}
else
if
(
dragOverGapBottom
)
{
data
=
await
dragOrder
({
book_id
:
id
,
drag_node
:
nowDropNode
,
position_node
:
sideDropNode
,
drop_type
:
'after'
drop_type
:
'after'
,
})
}
}
...
...
@@ -395,7 +430,7 @@ const Examine = () => {
book_id
:
id
,
drag_node
:
nowDropNode
,
position_node
:
sideDropNode
,
drop_type
:
'inner'
drop_type
:
'inner'
,
})
}
if
(
data
)
{
...
...
@@ -406,8 +441,11 @@ const Examine = () => {
return
(
<
div
className=
"examine"
>
<
div
className=
"content-box"
>
<
Row
gutter=
{
10
}
style=
{
{
height
:
'100%'
}
}
className=
"book-content-row"
>
<
Col
span=
{
isCollapse
?
1
:
4
}
className=
"book-content-tree"
>
<
div
className=
"book-content-row"
>
<
div
ref=
{
sidebarRef
}
className=
"book-content-tree"
style=
{
{
width
:
isCollapse
?
50
:
sidebarWidth
,
minWidth
:
isCollapse
?
50
:
200
,
flexShrink
:
0
}
}
>
<
div
className=
"border"
>
{
!
isCollapse
?
(
<>
...
...
@@ -431,8 +469,8 @@ const Examine = () => {
onClick=
{
()
=>
setisCollapse
(
true
)
}
></
Button
>
</
Col
>
</
Row
>
)
}
)
,
}
,
]
}
/>
{
gData
&&
gData
.
length
>
0
&&
(
...
...
@@ -450,7 +488,7 @@ const Examine = () => {
disabled=
{
loading
}
treeData=
{
gData
}
onExpand=
{
onExpand
}
titleRender=
{
nodeData
=>
chapterTitleRender
(
nodeData
)
}
titleRender=
{
(
nodeData
)
=>
chapterTitleRender
(
nodeData
)
}
/>
)
}
</>
...
...
@@ -470,14 +508,15 @@ const Examine = () => {
onClick=
{
()
=>
setisCollapse
(
false
)
}
></
Button
>
</
Col
>
</
Row
>
)
}
)
,
}
,
]
}
/>
)
}
</
div
>
</
Col
>
<
Col
span=
{
isCollapse
?
23
:
20
}
className=
"book-content-tree"
>
</
div
>
{
!
isCollapse
&&
<
div
className=
"resize-handle"
onMouseDown=
{
handleMouseDown
}
/>
}
<
div
className=
"book-content-editor"
style=
{
{
flex
:
1
,
minWidth
:
0
}
}
>
<
div
className=
"editor-right"
>
<
Spin
spinning=
{
loading
}
>
<
WangEditorCustomer
...
...
@@ -494,8 +533,8 @@ const Examine = () => {
/>
</
Spin
>
</
div
>
</
Col
>
</
Row
>
</
div
>
</
div
>
</
div
>
<
Modal
...
...
@@ -509,7 +548,7 @@ const Examine = () => {
closeIcon=
{
false
}
// 添加这一行以隐藏关闭按钮
onCancel=
{
()
=>
setEditKey
(
false
)
}
classNames=
{
{
wrapper
:
'chapter-title-modal'
wrapper
:
'chapter-title-modal'
,
}
}
>
<
EditChapterTitle
setEditKey=
{
setEditKey
}
...
...
src/pages/books/section/index.less
浏览文件 @
4069d643
...
...
@@ -7,9 +7,46 @@
.book-content-row {
height: 100%;
overflow: hidden;
display: flex;
gap: 0;
.book-content-tree {
height: 100%;
overflow: hidden;
transition: width 0s;
}
.book-content-editor {
height: 100%;
overflow: hidden;
}
}
.resize-handle {
width: 6px;
cursor: col-resize;
background: transparent;
position: relative;
flex-shrink: 0;
z-index: 10;
transition: background 0.2s;
&:hover,
&:active {
background: #1890ff;
border-radius: 3px;
}
&::after {
content: '';
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 2px;
height: 30px;
background: #d9d9d9;
border-radius: 1px;
transition: background 0.2s;
}
&:hover::after,
&:active::after {
background: #fff;
}
}
.ant-descriptions-item-label {
...
...
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论