Commit c99a5aba by pangchong

feat: 右键菜单

parent a65a856e
...@@ -11,6 +11,7 @@ declare module 'vue' { ...@@ -11,6 +11,7 @@ declare module 'vue' {
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'] NDataTable: typeof import('naive-ui')['NDataTable']
NDropdown: typeof import('naive-ui')['NDropdown']
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']
......
...@@ -32,6 +32,7 @@ ...@@ -32,6 +32,7 @@
"@commitlint/config-conventional": "^19.8.0", "@commitlint/config-conventional": "^19.8.0",
"@types/lodash": "^4.17.5", "@types/lodash": "^4.17.5",
"@types/node": "^20.14.2", "@types/node": "^20.14.2",
"@vicons/fluent": "^0.13.0",
"@vitejs/plugin-vue": "^5.0.4", "@vitejs/plugin-vue": "^5.0.4",
"autoprefixer": "^10.4.17", "autoprefixer": "^10.4.17",
"husky": "^8.0.0", "husky": "^8.0.0",
...@@ -966,6 +967,12 @@ ...@@ -966,6 +967,12 @@
"@uppy/core": "^2.3.3" "@uppy/core": "^2.3.3"
} }
}, },
"node_modules/@vicons/fluent": {
"version": "0.13.0",
"resolved": "https://registry.npmmirror.com/@vicons/fluent/-/fluent-0.13.0.tgz",
"integrity": "sha512-bYGZsOE3qzvm3Cm43e7tybgGlr5ZUpYqtRZq0g0Tfupe8jIzLolpvQLNUt1zS8Mgt6goTbUk5YH7Fkv16jkykg==",
"dev": true
},
"node_modules/@vitejs/plugin-vue": { "node_modules/@vitejs/plugin-vue": {
"version": "5.0.4", "version": "5.0.4",
"resolved": "https://registry.npmmirror.com/@vitejs/plugin-vue/-/plugin-vue-5.0.4.tgz", "resolved": "https://registry.npmmirror.com/@vitejs/plugin-vue/-/plugin-vue-5.0.4.tgz",
......
...@@ -35,6 +35,7 @@ ...@@ -35,6 +35,7 @@
"@commitlint/config-conventional": "^19.8.0", "@commitlint/config-conventional": "^19.8.0",
"@types/lodash": "^4.17.5", "@types/lodash": "^4.17.5",
"@types/node": "^20.14.2", "@types/node": "^20.14.2",
"@vicons/fluent": "^0.13.0",
"@vitejs/plugin-vue": "^5.0.4", "@vitejs/plugin-vue": "^5.0.4",
"autoprefixer": "^10.4.17", "autoprefixer": "^10.4.17",
"husky": "^8.0.0", "husky": "^8.0.0",
......
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
export {} export {}
declare global { declare global {
const EffectScope: typeof import('vue')['EffectScope'] const EffectScope: typeof import('vue')['EffectScope']
const NIcon: typeof import('naive-ui')['NIcon']
const computed: typeof import('vue')['computed'] const computed: typeof import('vue')['computed']
const createApp: typeof import('vue')['createApp'] const createApp: typeof import('vue')['createApp']
const customRef: typeof import('vue')['customRef'] const customRef: typeof import('vue')['customRef']
......
...@@ -7,7 +7,6 @@ ...@@ -7,7 +7,6 @@
</div> </div>
<n-button @click="uploadXml" class="h-full">上传XML</n-button> <n-button @click="uploadXml" class="h-full">上传XML</n-button>
</div> </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>
...@@ -22,7 +21,16 @@ ...@@ -22,7 +21,16 @@
@click="handleClick" @click="handleClick"
@contextmenu.prevent="handleContextMenu" @contextmenu.prevent="handleContextMenu"
/> />
<!-- <n-popover :show="showPopover" :x="x" :y="y" trigger="manual">厉害!</n-popover> --> <n-dropdown
placement="bottom-start"
trigger="manual"
:x="dropdownConfig.x"
:y="dropdownConfig.y"
:options="dropdownConfig.options"
:show="dropdownConfig.show"
:on-clickoutside="onClickoutside"
@select="handleSelect"
/>
</n-card> </n-card>
</div> </div>
</div> </div>
...@@ -38,6 +46,7 @@ import renderElemConf from '../functions/render-elem' ...@@ -38,6 +46,7 @@ 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 { uploadXml } from '../functions' import { uploadXml } from '../functions'
import { ArrowLeft24Filled, ArrowRight24Filled, Book20Filled, TableInsertColumn24Filled } from '@vicons/fluent'
const module: Partial<IModuleConf> = { const module: Partial<IModuleConf> = {
renderElems: renderElemConf, renderElems: renderElemConf,
...@@ -100,7 +109,7 @@ const ps = defineProps({ ...@@ -100,7 +109,7 @@ const ps = defineProps({
default: false default: false
} }
}) })
const es = defineEmits(['change', 'created', 'update:modelValue', 'handleClick']) const es = defineEmits(['change', 'created', 'update:modelValue', 'handleClick', 'handleContextSelect'])
// 编辑器实例,必须用 shallowRef // 编辑器实例,必须用 shallowRef
const editorRef = shallowRef<IDomEditor>() const editorRef = shallowRef<IDomEditor>()
const valueHtml = ref('') const valueHtml = ref('')
...@@ -132,6 +141,7 @@ const handleClick = (event: any) => { ...@@ -132,6 +141,7 @@ const handleClick = (event: any) => {
} }
//获取key //获取key
const getKey = (elem: any): string => { const getKey = (elem: any): string => {
if (!elem) return ''
const key = elem.getAttribute('data-key') const key = elem.getAttribute('data-key')
if (key && elem != null) { if (key && elem != null) {
return key return key
...@@ -140,8 +150,76 @@ const getKey = (elem: any): string => { ...@@ -140,8 +150,76 @@ const getKey = (elem: any): string => {
return getKey(elem) return getKey(elem)
} }
} }
const handleContextMenu = () => { //右键菜单
console.log('右键菜单') const dropdownConfig = reactive({
show: false,
x: 0,
y: 0,
options: [
{
label: '左缩进',
key: 'left',
icon() {
return h(NIcon, null, {
default: () => h(ArrowLeft24Filled)
})
}
},
{
label: '右缩进',
key: 'right',
icon() {
return h(NIcon, null, {
default: () => h(ArrowRight24Filled)
})
}
},
{
label: '插入',
key: 'insert',
icon() {
return h(NIcon, null, {
default: () => h(TableInsertColumn24Filled)
})
},
children: [
{
label: 'TaskTitle',
key: 'TaskTitle',
icon() {
return h(NIcon, null, {
default: () => h(Book20Filled)
})
}
},
{
label: 'TopicTitle',
key: 'TopicTitle',
icon() {
return h(NIcon, null, {
default: () => h(Book20Filled)
})
}
}
]
}
]
})
const handleContextMenu = (event: MouseEvent) => {
dropdownConfig.show = false
nextTick(() => {
dropdownConfig.show = true
dropdownConfig.x = event.clientX
dropdownConfig.y = event.clientY
})
}
const handleSelect = (key: string | number) => {
dropdownConfig.show = false
editorRef.value?.restoreSelection()
es('handleContextSelect', key)
}
const onClickoutside = () => {
dropdownConfig.show = false
} }
// 编辑器配置 // 编辑器配置
const message = useMessage() const message = useMessage()
......
export const nodeSet = [ export const nodeSet = [
'p',
'TaskTitle',
'TopicTitle',
'JOBCARD', 'JOBCARD',
'CEP', 'CEP',
'TITLE', 'TITLE',
...@@ -20,4 +23,4 @@ export const nodeSet = [ ...@@ -20,4 +23,4 @@ export const nodeSet = [
'L4ITEM', 'L4ITEM',
'STEP', 'STEP',
'RECORD-LINE' 'RECORD-LINE'
] ]
\ No newline at end of file
import { IDomEditor } from '@wangeditor/editor' import { IDomEditor, SlateTransforms } from '@wangeditor/editor'
import { editorRef, showLoading, treeData, treeRef, treeSelectedKeys, xmlContent, xmlDOM } from '../constants' import { editorRef, showLoading, treeData, treeRef, treeSelectedKeys, xmlContent, xmlDOM } from '../constants'
import { TreeOption } from 'naive-ui' import { TreeOption } from 'naive-ui'
import { nodeSet } from '../constants/nodeParsed' import { nodeSet } from '../constants/nodeParsed'
export const handleEditor = (editor: IDomEditor) => { export const handleEditor = (editor: IDomEditor) => {
// if (editor.getHtml() == '<p><br></p>') return if (editor.getHtml() == '<p><br></p>') return
// const xmlProcessing = useXMLProcessing() console.log(editor.getHtml())
// const res = xmlProcessing.processXML(editor.getHtml(), nodeSet) const xmlProcessing = useXMLProcessing()
// treeData.value = res.treeData const res = xmlProcessing.processXML(editor.getHtml(), nodeSet)
// xmlDOM.value = res.xmlDOM treeData.value = res.treeData
// xmlContent.value = res.xmlContent xmlDOM.value = res.xmlDOM
xmlContent.value = res.xmlContent
} }
export const handleClick = (key: string) => { export const handleClick = (key: string) => {
...@@ -17,6 +18,16 @@ export const handleClick = (key: string) => { ...@@ -17,6 +18,16 @@ export const handleClick = (key: string) => {
treeSelectedKeys.value = [key] treeSelectedKeys.value = [key]
} }
export const handleContextSelect = (key: string) => {
if (key == 'TaskTitle') {
const node = { type: 'TaskTitle', dataKey: 'fasdfasdf', children: [{ text: 'TaskTitle' }] }
editorRef.value?.editorRef?.insertNode(node)
} else if (key == 'TopicTitle') {
const node = { type: 'TopicTitle', children: [{ text: 'TopicTitle' }] }
editorRef.value?.editorRef?.insertNode(node)
}
}
let lastFocusedId = '' let lastFocusedId = ''
export const nodeProps = ({ option }: { option: TreeOption }) => { export const nodeProps = ({ option }: { option: TreeOption }) => {
return { return {
......
<template> <template>
<n-spin class="h-full w-full" content-class="h-full w-full" :show="showLoading" description="加载中..."> <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" @handleClick="handleClick"> <ContentEditor
ref="editorRef"
v-model="formData.html"
@change="handleEditor"
@created="handleEditor"
@handleClick="handleClick"
@handleContextSelect="handleContextSelect"
>
<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">
<ContentTree></ContentTree> <ContentTree></ContentTree>
...@@ -14,7 +21,7 @@ ...@@ -14,7 +21,7 @@
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, showLoading, xmlContent } from './constants' import { editorRef, formData, showLoading, xmlContent } from './constants'
import { handleClick, handleEditor } from './functions' import { handleClick, handleEditor, handleContextSelect } from './functions'
onMounted(() => { onMounted(() => {
// nextTick(() => { // nextTick(() => {
......
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