Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
C
center-book
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
图表
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
图像
聊天
创建新问题
作业
提交
问题看板
Open sidebar
EzijingWeb
center-book
Commits
97f423c0
提交
97f423c0
authored
10月 31, 2024
作者:
王鹏飞
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
chore: update
上级
a1f837ea
隐藏空白字符变更
内嵌
并排
正在显示
5 个修改的文件
包含
239 行增加
和
197 行删除
+239
-197
index.jsx
src/common/wangeditor-customer/index.jsx
+21
-2
AIModal.jsx
src/common/wangeditor-customer/menu/common/AIModal.jsx
+47
-6
chapterItem.js
src/common/wangeditor-customer/node/chapterItem.js
+84
-96
chapterTitle.js
src/common/wangeditor-customer/node/chapterTitle.js
+86
-92
useBaiduAI.js
src/hooks/useBaiduAI.js
+1
-1
没有找到文件。
src/common/wangeditor-customer/index.jsx
浏览文件 @
97f423c0
...
@@ -12,7 +12,7 @@ import { Boot } from '@wangeditor/editor'
...
@@ -12,7 +12,7 @@ import { Boot } from '@wangeditor/editor'
import
{
SlateEditor
,
DomEditor
,
SlateElement
,
SlateTransforms
}
from
'@wangeditor/editor'
import
{
SlateEditor
,
DomEditor
,
SlateElement
,
SlateTransforms
}
from
'@wangeditor/editor'
import
{
Editor
,
Toolbar
}
from
'@wangeditor/editor-for-react'
import
{
Editor
,
Toolbar
}
from
'@wangeditor/editor-for-react'
import
{
fontFamilyList
,
fontSizeList
,
lineHeightList
}
from
'./utils/setting'
import
{
fontFamilyList
,
lineHeightList
}
from
'./utils/setting'
import
'@wangeditor/editor/dist/css/style.css'
// 引入 css
import
'@wangeditor/editor/dist/css/style.css'
// 引入 css
import
timesave
from
'@/assets/images/timesave.png'
import
timesave
from
'@/assets/images/timesave.png'
...
@@ -415,7 +415,26 @@ const WangEditorCustomer = (props, ref) => {
...
@@ -415,7 +415,26 @@ const WangEditorCustomer = (props, ref) => {
}
}
},
},
MENU_CONF
:
{
MENU_CONF
:
{
fontSize
:
{
fontSizeList
},
fontSize
:
{
fontSizeList
:
[
{
name
:
'初号'
,
value
:
'56px'
},
{
name
:
'小初'
,
value
:
'48px'
},
{
name
:
'一号'
,
value
:
'34px'
},
{
name
:
'小一'
,
value
:
'32px'
},
{
name
:
'二号'
,
value
:
'29px'
},
{
name
:
'小二'
,
value
:
'24px'
},
{
name
:
'三号'
,
value
:
'21px'
},
{
name
:
'小三'
,
value
:
'20px'
},
{
name
:
'四号'
,
value
:
'18px'
},
{
name
:
'小四'
,
value
:
'16px'
},
{
name
:
'五号'
,
value
:
'14px'
},
{
name
:
'小五'
,
value
:
'12px'
},
{
name
:
'六号'
,
value
:
'10px'
},
{
name
:
'小六'
,
value
:
'8px'
},
{
name
:
'七号'
,
value
:
'7px'
},
{
name
:
'八号'
,
value
:
'6px'
}
]
},
fontFamily
:
{
fontFamilyList
},
fontFamily
:
{
fontFamilyList
},
lineHeight
:
{
lineHeightList
}
lineHeight
:
{
lineHeightList
}
}
}
...
...
src/common/wangeditor-customer/menu/common/AIModal.jsx
浏览文件 @
97f423c0
import
{
useEffect
,
useState
}
from
'react'
import
{
useEffect
,
useState
}
from
'react'
import
{
Modal
,
Input
,
Button
,
Flex
,
Spin
}
from
'antd'
import
{
Modal
,
Input
,
Button
,
Flex
,
Spin
}
from
'antd'
import
{
useAIEdit
}
from
'@/hooks/useBaiduAI'
import
{
useAIEdit
}
from
'@/hooks/useBaiduAI'
import
{
SlateTransforms
}
from
'@wangeditor/editor'
const
{
TextArea
}
=
Input
const
{
TextArea
}
=
Input
import
{
SlateEditor
,
SlateElement
,
SlateTransforms
}
from
'@wangeditor/editor'
const
actionMap
=
{
const
actionMap
=
{
rewrite
:
{
name
:
'改写'
,
prompt
:
'帮我改写以下文字内容:'
},
rewrite
:
{
name
:
'改写'
,
prompt
:
'帮我改写以下文字内容:'
},
expand
:
{
name
:
'扩写'
,
prompt
:
'帮我在以下文字内容基础上进行扩写:'
},
expand
:
{
name
:
'扩写'
,
prompt
:
'帮我在以下文字内容基础上进行扩写:'
},
abbreviate
:
{
name
:
'润色'
,
prompt
:
'帮我润色以下文字内容:'
},
abbreviate
:
{
name
:
'润色'
,
prompt
:
'帮我润色以下文字内容:'
},
summary
:
{
name
:
'总结'
,
prompt
:
'帮我总结以下文字内容:'
},
summary
:
{
name
:
'总结'
,
prompt
:
'帮我总结以下文字内容:'
},
punctuation
:
{
name
:
'标点校对'
,
prompt
:
'帮我校对以下文字内容中的标点符号'
},
punctuation
:
{
contentInspect
:
{
name
:
'内容检查'
,
prompt
:
'帮我检查以下文字内容中的敏感词和错别字'
}
name
:
'标点校对'
,
prompt
:
`帮我校对标点符号,要求如下:
1、如果标点符号没有问题,则告诉我“该内容标点符号正常”。
2、如果标点符号存在问题,则按照如下规则进行返回:
(1)带有错误标点符号的句子:
(2)纠正标点符号之后正确的句子:
(3)更新符号之后的完整内容:
具体要校对的内容如下:`
},
contentInspect
:
{
name
:
'内容检查'
,
prompt
:
`帮我检查敏感词和错别字,要求如下:
1、如果没有敏感词或者错别字,则告诉我“该内容正常,无敏感词和错别字”。
2、如果存在敏感词或错别字问题,则按照如下规则进行返回:
(1)带有敏感词或错别字的句子:
(2)纠正敏感词或错别字之后正确的句子:
(3)更新之后的完整内容:
具体要校对的内容如下:`
}
}
}
export
default
function
AIModal
({
editor
,
docAction
})
{
export
default
function
AIModal
({
editor
,
docAction
})
{
...
@@ -38,14 +56,37 @@ export default function AIModal({ editor, docAction }) {
...
@@ -38,14 +56,37 @@ export default function AIModal({ editor, docAction }) {
}
}
const
handlePrimary
=
()
=>
{
const
handlePrimary
=
()
=>
{
let
result
=
content
.
trim
()
// 标点校对结果判断
if
(
docAction
===
'punctuation'
)
{
if
(
result
.
includes
(
'该内容标点符号正常'
))
{
setIsModalOpen
(
false
)
return
}
const
match
=
result
.
match
(
/更新符号之后的完整内容
[
::
]?\s?([\s\S]
*
)
/
)
if
(
match
)
{
result
=
match
[
1
].
trim
()
}
}
// 内容检查结果判断
if
(
docAction
===
'contentInspect'
)
{
if
(
result
.
includes
(
'该内容正常,无敏感词和错别字'
))
{
setIsModalOpen
(
false
)
return
}
const
match
=
result
.
match
(
/更新之后的完整内容
[
::
]?\s?([\s\S]
*
)
/
)
if
(
match
)
{
result
=
match
[
1
].
trim
()
}
}
console
.
log
(
result
)
editor
.
restoreSelection
()
editor
.
restoreSelection
()
// 删除当前选中的节点
// 删除当前选中的节点
SlateTransforms
.
removeNodes
(
editor
)
SlateTransforms
.
removeNodes
(
editor
)
const
contentArr
=
conten
t
.
split
(
'
\
n'
).
filter
(
item
=>
item
)
const
resultArr
=
resul
t
.
split
(
'
\
n'
).
filter
(
item
=>
item
)
const
nodeList
=
conten
tArr
.
map
(
item
=>
{
const
nodeList
=
resul
tArr
.
map
(
item
=>
{
return
{
type
:
'paragraph'
,
indent
:
'2em'
,
children
:
[{
text
:
item
}]
}
return
{
type
:
'paragraph'
,
indent
:
'2em'
,
children
:
[{
text
:
item
}]
}
})
})
console
.
log
(
nodeList
,
editor
.
children
)
// 插入节点
// 插入节点
SlateTransforms
.
insertNodes
(
editor
,
nodeList
)
SlateTransforms
.
insertNodes
(
editor
,
nodeList
)
setIsModalOpen
(
false
)
setIsModalOpen
(
false
)
...
...
src/common/wangeditor-customer/node/chapterItem.js
浏览文件 @
97f423c0
import
{
DomEditor
,
SlateTransforms
}
from
'@wangeditor/editor'
;
import
{
DomEditor
,
SlateTransforms
}
from
'@wangeditor/editor'
import
iconClose
from
'@/assets/images/icon_chapter_close.png'
;
import
iconClose
from
'@/assets/images/icon_chapter_close.png'
import
{
h
}
from
'snabbdom'
;
import
{
h
}
from
'snabbdom'
import
{
findNodeWithParent
}
from
'../utils/setting'
;
import
{
findNodeWithParent
}
from
'../utils/setting'
import
$
from
'jquery'
;
const
withChapterSectionNode
=
(
editor
)
=>
{
const
withChapterSectionNode
=
editor
=>
{
const
{
isInline
,
isVoid
,
normalizeNode
}
=
editor
;
const
{
isInline
,
isVoid
,
normalizeNode
}
=
editor
const
newEditor
=
editor
;
const
newEditor
=
editor
// newEditor.isInline = (elem) => {
// newEditor.isInline = (elem) => {
// const type = DomEditor.getNodeType(elem);
// const type = DomEditor.getNodeType(elem);
...
@@ -14,26 +13,26 @@ const withChapterSectionNode = (editor) => {
...
@@ -14,26 +13,26 @@ const withChapterSectionNode = (editor) => {
// return isInline(elem);
// return isInline(elem);
// };
// };
newEditor
.
isVoid
=
(
elem
)
=>
{
newEditor
.
isVoid
=
elem
=>
{
const
type
=
DomEditor
.
getNodeType
(
elem
)
;
const
type
=
DomEditor
.
getNodeType
(
elem
)
if
(
type
===
'chapterSection'
)
return
true
;
// 设置为 void
if
(
type
===
'chapterSection'
)
return
true
// 设置为 void
return
isVoid
(
elem
)
;
return
isVoid
(
elem
)
}
;
}
// 重新 normalize
// 重新 normalize
newEditor
.
normalizeNode
=
([
node
,
path
])
=>
{
newEditor
.
normalizeNode
=
([
node
,
path
])
=>
{
const
type
=
DomEditor
.
getNodeType
(
node
)
;
const
type
=
DomEditor
.
getNodeType
(
node
)
if
(
type
!==
'chapterSection'
)
{
if
(
type
!==
'chapterSection'
)
{
// 未命中 chapterSection ,执行默认的 normalizeNode
// 未命中 chapterSection ,执行默认的 normalizeNode
return
normalizeNode
([
node
,
path
])
;
return
normalizeNode
([
node
,
path
])
}
}
// editor 顶级 node
// editor 顶级 node
const
topLevelNodes
=
newEditor
.
children
||
[]
;
const
topLevelNodes
=
newEditor
.
children
||
[]
// 后面必须跟一个 p header blockquote(否则后面无法继续输入文字)
// 后面必须跟一个 p header blockquote(否则后面无法继续输入文字)
const
nextNode
=
topLevelNodes
[
path
[
0
]
+
1
]
||
{}
;
const
nextNode
=
topLevelNodes
[
path
[
0
]
+
1
]
||
{}
const
nextNodeType
=
DomEditor
.
getNodeType
(
nextNode
)
;
const
nextNodeType
=
DomEditor
.
getNodeType
(
nextNode
)
if
(
if
(
nextNodeType
!==
'paragraph'
&&
nextNodeType
!==
'paragraph'
&&
nextNodeType
!==
'blockquote'
&&
nextNodeType
!==
'blockquote'
&&
...
@@ -46,16 +45,16 @@ const withChapterSectionNode = (editor) => {
...
@@ -46,16 +45,16 @@ const withChapterSectionNode = (editor) => {
!
nextNodeType
.
startsWith
(
'header'
)
!
nextNodeType
.
startsWith
(
'header'
)
)
{
)
{
// 后面不是 p 或 header ,则插入一个空 p
// 后面不是 p 或 header ,则插入一个空 p
const
p
=
{
type
:
'paragraph'
,
children
:
[{
text
:
''
}]
}
;
const
p
=
{
type
:
'paragraph'
,
children
:
[{
text
:
''
}]
}
const
insertPath
=
[
path
[
0
]
+
1
]
;
const
insertPath
=
[
path
[
0
]
+
1
]
SlateTransforms
.
insertNodes
(
newEditor
,
p
,
{
SlateTransforms
.
insertNodes
(
newEditor
,
p
,
{
at
:
insertPath
,
// 在 link-card 后面插入
at
:
insertPath
// 在 link-card 后面插入
})
;
})
}
}
}
;
}
return
newEditor
;
// 返回 newEditor ,重要!!!
return
newEditor
// 返回 newEditor ,重要!!!
}
;
}
// 在编辑器中渲染新元素
// 在编辑器中渲染新元素
// 定义 renderElem 函数
// 定义 renderElem 函数
...
@@ -70,8 +69,8 @@ const renderChapterSection = (elem, children, editor) => {
...
@@ -70,8 +69,8 @@ const renderChapterSection = (elem, children, editor) => {
height
=
100
,
height
=
100
,
size
=
20
,
size
=
20
,
family
=
'黑体'
,
family
=
'黑体'
,
callback
,
callback
}
=
elem
;
}
=
elem
// 附件元素 vnode
// 附件元素 vnode
const
attachVnode
=
h
(
const
attachVnode
=
h
(
...
@@ -83,7 +82,7 @@ const renderChapterSection = (elem, children, editor) => {
...
@@ -83,7 +82,7 @@ const renderChapterSection = (elem, children, editor) => {
// HTML 属性,驼峰式写法
// HTML 属性,驼峰式写法
contentEditable
:
false
,
contentEditable
:
false
,
className
:
'chapter-item-section'
,
className
:
'chapter-item-section'
,
id
:
'chapter-item-section'
,
id
:
'chapter-item-section'
},
},
dataset
:
{
dataset
:
{
title
,
title
,
...
@@ -91,7 +90,7 @@ const renderChapterSection = (elem, children, editor) => {
...
@@ -91,7 +90,7 @@ const renderChapterSection = (elem, children, editor) => {
bgColor
,
bgColor
,
textColor
,
textColor
,
align
,
align
,
family
,
family
},
},
style
:
{
style
:
{
backgroundColor
:
bgColor
,
backgroundColor
:
bgColor
,
...
@@ -100,15 +99,14 @@ const renderChapterSection = (elem, children, editor) => {
...
@@ -100,15 +99,14 @@ const renderChapterSection = (elem, children, editor) => {
display
:
'flex'
,
display
:
'flex'
,
alignItems
:
'center'
,
alignItems
:
'center'
,
padding
:
'0 20px'
,
padding
:
'0 20px'
,
fontFamily
:
family
,
fontFamily
:
family
},
// style ,驼峰式写法
},
// style ,驼峰式写法
on
:
{
on
:
{
click
(
ev
)
{
click
(
ev
)
{
ev
.
stopPropagation
()
;
ev
.
stopPropagation
()
ev
.
preventDefault
()
;
ev
.
preventDefault
()
const
data
=
{
const
data
=
{
title
,
title
,
title
,
random
:
random
,
random
:
random
,
i
:
Math
.
random
(),
i
:
Math
.
random
(),
...
@@ -117,12 +115,12 @@ const renderChapterSection = (elem, children, editor) => {
...
@@ -117,12 +115,12 @@ const renderChapterSection = (elem, children, editor) => {
align
:
align
,
align
:
align
,
height
:
height
,
height
:
height
,
size
:
size
,
size
:
size
,
family
:
family
,
family
:
family
}
;
}
localStorage
.
setItem
(
'chapterItemNum'
,
JSON
.
stringify
(
data
))
;
localStorage
.
setItem
(
'chapterItemNum'
,
JSON
.
stringify
(
data
))
callback
&&
callback
(
data
)
;
callback
&&
callback
(
data
)
}
/* 其他... */
,
}
/* 其他... */
}
,
}
},
},
// 子节点
// 子节点
[
[
...
@@ -134,17 +132,17 @@ const renderChapterSection = (elem, children, editor) => {
...
@@ -134,17 +132,17 @@ const renderChapterSection = (elem, children, editor) => {
textAlign
:
align
,
textAlign
:
align
,
flex
:
1
,
flex
:
1
,
color
:
textColor
,
color
:
textColor
,
fontFamily
:
family
,
fontFamily
:
family
}
,
}
},
},
[
title
]
,
[
title
]
),
),
h
(
h
(
'span'
,
'span'
,
{
{
props
:
{
props
:
{
contentEditable
:
false
,
contentEditable
:
false
,
className
:
`chapter-close`
,
className
:
`chapter-close`
},
},
style
:
{
style
:
{
position
:
'absolute'
,
position
:
'absolute'
,
...
@@ -152,43 +150,38 @@ const renderChapterSection = (elem, children, editor) => {
...
@@ -152,43 +150,38 @@ const renderChapterSection = (elem, children, editor) => {
right
:
'15px'
,
right
:
'15px'
,
display
:
'inline'
,
display
:
'inline'
,
width
:
'18px'
,
width
:
'18px'
,
height
:
'18px'
,
height
:
'18px'
},
},
on
:
{
on
:
{
async
click
(
ev
)
{
async
click
(
ev
)
{
ev
.
stopPropagation
()
;
ev
.
stopPropagation
()
ev
.
preventDefault
()
;
ev
.
preventDefault
()
try
{
try
{
const
path
=
findNodeWithParent
(
const
path
=
findNodeWithParent
(
editor
.
children
,
'chapterSection'
,
'random'
,
random
)
editor
.
children
,
SlateTransforms
.
removeNodes
(
editor
,
{
at
:
path
.
reverse
()
})
'chapterSection'
,
'random'
,
random
,
);
SlateTransforms
.
removeNodes
(
editor
,
{
at
:
path
.
reverse
()
});
}
catch
(
e
)
{
}
catch
(
e
)
{
console
.
log
(
e
)
;
console
.
log
(
e
)
}
}
}
,
}
}
,
}
},
},
[
[
h
(
'img'
,
{
h
(
'img'
,
{
props
:
{
src
:
iconClose
,
width
:
18
,
height
:
18
},
props
:
{
src
:
iconClose
,
width
:
18
,
height
:
18
},
style
:
{
cursor
:
'pointer'
}
,
style
:
{
cursor
:
'pointer'
}
})
,
})
]
,
]
)
,
)
]
,
]
)
;
)
return
attachVnode
;
return
attachVnode
}
;
}
const
renderElemConf
=
{
const
renderElemConf
=
{
type
:
'chapterSection'
,
type
:
'chapterSection'
,
renderElem
:
renderChapterSection
,
renderElem
:
renderChapterSection
}
;
}
// 把新元素转换为 HTML
// 把新元素转换为 HTML
const
chapterSectionToHtml
=
(
elem
,
childrenHtml
)
=>
{
const
chapterSectionToHtml
=
(
elem
,
childrenHtml
)
=>
{
...
@@ -201,8 +194,8 @@ const chapterSectionToHtml = (elem, childrenHtml) => {
...
@@ -201,8 +194,8 @@ const chapterSectionToHtml = (elem, childrenHtml) => {
align
=
'center'
,
align
=
'center'
,
height
=
100
,
height
=
100
,
size
=
20
,
size
=
20
,
family
=
'黑体'
,
family
=
'黑体'
}
=
elem
;
}
=
elem
// 生成 HTML 代码
// 生成 HTML 代码
const
html
=
`<h2
const
html
=
`<h2
...
@@ -218,26 +211,26 @@ const chapterSectionToHtml = (elem, childrenHtml) => {
...
@@ -218,26 +211,26 @@ const chapterSectionToHtml = (elem, childrenHtml) => {
data-size="
${
size
}
"
data-size="
${
size
}
"
data-family="
${
family
}
"
data-family="
${
family
}
"
style="background-color:
${
bgColor
}
; height:
${
height
}
px; box-sizing: border-box; padding: 0 20px; display: flex; align-items: center; font-family: '
${
family
}
'; "
style="background-color:
${
bgColor
}
; height:
${
height
}
px; box-sizing: border-box; padding: 0 20px; display: flex; align-items: center; font-family: '
${
family
}
'; "
><p style="flex: 1; color:
${
textColor
}
; font-family: '
${
family
}
'; text-align:
${
align
}
; font-size:
${
size
}
px;">
${
title
}
</p></h2>`
;
><p style="flex: 1; color:
${
textColor
}
; font-family: '
${
family
}
'; text-align:
${
align
}
; font-size:
${
size
}
px;">
${
title
}
</p></h2>`
return
html
;
return
html
}
;
}
const
chapterSectionElemToHtmlConf
=
{
const
chapterSectionElemToHtmlConf
=
{
type
:
'chapterSection'
,
// 新元素的 type ,重要!!!
type
:
'chapterSection'
,
// 新元素的 type ,重要!!!
elemToHtml
:
chapterSectionToHtml
,
elemToHtml
:
chapterSectionToHtml
}
;
}
// 解析新元素 HTML 到编辑器
// 解析新元素 HTML 到编辑器
const
parseChapterSectionHtml
=
(
domElem
,
children
,
editor
)
=>
{
const
parseChapterSectionHtml
=
(
domElem
,
children
,
editor
)
=>
{
// 从 DOM element 中获取“附件”的信息
// 从 DOM element 中获取“附件”的信息
const
bgColor
=
domElem
.
getAttribute
(
'data-bgColor'
)
||
''
;
const
bgColor
=
domElem
.
getAttribute
(
'data-bgColor'
)
||
''
const
textColor
=
domElem
.
getAttribute
(
'data-textColor'
)
||
'#333333'
;
const
textColor
=
domElem
.
getAttribute
(
'data-textColor'
)
||
'#333333'
const
title
=
domElem
.
getAttribute
(
'data-title'
)
||
''
;
const
title
=
domElem
.
getAttribute
(
'data-title'
)
||
''
const
random
=
domElem
.
getAttribute
(
'data-random'
)
||
''
;
const
random
=
domElem
.
getAttribute
(
'data-random'
)
||
''
const
align
=
domElem
.
getAttribute
(
'data-align'
)
||
'center'
;
const
align
=
domElem
.
getAttribute
(
'data-align'
)
||
'center'
const
height
=
domElem
.
getAttribute
(
'data-height'
)
||
100
;
const
height
=
domElem
.
getAttribute
(
'data-height'
)
||
100
const
size
=
domElem
.
getAttribute
(
'data-size'
)
||
20
;
const
size
=
domElem
.
getAttribute
(
'data-size'
)
||
20
const
family
=
domElem
.
getAttribute
(
'data-family'
)
||
'黑体'
;
const
family
=
domElem
.
getAttribute
(
'data-family'
)
||
'黑体'
// 生成“附件”元素(按照此前约定的数据结构)
// 生成“附件”元素(按照此前约定的数据结构)
const
myResume
=
{
const
myResume
=
{
...
@@ -250,27 +243,22 @@ const parseChapterSectionHtml = (domElem, children, editor) => {
...
@@ -250,27 +243,22 @@ const parseChapterSectionHtml = (domElem, children, editor) => {
height
,
height
,
size
,
size
,
family
,
family
,
children
:
[{
text
:
''
}]
,
// void node 必须有 children ,其中有一个空字符串,重要!!!
children
:
[{
text
:
''
}]
// void node 必须有 children ,其中有一个空字符串,重要!!!
}
;
}
return
myResume
;
return
myResume
}
;
}
const
parseChapterSectionConf
=
{
const
parseChapterSectionConf
=
{
selector
:
'h2[data-w-e-type="chapterSection"]'
,
// CSS 选择器,匹配特定的 HTML 标签
selector
:
'h2[data-w-e-type="chapterSection"]'
,
// CSS 选择器,匹配特定的 HTML 标签
parseElemHtml
:
parseChapterSectionHtml
,
parseElemHtml
:
parseChapterSectionHtml
}
;
}
const
chapterSectionModule
=
{
const
chapterSectionModule
=
{
editorPlugin
:
withChapterSectionNode
,
editorPlugin
:
withChapterSectionNode
,
renderElems
:
[
renderElemConf
],
renderElems
:
[
renderElemConf
],
elemsToHtml
:
[
chapterSectionElemToHtmlConf
],
elemsToHtml
:
[
chapterSectionElemToHtmlConf
],
parseElemsHtml
:
[
parseChapterSectionConf
]
,
parseElemsHtml
:
[
parseChapterSectionConf
]
}
;
}
export
default
chapterSectionModule
;
export
default
chapterSectionModule
export
{
export
{
withChapterSectionNode
,
renderElemConf
,
chapterSectionElemToHtmlConf
,
parseChapterSectionConf
}
withChapterSectionNode
,
renderElemConf
,
chapterSectionElemToHtmlConf
,
parseChapterSectionConf
,
};
src/common/wangeditor-customer/node/chapterTitle.js
浏览文件 @
97f423c0
import
{
DomEditor
,
SlateTransforms
}
from
'@wangeditor/editor'
;
import
{
DomEditor
,
SlateTransforms
}
from
'@wangeditor/editor'
import
iconClose
from
'@/assets/images/icon_chapter_close.png'
;
import
iconClose
from
'@/assets/images/icon_chapter_close.png'
import
{
h
}
from
'snabbdom'
;
import
{
h
}
from
'snabbdom'
import
{
findNodeWithParent
}
from
'../utils/setting'
;
import
{
findNodeWithParent
}
from
'../utils/setting'
import
$
from
'jquery'
;
const
withChapterHeaderNode
=
(
editor
)
=>
{
const
withChapterHeaderNode
=
editor
=>
{
const
{
isInline
,
isVoid
,
normalizeNode
}
=
editor
;
const
{
isInline
,
isVoid
,
normalizeNode
}
=
editor
const
newEditor
=
editor
;
const
newEditor
=
editor
// newEditor.isInline = (elem) => {
// newEditor.isInline = (elem) => {
// const type = DomEditor.getNodeType(elem);
// const type = DomEditor.getNodeType(elem);
...
@@ -14,25 +13,25 @@ const withChapterHeaderNode = (editor) => {
...
@@ -14,25 +13,25 @@ const withChapterHeaderNode = (editor) => {
// return isInline(elem);
// return isInline(elem);
// };
// };
newEditor
.
isVoid
=
(
elem
)
=>
{
newEditor
.
isVoid
=
elem
=>
{
const
type
=
DomEditor
.
getNodeType
(
elem
)
;
const
type
=
DomEditor
.
getNodeType
(
elem
)
if
(
type
===
'chapterHeader'
)
return
true
;
// 设置为 void
if
(
type
===
'chapterHeader'
)
return
true
// 设置为 void
return
isVoid
(
elem
)
;
return
isVoid
(
elem
)
}
;
}
// 重新 normalize
// 重新 normalize
newEditor
.
normalizeNode
=
([
node
,
path
])
=>
{
newEditor
.
normalizeNode
=
([
node
,
path
])
=>
{
const
type
=
DomEditor
.
getNodeType
(
node
)
;
const
type
=
DomEditor
.
getNodeType
(
node
)
if
(
type
!==
'chapterHeader'
)
{
if
(
type
!==
'chapterHeader'
)
{
// 未命中 chapterHeader ,执行默认的 normalizeNode
// 未命中 chapterHeader ,执行默认的 normalizeNode
return
normalizeNode
([
node
,
path
])
;
return
normalizeNode
([
node
,
path
])
}
}
// editor 顶级 node
// editor 顶级 node
const
topLevelNodes
=
newEditor
.
children
||
[]
;
const
topLevelNodes
=
newEditor
.
children
||
[]
// 后面必须跟一个 p header blockquote (否则后面无法继续输入文字)
// 后面必须跟一个 p header blockquote (否则后面无法继续输入文字)
const
nextNode
=
topLevelNodes
[
path
[
0
]
+
1
]
||
{}
;
const
nextNode
=
topLevelNodes
[
path
[
0
]
+
1
]
||
{}
const
nextNodeType
=
DomEditor
.
getNodeType
(
nextNode
)
;
const
nextNodeType
=
DomEditor
.
getNodeType
(
nextNode
)
if
(
if
(
nextNodeType
!==
'paragraph'
&&
nextNodeType
!==
'paragraph'
&&
nextNodeType
!==
'blockquote'
&&
nextNodeType
!==
'blockquote'
&&
...
@@ -45,16 +44,16 @@ const withChapterHeaderNode = (editor) => {
...
@@ -45,16 +44,16 @@ const withChapterHeaderNode = (editor) => {
!
nextNodeType
.
startsWith
(
'header'
)
!
nextNodeType
.
startsWith
(
'header'
)
)
{
)
{
// 后面不是 p 或 header ,则插入一个空 p
// 后面不是 p 或 header ,则插入一个空 p
const
p
=
{
type
:
'paragraph'
,
children
:
[{
text
:
''
}]
}
;
const
p
=
{
type
:
'paragraph'
,
children
:
[{
text
:
''
}]
}
const
insertPath
=
[
path
[
0
]
+
1
]
;
const
insertPath
=
[
path
[
0
]
+
1
]
SlateTransforms
.
insertNodes
(
newEditor
,
p
,
{
SlateTransforms
.
insertNodes
(
newEditor
,
p
,
{
at
:
insertPath
,
// 在 link-card 后面插入
at
:
insertPath
// 在 link-card 后面插入
})
;
})
}
}
}
;
}
return
newEditor
;
// 返回 newEditor ,重要!!!
return
newEditor
// 返回 newEditor ,重要!!!
}
;
}
// 在编辑器中渲染新元素
// 在编辑器中渲染新元素
// 定义 renderElem 函数
// 定义 renderElem 函数
...
@@ -69,8 +68,8 @@ const renderChapterHeader = (elem, children, editor) => {
...
@@ -69,8 +68,8 @@ const renderChapterHeader = (elem, children, editor) => {
height
=
200
,
height
=
200
,
size
=
200
,
size
=
200
,
family
=
'黑体'
,
family
=
'黑体'
,
callback
,
callback
}
=
elem
;
}
=
elem
// 附件元素 vnode
// 附件元素 vnode
const
attachVnode
=
h
(
const
attachVnode
=
h
(
...
@@ -82,7 +81,7 @@ const renderChapterHeader = (elem, children, editor) => {
...
@@ -82,7 +81,7 @@ const renderChapterHeader = (elem, children, editor) => {
// HTML 属性,驼峰式写法
// HTML 属性,驼峰式写法
contentEditable
:
false
,
contentEditable
:
false
,
className
:
'chapter-item-header'
,
className
:
'chapter-item-header'
,
id
:
'chapter-item-header'
,
id
:
'chapter-item-header'
},
},
dataset
:
{
dataset
:
{
title
,
title
,
...
@@ -92,7 +91,7 @@ const renderChapterHeader = (elem, children, editor) => {
...
@@ -92,7 +91,7 @@ const renderChapterHeader = (elem, children, editor) => {
align
,
align
,
bgColor
,
bgColor
,
size
,
size
,
family
,
family
},
},
style
:
{
style
:
{
backgroundImage
:
`url(
${
bgImgUrl
}
)`
,
backgroundImage
:
`url(
${
bgImgUrl
}
)`
,
...
@@ -105,12 +104,12 @@ const renderChapterHeader = (elem, children, editor) => {
...
@@ -105,12 +104,12 @@ const renderChapterHeader = (elem, children, editor) => {
display
:
'flex'
,
display
:
'flex'
,
alignItems
:
'center'
,
alignItems
:
'center'
,
padding
:
'0 20px'
,
padding
:
'0 20px'
,
fontFamily
:
family
,
fontFamily
:
family
},
// style ,驼峰式写法
},
// style ,驼峰式写法
on
:
{
on
:
{
click
(
ev
)
{
click
(
ev
)
{
ev
.
stopPropagation
()
;
ev
.
stopPropagation
()
ev
.
preventDefault
()
;
ev
.
preventDefault
()
const
data
=
{
const
data
=
{
title
,
title
,
...
@@ -122,12 +121,12 @@ const renderChapterHeader = (elem, children, editor) => {
...
@@ -122,12 +121,12 @@ const renderChapterHeader = (elem, children, editor) => {
align
:
align
,
align
:
align
,
height
:
height
,
height
:
height
,
size
:
size
,
size
:
size
,
family
:
family
,
family
:
family
}
;
}
localStorage
.
setItem
(
'chapterTitleNum'
,
JSON
.
stringify
(
data
))
;
localStorage
.
setItem
(
'chapterTitleNum'
,
JSON
.
stringify
(
data
))
callback
&&
callback
(
data
)
;
callback
&&
callback
(
data
)
}
/* 其他... */
,
}
/* 其他... */
}
,
}
},
},
// 子节点
// 子节点
[
[
...
@@ -139,17 +138,17 @@ const renderChapterHeader = (elem, children, editor) => {
...
@@ -139,17 +138,17 @@ const renderChapterHeader = (elem, children, editor) => {
flex
:
1
,
flex
:
1
,
color
:
textColor
?
textColor
:
'#000'
,
color
:
textColor
?
textColor
:
'#000'
,
textAlign
:
align
,
textAlign
:
align
,
fontFamily
:
family
,
fontFamily
:
family
}
,
}
},
},
[
title
]
,
[
title
]
),
),
h
(
h
(
'span'
,
'span'
,
{
{
props
:
{
props
:
{
contentEditable
:
false
,
contentEditable
:
false
,
className
:
`chapter-close`
,
className
:
`chapter-close`
},
},
style
:
{
style
:
{
position
:
'absolute'
,
position
:
'absolute'
,
...
@@ -157,39 +156,39 @@ const renderChapterHeader = (elem, children, editor) => {
...
@@ -157,39 +156,39 @@ const renderChapterHeader = (elem, children, editor) => {
right
:
'15px'
,
right
:
'15px'
,
display
:
'inline'
,
display
:
'inline'
,
width
:
'18px'
,
width
:
'18px'
,
height
:
'18px'
,
height
:
'18px'
},
},
on
:
{
on
:
{
async
click
(
ev
)
{
async
click
(
ev
)
{
ev
.
stopPropagation
()
;
ev
.
stopPropagation
()
ev
.
preventDefault
()
;
ev
.
preventDefault
()
try
{
try
{
const
path
=
findNodeWithParent
(
editor
.
children
,
'chapterHeader'
,
'random'
,
random
)
;
const
path
=
findNodeWithParent
(
editor
.
children
,
'chapterHeader'
,
'random'
,
random
)
SlateTransforms
.
removeNodes
(
editor
,
{
at
:
path
.
reverse
()
})
;
SlateTransforms
.
removeNodes
(
editor
,
{
at
:
path
.
reverse
()
})
}
catch
(
e
)
{
}
catch
(
e
)
{
console
.
log
(
e
)
;
console
.
log
(
e
)
}
}
}
,
}
}
,
}
},
},
[
[
h
(
'img'
,
{
h
(
'img'
,
{
props
:
{
src
:
iconClose
,
width
:
18
,
height
:
18
},
props
:
{
src
:
iconClose
,
width
:
18
,
height
:
18
},
style
:
{
cursor
:
'pointer'
}
,
style
:
{
cursor
:
'pointer'
}
})
,
})
]
,
]
)
,
)
]
,
]
)
;
)
return
attachVnode
;
return
attachVnode
}
;
}
const
renderElemConf
=
{
const
renderElemConf
=
{
type
:
'chapterHeader'
,
type
:
'chapterHeader'
,
renderElem
:
renderChapterHeader
,
renderElem
:
renderChapterHeader
}
;
}
// 把新元素转换为 HTML
// 把新元素转换为 HTML
const
chapterHeaderToHtml
=
(
elem
,
childrenHtml
)
=>
{
const
chapterHeaderToHtml
=
(
elem
,
childrenHtml
)
=>
{
...
@@ -203,12 +202,12 @@ const chapterHeaderToHtml = (elem, childrenHtml) => {
...
@@ -203,12 +202,12 @@ const chapterHeaderToHtml = (elem, childrenHtml) => {
bgColor
=
''
,
bgColor
=
''
,
height
=
200
,
height
=
200
,
size
=
26
,
size
=
26
,
family
=
'黑体'
,
family
=
'黑体'
}
=
elem
;
}
=
elem
let
background
=
`background-image:url(
${
bgImgUrl
}
); background-repeat: no-repeat; background-position: center center; background-size: cover;`
;
let
background
=
`background-image:url(
${
bgImgUrl
}
); background-repeat: no-repeat; background-position: center center; background-size: cover;`
if
(
bgColor
)
{
if
(
bgColor
)
{
background
+=
` background-color:
${
bgColor
}
;`
;
background
+=
` background-color:
${
bgColor
}
;`
}
}
// 生成 HTML 代码
// 生成 HTML 代码
...
@@ -226,26 +225,26 @@ const chapterHeaderToHtml = (elem, childrenHtml) => {
...
@@ -226,26 +225,26 @@ const chapterHeaderToHtml = (elem, childrenHtml) => {
data-size="
${
size
}
"
data-size="
${
size
}
"
data-family="
${
family
}
"
data-family="
${
family
}
"
style="
${
background
}
height:
${
height
}
px; display: flex; align-items: center; padding: 0 20px; box-sizing: border-box; font-family: '
${
family
}
'; "
style="
${
background
}
height:
${
height
}
px; display: flex; align-items: center; padding: 0 20px; box-sizing: border-box; font-family: '
${
family
}
'; "
><p style="flex: 1; font-family: '
${
family
}
'; font-size:
${
size
}
px; color:
${
textColor
}
; text-align:
${
align
}
;">
${
title
}
</p></h1>`
;
><p style="flex: 1; font-family: '
${
family
}
'; font-size:
${
size
}
px; color:
${
textColor
}
; text-align:
${
align
}
;">
${
title
}
</p></h1>`
return
html
;
return
html
}
;
}
const
chapterHeaderElemToHtmlConf
=
{
const
chapterHeaderElemToHtmlConf
=
{
type
:
'chapterHeader'
,
// 新元素的 type ,重要!!!
type
:
'chapterHeader'
,
// 新元素的 type ,重要!!!
elemToHtml
:
chapterHeaderToHtml
,
elemToHtml
:
chapterHeaderToHtml
}
;
}
// 解析新元素 HTML 到编辑器
// 解析新元素 HTML 到编辑器
const
parseChapterHeaderHtml
=
(
domElem
,
children
,
editor
)
=>
{
const
parseChapterHeaderHtml
=
(
domElem
,
children
,
editor
)
=>
{
// 从 DOM element 中获取“附件”的信息
// 从 DOM element 中获取“附件”的信息
const
bgImgUrl
=
domElem
.
getAttribute
(
'data-bgImgUrl'
)
||
''
;
const
bgImgUrl
=
domElem
.
getAttribute
(
'data-bgImgUrl'
)
||
''
const
textColor
=
domElem
.
getAttribute
(
'data-textColor'
)
||
'#000000'
;
const
textColor
=
domElem
.
getAttribute
(
'data-textColor'
)
||
'#000000'
const
title
=
domElem
.
getAttribute
(
'data-title'
)
||
''
;
const
title
=
domElem
.
getAttribute
(
'data-title'
)
||
''
const
random
=
domElem
.
getAttribute
(
'data-random'
)
||
''
;
const
random
=
domElem
.
getAttribute
(
'data-random'
)
||
''
const
align
=
domElem
.
getAttribute
(
'data-align'
)
||
'left'
;
const
align
=
domElem
.
getAttribute
(
'data-align'
)
||
'left'
const
bgColor
=
domElem
.
getAttribute
(
'data-bgColor'
)
||
''
;
const
bgColor
=
domElem
.
getAttribute
(
'data-bgColor'
)
||
''
const
size
=
domElem
.
getAttribute
(
'data-size'
)
||
26
;
const
size
=
domElem
.
getAttribute
(
'data-size'
)
||
26
const
family
=
domElem
.
getAttribute
(
'data-family'
)
||
'黑体'
;
const
family
=
domElem
.
getAttribute
(
'data-family'
)
||
'黑体'
// 生成“附件”元素(按照此前约定的数据结构)
// 生成“附件”元素(按照此前约定的数据结构)
const
myResume
=
{
const
myResume
=
{
...
@@ -258,27 +257,22 @@ const parseChapterHeaderHtml = (domElem, children, editor) => {
...
@@ -258,27 +257,22 @@ const parseChapterHeaderHtml = (domElem, children, editor) => {
bgColor
,
bgColor
,
size
,
size
,
family
,
family
,
children
:
[{
text
:
''
}]
,
// void node 必须有 children ,其中有一个空字符串,重要!!!
children
:
[{
text
:
''
}]
// void node 必须有 children ,其中有一个空字符串,重要!!!
}
;
}
return
myResume
;
return
myResume
}
;
}
const
parseChapterHeaderConf
=
{
const
parseChapterHeaderConf
=
{
selector
:
'h1[data-w-e-type="chapterHeader"]'
,
// CSS 选择器,匹配特定的 HTML 标签
selector
:
'h1[data-w-e-type="chapterHeader"]'
,
// CSS 选择器,匹配特定的 HTML 标签
parseElemHtml
:
parseChapterHeaderHtml
,
parseElemHtml
:
parseChapterHeaderHtml
}
;
}
const
chapterHeaderModule
=
{
const
chapterHeaderModule
=
{
editorPlugin
:
withChapterHeaderNode
,
editorPlugin
:
withChapterHeaderNode
,
renderElems
:
[
renderElemConf
],
renderElems
:
[
renderElemConf
],
elemsToHtml
:
[
chapterHeaderElemToHtmlConf
],
elemsToHtml
:
[
chapterHeaderElemToHtmlConf
],
parseElemsHtml
:
[
parseChapterHeaderConf
]
,
parseElemsHtml
:
[
parseChapterHeaderConf
]
}
;
}
export
default
chapterHeaderModule
;
export
default
chapterHeaderModule
export
{
export
{
withChapterHeaderNode
,
renderElemConf
,
chapterHeaderElemToHtmlConf
,
parseChapterHeaderConf
}
withChapterHeaderNode
,
renderElemConf
,
chapterHeaderElemToHtmlConf
,
parseChapterHeaderConf
,
};
src/hooks/useBaiduAI.js
浏览文件 @
97f423c0
...
@@ -10,7 +10,7 @@ export function useAIEdit() {
...
@@ -10,7 +10,7 @@ export function useAIEdit() {
const
fetch
=
useCallback
(
async
params
=>
{
const
fetch
=
useCallback
(
async
params
=>
{
setIsLoading
(
true
)
setIsLoading
(
true
)
try
{
try
{
const
defaultParams
=
{
ernie_name
:
'ERNIE-
Lite-8K-0922
'
,
stream
:
false
}
const
defaultParams
=
{
ernie_name
:
'ERNIE-
4.0-8K-Preview
'
,
stream
:
false
}
const
res
=
await
baiduAIChat
({
...
defaultParams
,
params
})
const
res
=
await
baiduAIChat
({
...
defaultParams
,
params
})
const
message
=
{
role
:
'assistant'
,
content
:
res
.
data
.
result
}
const
message
=
{
role
:
'assistant'
,
content
:
res
.
data
.
result
}
setMessages
(
prevMessages
=>
[...
prevMessages
,
message
])
setMessages
(
prevMessages
=>
[...
prevMessages
,
message
])
...
...
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论