Commit 35d47621 by qlintonger xeno

Merge remote-tracking branch 'origin/master'

parents cb10223e 433e1346
...@@ -7,15 +7,21 @@ export {} ...@@ -7,15 +7,21 @@ export {}
declare module 'vue' { declare module 'vue' {
export interface GlobalComponents { export interface GlobalComponents {
NButton: typeof import('naive-ui')['NButton']
NCard: typeof import('naive-ui')['NCard'] NCard: typeof import('naive-ui')['NCard']
NConfigProvider: typeof import('naive-ui')['NConfigProvider'] NConfigProvider: typeof import('naive-ui')['NConfigProvider']
NDataTable: typeof import('naive-ui')['NDataTable']
NInput: typeof import('naive-ui')['NInput'] NInput: typeof import('naive-ui')['NInput']
NLayout: typeof import('naive-ui')['NLayout'] NLayout: typeof import('naive-ui')['NLayout']
NLayoutContent: typeof import('naive-ui')['NLayoutContent'] NLayoutContent: typeof import('naive-ui')['NLayoutContent']
NLayoutFooter: typeof import('naive-ui')['NLayoutFooter'] NLayoutFooter: typeof import('naive-ui')['NLayoutFooter']
NLayoutHeader: typeof import('naive-ui')['NLayoutHeader'] NLayoutHeader: typeof import('naive-ui')['NLayoutHeader']
NMessageProvider: typeof import('naive-ui')['NMessageProvider'] 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'] NTree: typeof import('naive-ui')['NTree']
NUpload: typeof import('naive-ui')['NUpload']
RouterLink: typeof import('vue-router')['RouterLink'] RouterLink: typeof import('vue-router')['RouterLink']
RouterView: typeof import('vue-router')['RouterView'] RouterView: typeof import('vue-router')['RouterView']
} }
......
<template> <template>
<div class="z-10 h-full flex flex-col"> <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"> <div class="p-[15px] flex flex-1 overflow-hidden">
<slot name="left"></slot> <slot name="left"></slot>
...@@ -28,7 +34,7 @@ import { Boot, IModuleConf } from '@wangeditor/editor' ...@@ -28,7 +34,7 @@ import { Boot, IModuleConf } from '@wangeditor/editor'
import renderElemConf from '../functions/render-elem' import renderElemConf from '../functions/render-elem'
import elemToHtmlConf from '../functions/elem-to-html' import elemToHtmlConf from '../functions/elem-to-html'
import parseHtmlConf from '../functions/parse-elem-html' import parseHtmlConf from '../functions/parse-elem-html'
import myMenuConf from '../functions/extra-menu' import { uploadXml } from '../functions'
const module: Partial<IModuleConf> = { const module: Partial<IModuleConf> = {
renderElems: renderElemConf, renderElems: renderElemConf,
...@@ -36,7 +42,6 @@ const module: Partial<IModuleConf> = { ...@@ -36,7 +42,6 @@ const module: Partial<IModuleConf> = {
parseElemsHtml: parseHtmlConf parseElemsHtml: parseHtmlConf
} }
Boot.registerModule(module) Boot.registerModule(module)
Boot.registerMenu(myMenuConf) // 注册菜单
//菜单配置 //菜单配置
const toolbarConfig = { const toolbarConfig = {
...@@ -59,8 +64,7 @@ const toolbarConfig = { ...@@ -59,8 +64,7 @@ const toolbarConfig = {
'uploadImage', 'uploadImage',
'insertLink', 'insertLink',
'fullScreen', 'fullScreen',
'clearStyle', 'clearStyle'
'XML'
] ]
} }
......
...@@ -2,10 +2,11 @@ ...@@ -2,10 +2,11 @@
import type { TreeOption } from 'naive-ui' import type { TreeOption } from 'naive-ui'
import { TreeRenderResult } from '@/lib/XMLProcessor/src/typing' import { TreeRenderResult } from '@/lib/XMLProcessor/src/typing'
export const showLoading = ref(false)
// 菜单相关 // 菜单相关
export const searchKey = ref('') export const searchKey = ref('')
export const treeData: Ref<TreeOption[]> = 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 treeSelectedKeys = ref<string[]>([])
export const xmlContent: Ref<string> = ref('') export const xmlContent: Ref<string> = ref('')
//编辑器相关 //编辑器相关
...@@ -15,36 +16,33 @@ export const formData = reactive({ ...@@ -15,36 +16,33 @@ export const formData = reactive({
}) })
// 递归函数:检查树中是否存在满足条件的节点 // 递归函数:检查树中是否存在满足条件的节点
// 递归函数:检查树中是否存在满足条件的节点,并构建新的树结构 // 递归函数:检查树中是否存在满足条件的节点,并构建新的树结构
function buildFilteredTree( function buildFilteredTree(tree: TreeRenderResult, searchString: string): TreeRenderResult | null {
tree: TreeRenderResult,
searchString: string
): TreeRenderResult | null {
// 如果当前节点的 label 包含指定字符串,直接返回当前节点 // 如果当前节点的 label 包含指定字符串,直接返回当前节点
if (tree.label.includes(searchString)) { if (tree.label.includes(searchString)) {
return { ...tree }; // 返回当前节点的副本 return { ...tree } // 返回当前节点的副本
} }
// 如果当前节点有子节点,递归检查每个子节点 // 如果当前节点有子节点,递归检查每个子节点
if (tree.children) { if (tree.children) {
const filteredChildren: TreeRenderResult[] = []; const filteredChildren: TreeRenderResult[] = []
for (let child of tree.children) { for (let child of tree.children) {
const result = buildFilteredTree(child, searchString); const result = buildFilteredTree(child, searchString)
if (result) { if (result) {
filteredChildren.push(result); // 如果子节点符合条件,加入到当前节点的子节点列表 filteredChildren.push(result) // 如果子节点符合条件,加入到当前节点的子节点列表
} }
} }
// 如果有符合条件的子节点,返回当前节点,并更新子节点列表 // 如果有符合条件的子节点,返回当前节点,并更新子节点列表
if (filteredChildren.length > 0) { if (filteredChildren.length > 0) {
return { ...tree, children: filteredChildren }; return { ...tree, children: filteredChildren }
} }
} }
// 如果当前节点及其子节点都不满足条件,返回 null // 如果当前节点及其子节点都不满足条件,返回 null
return null; return null
} }
export const realComposableData = computed(function() { export const realComposableData = computed(function () {
if (!searchKey.value) { if (!searchKey.value) {
return treeData.value return treeData.value
} }
......
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() // 返回定义的菜单类实例
}
}
import { IDomEditor } from '@wangeditor/editor' 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 { TreeOption } from 'naive-ui'
import { nodeSet } from '../constants/nodeParsed' import { nodeSet } from '../constants/nodeParsed'
import { getCurrentInstance, getCurrentScope } from 'vue'
export const handleEditor = (editor: IDomEditor) => { export const handleEditor = (editor: IDomEditor) => {
// console.log(editor.getElemsByTypePrefix('JOBCARD')) // if (editor.getHtml() == '<p><br></p>') return
// console.log(editor) // const xmlProcessing = useXMLProcessing()
// const headers = editor.getElemsByTypePrefix('header') // const res = xmlProcessing.processXML(editor.getHtml(), nodeSet)
// const menu = headers.map((header: any) => { // treeData.value = res.treeData
// const title = SlateNode.string(header) // xmlDOM.value = res.xmlDOM
// return { // xmlContent.value = res.xmlContent
// title,
// key: header.id,
// type: header.type
// }
// })
// treeData.value = buildTree(menu)
} }
let lastFocusedId = '' let lastFocusedId = ''
...@@ -35,11 +28,24 @@ export const nodeProps = ({ option }: { option: TreeOption }) => { ...@@ -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() const xmlProcessing = useXMLProcessing()
showLoading.value = true
const res = await xmlProcessing.processFile(file, nodeSet) const res = await xmlProcessing.processFile(file, nodeSet)
showLoading.value = false
treeData.value = res.treeData treeData.value = res.treeData
xmlDOM.value = res.xmlDOM xmlDOM.value = res.xmlDOM
xmlContent.value = res.xmlContent xmlContent.value = res.xmlContent
editorRef.value?.editorRef?.setHtml(xmlContent.value) editorRef.value?.editorRef?.setHtml(xmlContent.value)
}
})
} }
<template> <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"> <ContentEditor ref="editorRef" v-model="formData.html" @change="handleEditor" @created="handleEditor">
<template #left> <template #left>
<n-card class="h-full min-w-[300px] max-w-[300px] mr-[15px]" content-class="bg-baseColor !p-0 overflow-hidden"> <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 @@ ...@@ -6,13 +7,20 @@
</n-card> </n-card>
</template> </template>
</ContentEditor> </ContentEditor>
</n-spin>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import ContentEditor from './components/ContentEditor.vue' import ContentEditor from './components/ContentEditor.vue'
import ContentTree from './components/ContentTree.vue' import ContentTree from './components/ContentTree.vue'
import { editorRef, formData } from './constants' import { editorRef, formData, showLoading, xmlContent } from './constants'
import { handleEditor } from './functions' import { handleEditor } from './functions'
onMounted(() => {
// nextTick(() => {
// editorRef.value?.editorRef?.setHtml(xmlContent.value)
// })
})
</script> </script>
<style lang="less" scoped> <style lang="less" scoped>
:deep(.focus) { :deep(.focus) {
......
...@@ -23,7 +23,7 @@ export default defineConfig({ ...@@ -23,7 +23,7 @@ export default defineConfig({
{ {
'naive-ui': ['useDialog', 'useMessage', 'useNotification', 'useLoadingBar'], 'naive-ui': ['useDialog', 'useMessage', 'useNotification', 'useLoadingBar'],
'@/hooks/useEventBus': ['useEventBus'], '@/hooks/useEventBus': ['useEventBus'],
"@/lib/XMLProcessor/src/index": ['useXMLProcessing'] '@/lib/XMLProcessor/src/index': ['useXMLProcessing']
} }
], ],
dts: 'src/auto-import.d.ts', dts: 'src/auto-import.d.ts',
...@@ -39,5 +39,11 @@ export default defineConfig({ ...@@ -39,5 +39,11 @@ export default defineConfig({
alias: { alias: {
'@': resolve('src') '@': resolve('src')
} }
},
base: './', // 打包路径
server: {
open: true, // 自动打开
cors: true, // 跨域
host: true
} }
}) })
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment