Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
V
vue3_onlineEditor
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
pangchong
vue3_onlineEditor
Commits
35d47621
Commit
35d47621
authored
Mar 31, 2025
by
qlintonger xeno
Browse files
Options
Browse Files
Download
Plain Diff
Merge remote-tracking branch 'origin/master'
parents
cb10223e
433e1346
Show whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
62 additions
and
78 deletions
+62
-78
components.d.ts
+6
-0
src/views/editor/components/ContentEditor.vue
+9
-5
src/views/editor/constants/index.ts
+10
-12
src/views/editor/functions/extra-menu.ts
+0
-44
src/views/editor/functions/index.ts
+21
-15
src/views/editor/index.vue
+9
-1
vite.config.ts
+7
-1
No files found.
components.d.ts
View file @
35d47621
...
...
@@ -7,15 +7,21 @@ export {}
declare
module
'vue'
{
export
interface
GlobalComponents
{
NButton
:
typeof
import
(
'naive-ui'
)[
'NButton'
]
NCard
:
typeof
import
(
'naive-ui'
)[
'NCard'
]
NConfigProvider
:
typeof
import
(
'naive-ui'
)[
'NConfigProvider'
]
NDataTable
:
typeof
import
(
'naive-ui'
)[
'NDataTable'
]
NInput
:
typeof
import
(
'naive-ui'
)[
'NInput'
]
NLayout
:
typeof
import
(
'naive-ui'
)[
'NLayout'
]
NLayoutContent
:
typeof
import
(
'naive-ui'
)[
'NLayoutContent'
]
NLayoutFooter
:
typeof
import
(
'naive-ui'
)[
'NLayoutFooter'
]
NLayoutHeader
:
typeof
import
(
'naive-ui'
)[
'NLayoutHeader'
]
NMessageProvider
:
typeof
import
(
'naive-ui'
)[
'NMessageProvider'
]
NResult
:
typeof
import
(
'naive-ui'
)[
'NResult'
]
NSpace
:
typeof
import
(
'naive-ui'
)[
'NSpace'
]
NSpin
:
typeof
import
(
'naive-ui'
)[
'NSpin'
]
NTree
:
typeof
import
(
'naive-ui'
)[
'NTree'
]
NUpload
:
typeof
import
(
'naive-ui'
)[
'NUpload'
]
RouterLink
:
typeof
import
(
'vue-router'
)[
'RouterLink'
]
RouterView
:
typeof
import
(
'vue-router'
)[
'RouterView'
]
}
...
...
src/views/editor/components/ContentEditor.vue
View file @
35d47621
<
template
>
<div
class=
"z-10 h-full flex flex-col"
>
<!-- 工具栏 -->
<Toolbar
:editor=
"editorRef"
:editorId=
"editorId"
:defaultConfig=
"toolbarConfig"
class=
"border-b border-solid border-borderColor"
/>
<div
class=
"flex"
>
<div
class=
"flex-1"
>
<Toolbar
:editor=
"editorRef"
:editorId=
"editorId"
class=
"border-b border-solid border-borderColor"
/>
</div>
<n-button
@
click=
"uploadXml"
class=
"h-full"
>
上传XML
</n-button>
</div>
<!-- 编辑器 -->
<div
class=
"p-[15px] flex flex-1 overflow-hidden"
>
<slot
name=
"left"
></slot>
...
...
@@ -28,7 +34,7 @@ import { Boot, IModuleConf } from '@wangeditor/editor'
import
renderElemConf
from
'../functions/render-elem'
import
elemToHtmlConf
from
'../functions/elem-to-html'
import
parseHtmlConf
from
'../functions/parse-elem-html'
import
myMenuConf
from
'../functions/extra-menu
'
import
{
uploadXml
}
from
'../functions
'
const
module
:
Partial
<
IModuleConf
>
=
{
renderElems
:
renderElemConf
,
...
...
@@ -36,7 +42,6 @@ const module: Partial<IModuleConf> = {
parseElemsHtml
:
parseHtmlConf
}
Boot
.
registerModule
(
module
)
Boot
.
registerMenu
(
myMenuConf
)
// 注册菜单
//菜单配置
const
toolbarConfig
=
{
...
...
@@ -59,8 +64,7 @@ const toolbarConfig = {
'uploadImage'
,
'insertLink'
,
'fullScreen'
,
'clearStyle'
,
'XML'
'clearStyle'
]
}
...
...
src/views/editor/constants/index.ts
View file @
35d47621
...
...
@@ -2,10 +2,11 @@
import
type
{
TreeOption
}
from
'naive-ui'
import
{
TreeRenderResult
}
from
'@/lib/XMLProcessor/src/typing'
export
const
showLoading
=
ref
(
false
)
// 菜单相关
export
const
searchKey
=
ref
(
''
)
export
const
treeData
:
Ref
<
TreeOption
[]
>
=
ref
([])
export
const
xmlDOM
:
Ref
<
Document
>
=
ref
()
export
const
xmlDOM
:
Ref
<
Document
>
=
ref
()
export
const
treeSelectedKeys
=
ref
<
string
[]
>
([])
export
const
xmlContent
:
Ref
<
string
>
=
ref
(
''
)
//编辑器相关
...
...
@@ -15,36 +16,33 @@ export const formData = reactive({
})
// 递归函数:检查树中是否存在满足条件的节点
// 递归函数:检查树中是否存在满足条件的节点,并构建新的树结构
function
buildFilteredTree
(
tree
:
TreeRenderResult
,
searchString
:
string
):
TreeRenderResult
|
null
{
function
buildFilteredTree
(
tree
:
TreeRenderResult
,
searchString
:
string
):
TreeRenderResult
|
null
{
// 如果当前节点的 label 包含指定字符串,直接返回当前节点
if
(
tree
.
label
.
includes
(
searchString
))
{
return
{
...
tree
}
;
// 返回当前节点的副本
return
{
...
tree
}
// 返回当前节点的副本
}
// 如果当前节点有子节点,递归检查每个子节点
if
(
tree
.
children
)
{
const
filteredChildren
:
TreeRenderResult
[]
=
[]
;
const
filteredChildren
:
TreeRenderResult
[]
=
[]
for
(
let
child
of
tree
.
children
)
{
const
result
=
buildFilteredTree
(
child
,
searchString
)
;
const
result
=
buildFilteredTree
(
child
,
searchString
)
if
(
result
)
{
filteredChildren
.
push
(
result
)
;
// 如果子节点符合条件,加入到当前节点的子节点列表
filteredChildren
.
push
(
result
)
// 如果子节点符合条件,加入到当前节点的子节点列表
}
}
// 如果有符合条件的子节点,返回当前节点,并更新子节点列表
if
(
filteredChildren
.
length
>
0
)
{
return
{
...
tree
,
children
:
filteredChildren
}
;
return
{
...
tree
,
children
:
filteredChildren
}
}
}
// 如果当前节点及其子节点都不满足条件,返回 null
return
null
;
return
null
}
export
const
realComposableData
=
computed
(
function
()
{
export
const
realComposableData
=
computed
(
function
()
{
if
(
!
searchKey
.
value
)
{
return
treeData
.
value
}
...
...
src/views/editor/functions/extra-menu.ts
deleted
100644 → 0
View file @
cb10223e
import
{
IButtonMenu
,
IDomEditor
}
from
'@wangeditor/editor'
import
{
uploadXml
}
from
'.'
class
XMLMenu
implements
IButtonMenu
{
title
:
string
tag
:
string
constructor
()
{
this
.
title
=
'上传XML'
// 自定义菜单标题
this
.
tag
=
'button'
// 菜单的标签,默认是button
}
getValue
(
editor
:
IDomEditor
):
string
|
boolean
{
// 获取菜单执行时的 value,用不到则返回空字符串或 false
return
''
}
isActive
(
editor
:
IDomEditor
):
boolean
{
// 菜单是否需要激活,用不到则返回 false
return
false
}
isDisabled
(
editor
:
IDomEditor
):
boolean
{
// 菜单是否需要禁用,用不到则返回 false
return
false
}
async
exec
(
editor
:
IDomEditor
,
value
:
string
|
boolean
)
{
// 点击菜单时触发的函数
if
(
this
.
isDisabled
(
editor
))
return
const
arrFileHandle
=
await
(
window
as
any
).
showOpenFilePicker
({
types
:
[
{
accept
:
{
'XML/*'
:
[
'.xml'
]
}
}
]
})
const
file
=
await
arrFileHandle
[
0
].
getFile
()
uploadXml
(
file
)
}
}
export
default
{
key
:
'XML'
,
// 定义 menu key,要保证唯一、不重复
factory
()
{
return
new
XMLMenu
()
// 返回定义的菜单类实例
}
}
src/views/editor/functions/index.ts
View file @
35d47621
import
{
IDomEditor
}
from
'@wangeditor/editor'
import
{
editorRef
,
treeData
,
xmlContent
,
xmlDOM
}
from
'../constants'
import
{
editorRef
,
showLoading
,
treeData
,
xmlContent
,
xmlDOM
}
from
'../constants'
import
{
TreeOption
}
from
'naive-ui'
import
{
nodeSet
}
from
'../constants/nodeParsed'
import
{
getCurrentInstance
,
getCurrentScope
}
from
'vue'
export
const
handleEditor
=
(
editor
:
IDomEditor
)
=>
{
// console.log(editor.getElemsByTypePrefix('JOBCARD'))
// console.log(editor)
// const headers = editor.getElemsByTypePrefix('header')
// const menu = headers.map((header: any) => {
// const title = SlateNode.string(header)
// return {
// title,
// key: header.id,
// type: header.type
// }
// })
// treeData.value = buildTree(menu)
// if (editor.getHtml() == '<p><br></p>') return
// const xmlProcessing = useXMLProcessing()
// const res = xmlProcessing.processXML(editor.getHtml(), nodeSet)
// treeData.value = res.treeData
// xmlDOM.value = res.xmlDOM
// xmlContent.value = res.xmlContent
}
let
lastFocusedId
=
''
...
...
@@ -35,11 +28,24 @@ export const nodeProps = ({ option }: { option: TreeOption }) => {
}
}
}
export
const
uploadXml
=
async
(
file
:
File
)
=>
{
export
const
uploadXml
=
async
()
=>
{
const
input
=
document
.
createElement
(
'input'
)
input
.
type
=
'file'
input
.
accept
=
'application/xml,text/xml'
input
.
multiple
=
false
input
.
click
()
input
.
addEventListener
(
'change'
,
async
(
event
:
Event
)
=>
{
const
files
=
(
event
.
target
as
HTMLInputElement
).
files
if
(
files
&&
files
.
length
>
0
)
{
const
file
=
files
[
0
]
const
xmlProcessing
=
useXMLProcessing
()
showLoading
.
value
=
true
const
res
=
await
xmlProcessing
.
processFile
(
file
,
nodeSet
)
showLoading
.
value
=
false
treeData
.
value
=
res
.
treeData
xmlDOM
.
value
=
res
.
xmlDOM
xmlContent
.
value
=
res
.
xmlContent
editorRef
.
value
?.
editorRef
?.
setHtml
(
xmlContent
.
value
)
}
})
}
src/views/editor/index.vue
View file @
35d47621
<
template
>
<n-spin
class=
"h-full w-full"
content-class=
"h-full w-full"
:show=
"showLoading"
description=
"加载中..."
>
<ContentEditor
ref=
"editorRef"
v-model=
"formData.html"
@
change=
"handleEditor"
@
created=
"handleEditor"
>
<template
#
left
>
<n-card
class=
"h-full min-w-[300px] max-w-[300px] mr-[15px]"
content-class=
"bg-baseColor !p-0 overflow-hidden"
>
...
...
@@ -6,13 +7,20 @@
</n-card>
</
template
>
</ContentEditor>
</n-spin>
</template>
<
script
setup
lang=
"ts"
>
import
ContentEditor
from
'./components/ContentEditor.vue'
import
ContentTree
from
'./components/ContentTree.vue'
import
{
editorRef
,
formData
}
from
'./constants'
import
{
editorRef
,
formData
,
showLoading
,
xmlContent
}
from
'./constants'
import
{
handleEditor
}
from
'./functions'
onMounted
(()
=>
{
// nextTick(() => {
// editorRef.value?.editorRef?.setHtml(xmlContent.value)
// })
})
</
script
>
<
style
lang=
"less"
scoped
>
:deep
(
.focus
)
{
...
...
vite.config.ts
View file @
35d47621
...
...
@@ -23,7 +23,7 @@ export default defineConfig({
{
'naive-ui'
:
[
'useDialog'
,
'useMessage'
,
'useNotification'
,
'useLoadingBar'
],
'@/hooks/useEventBus'
:
[
'useEventBus'
],
"@/lib/XMLProcessor/src/index"
:
[
'useXMLProcessing'
]
'@/lib/XMLProcessor/src/index'
:
[
'useXMLProcessing'
]
}
],
dts
:
'src/auto-import.d.ts'
,
...
...
@@ -39,5 +39,11 @@ export default defineConfig({
alias
:
{
'@'
:
resolve
(
'src'
)
}
},
base
:
'./'
,
// 打包路径
server
:
{
open
:
true
,
// 自动打开
cors
:
true
,
// 跨域
host
:
true
}
})
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment