Commit c99a5aba by pangchong

feat: 右键菜单

parent a65a856e
......@@ -11,6 +11,7 @@ declare module 'vue' {
NCard: typeof import('naive-ui')['NCard']
NConfigProvider: typeof import('naive-ui')['NConfigProvider']
NDataTable: typeof import('naive-ui')['NDataTable']
NDropdown: typeof import('naive-ui')['NDropdown']
NInput: typeof import('naive-ui')['NInput']
NLayout: typeof import('naive-ui')['NLayout']
NLayoutContent: typeof import('naive-ui')['NLayoutContent']
......
......@@ -32,6 +32,7 @@
"@commitlint/config-conventional": "^19.8.0",
"@types/lodash": "^4.17.5",
"@types/node": "^20.14.2",
"@vicons/fluent": "^0.13.0",
"@vitejs/plugin-vue": "^5.0.4",
"autoprefixer": "^10.4.17",
"husky": "^8.0.0",
......@@ -966,6 +967,12 @@
"@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": {
"version": "5.0.4",
"resolved": "https://registry.npmmirror.com/@vitejs/plugin-vue/-/plugin-vue-5.0.4.tgz",
......
......@@ -35,6 +35,7 @@
"@commitlint/config-conventional": "^19.8.0",
"@types/lodash": "^4.17.5",
"@types/node": "^20.14.2",
"@vicons/fluent": "^0.13.0",
"@vitejs/plugin-vue": "^5.0.4",
"autoprefixer": "^10.4.17",
"husky": "^8.0.0",
......
......@@ -6,6 +6,7 @@
export {}
declare global {
const EffectScope: typeof import('vue')['EffectScope']
const NIcon: typeof import('naive-ui')['NIcon']
const computed: typeof import('vue')['computed']
const createApp: typeof import('vue')['createApp']
const customRef: typeof import('vue')['customRef']
......
......@@ -7,7 +7,6 @@
</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>
......@@ -22,7 +21,16 @@
@click="handleClick"
@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>
</div>
</div>
......@@ -38,6 +46,7 @@ import renderElemConf from '../functions/render-elem'
import elemToHtmlConf from '../functions/elem-to-html'
import parseHtmlConf from '../functions/parse-elem-html'
import { uploadXml } from '../functions'
import { ArrowLeft24Filled, ArrowRight24Filled, Book20Filled, TableInsertColumn24Filled } from '@vicons/fluent'
const module: Partial<IModuleConf> = {
renderElems: renderElemConf,
......@@ -100,7 +109,7 @@ const ps = defineProps({
default: false
}
})
const es = defineEmits(['change', 'created', 'update:modelValue', 'handleClick'])
const es = defineEmits(['change', 'created', 'update:modelValue', 'handleClick', 'handleContextSelect'])
// 编辑器实例,必须用 shallowRef
const editorRef = shallowRef<IDomEditor>()
const valueHtml = ref('')
......@@ -132,6 +141,7 @@ const handleClick = (event: any) => {
}
//获取key
const getKey = (elem: any): string => {
if (!elem) return ''
const key = elem.getAttribute('data-key')
if (key && elem != null) {
return key
......@@ -140,8 +150,76 @@ const getKey = (elem: any): string => {
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()
......
export const nodeSet = [
'p',
'TaskTitle',
'TopicTitle',
'JOBCARD',
'CEP',
'TITLE',
......
import { IDomEditor } from '@wangeditor/editor'
import { IDomEditor, SlateTransforms } from '@wangeditor/editor'
import { editorRef, showLoading, treeData, treeRef, treeSelectedKeys, xmlContent, xmlDOM } from '../constants'
import { TreeOption } from 'naive-ui'
import { nodeSet } from '../constants/nodeParsed'
export const handleEditor = (editor: IDomEditor) => {
// 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
if (editor.getHtml() == '<p><br></p>') return
console.log(editor.getHtml())
const xmlProcessing = useXMLProcessing()
const res = xmlProcessing.processXML(editor.getHtml(), nodeSet)
treeData.value = res.treeData
xmlDOM.value = res.xmlDOM
xmlContent.value = res.xmlContent
}
export const handleClick = (key: string) => {
......@@ -17,6 +18,16 @@ export const handleClick = (key: string) => {
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 = ''
export const nodeProps = ({ option }: { option: TreeOption }) => {
return {
......
<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" @handleClick="handleClick">
<ContentEditor
ref="editorRef"
v-model="formData.html"
@change="handleEditor"
@created="handleEditor"
@handleClick="handleClick"
@handleContextSelect="handleContextSelect"
>
<template #left>
<n-card class="h-full min-w-[300px] max-w-[300px] mr-[15px]" content-class="bg-baseColor !p-0 overflow-hidden">
<ContentTree></ContentTree>
......@@ -14,7 +21,7 @@
import ContentEditor from './components/ContentEditor.vue'
import ContentTree from './components/ContentTree.vue'
import { editorRef, formData, showLoading, xmlContent } from './constants'
import { handleClick, handleEditor } from './functions'
import { handleClick, handleEditor, handleContextSelect } from './functions'
onMounted(() => {
// 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