Commit 047f00db by pangchong

refactor(editor): 重构编辑区右键菜单为函数式下拉菜单

- 将 EditAreaContextMenuModal 由模态窗口改为基于 Dropdown 的浮动下拉菜单
- 支持右键位置自适应,新增 contextMenuX、contextMenuY 用于定位菜单坐标
- 新增 TargetNodeItem 组件,支持目标节点层级列表字典树形选择与高亮
- 优化编辑节点菜单选项结构,包含节点编辑、结构调整、顺序调整、复制粘贴、智能翻译、查看规则等分组
- 实现目标节点切换逻辑,切换选中目标节点时同步更新左侧树视图选中状态
- 统一菜单项图标,提升菜单视觉一致性和用户体验
- 根据 DTD 规则及节点状态动态启用或禁用菜单项
- 移除了原有的 CommonModal 结构,简化组件实现与提升性能
- 调整 EditorPanel 组件代码,新增右键点击坐标传递及菜单弹出控制逻辑
- 修复节点标签和文本内容显示逻辑,完善标签名称与文本摘要展示
- 删除 xmlTags.ts 中未使用的 GRPHCREF 标签注释处理
parent 1e86e866
......@@ -31,7 +31,7 @@ export const INLINE_ELEMENTS = [
'REFBLOCK',
'REFINT',
'REFEXT',
'GRPHCREF',
// 'GRPHCREF',
// 零件编号类
'EIN',
'EINMFR',
......
<template>
<div
class="target-node-item"
:class="{ 'is-selected': isSelected }"
:style="{ paddingLeft: `${(item.depth || 0) * 12 + 12}px` }"
:title="item.displayName"
>
<span class="check-space">
<span v-if="isSelected" class="check-icon"></span>
</span>
<span class="node-tag">{{ item.tagName }}</span>
<span v-if="item.suffix" class="node-suffix">{{ item.suffix }}</span>
</div>
</template>
<script setup lang="ts">
export interface TargetItem {
id: string
tagName: string
suffix: string
displayName: string
pathString: string
depth: number
}
defineProps<{
item: TargetItem
isSelected?: boolean
}>()
</script>
<style scoped>
.target-node-item {
display: flex;
align-items: center;
height: 32px;
line-height: 32px;
font-size: 13px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
color: var(--n-text-color);
user-select: none;
margin: 0 -12px;
padding-right: 12px;
box-sizing: border-box;
border-radius: 3px;
transition:
background-color 0.15s ease,
color 0.15s ease;
}
.target-node-item.is-selected {
color: var(--n-primary-color);
background-color: var(--n-option-color-active, rgba(112, 91, 246, 0.12));
font-weight: 600;
}
.check-space {
display: inline-flex;
align-items: center;
justify-content: center;
width: 18px;
height: 18px;
margin-right: 4px;
flex-shrink: 0;
}
.check-icon {
color: var(--n-primary-color);
font-weight: 800;
font-size: 13px;
line-height: 1;
}
.node-tag {
font-weight: 600;
font-family: monospace, var(--n-font-family);
flex-shrink: 0;
}
.target-node-item.is-selected .node-tag {
color: var(--n-primary-color);
font-weight: 700;
}
.node-suffix {
margin-left: 6px;
font-weight: 400;
opacity: 0.65;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
flex: 1;
min-width: 0;
max-width: 220px;
}
.target-node-item.is-selected .node-suffix {
color: var(--n-primary-color);
opacity: 0.9;
}
</style>
export interface EditAreaContextMenuProps {
modelValue: boolean
nodeIds: string[]
x?: number
y?: number
}
......@@ -67,8 +67,14 @@
<!-- 查找与替换浮动面板 -->
<FindReplacePanel v-model:visible="findReplaceVisible" :sync-editor-scroll="syncEditorScroll" />
<!-- 编辑区非 Table 元素右键上下文菜单弹窗 -->
<EditAreaContextMenuModal v-model="contextMenuVisible" :node-ids="contextMenuNodeIds" />
<!-- 编辑区非 Table 元素右键上下文菜单浮动下拉 -->
<EditAreaContextMenuModal
v-model="contextMenuVisible"
:node-ids="contextMenuNodeIds"
:x="contextMenuX"
:y="contextMenuY"
/>
<!-- 文本选择悬浮工具栏 -->
<SelectionToolbar />
......@@ -153,6 +159,8 @@ const handleEditSelectedNode = () => {
const contextMenuVisible = ref(false)
const contextMenuNodeIds = ref<string[]>([])
const contextMenuX = ref(0)
const contextMenuY = ref(0)
const handleContextMenu = (e: MouseEvent) => {
e.preventDefault()
......@@ -198,10 +206,13 @@ const handleContextMenu = (e: MouseEvent) => {
if (isInsideTable) return
if (ids.length > 0) {
contextMenuX.value = e.clientX
contextMenuY.value = e.clientY
contextMenuNodeIds.value = ids
contextMenuVisible.value = true
}
}
</script>
<style scoped>
......
......@@ -73,8 +73,11 @@ export function useAddNodeModal(formRef: Ref<FormInst | null>) {
const node = store.nodeMap.get(nodeId)?.node ?? null
return node ? `编辑节点 <${node.tagName}>` : '编辑节点'
}
if (nodeId && nodeId.includes('-txt-')) {
return `#text ${map[addNodeMode.value]}`
}
const node = store.nodeMap.get(nodeId)?.node ?? null
return node ? `${node.tagName} ${map[addNodeMode.value]}` : map[addNodeMode.value]
return node ? `<${node.tagName}> ${map[addNodeMode.value]}` : map[addNodeMode.value]
})
// 标签下拉选项
......
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