Commit b6df8dc3 by pangchong

feat(editor): 优化文档节点渲染及表格编辑器功能

- 新增 EXPD、EXPDNAME、ITEMNBR 标签及其复合容器映射
- 优化 dtdManager 子元素出现约束判断,支持父节点重复属性传递
- DocNodeRenderer 组件中新增 renderInline 计算属性替代 isInline
- 增强引用(REFINT、REFEXT、GRPHCREF)内容的混合渲染和编辑功能
- 为 EXPD 标签定制统一配置化渲染方案
- TableEditor 组件支持表头及表体行中非 ENTRY 子节点展示
- 调整行选中样式及操作按钮位置,提升行选择和删除体验
- TableEditor functionals 新增获取行非 ENTRY 子节点方法,优化逻辑复用
- NodeTree 组件删除节点时修正选中节点行为,防止选中错误
parent feaf36ba
......@@ -67,7 +67,10 @@ export const INLINE_ELEMENTS = [
'CON',
'NCON',
'REVST',
'REVEND'
'REVEND',
'EXPD',
'EXPDNAME',
'ITEMNBR'
]
// 段落类节点标签(PARA 为英文段落,PARAC 为中文段落)
......@@ -149,7 +152,8 @@ export const COMPOSITE_CONTAINER_MAP: Record<string, string[]> = {
TED: ['TOOLNAME', 'TOOLNBR'],
CON: ['CONNAME', 'CONNBR'],
GRAPHIC: ['TITLE'],
EINDATA: ['EIN']
EINDATA: ['EIN'],
EXPD: ['EXPDNAME', 'CSN', 'ITEMNBR']
}
// 动态派生出所有复合容器节点标签集
......
......@@ -226,14 +226,21 @@ export function getMinChildCount(parentTagName: string, childTagName: string): n
/**
* 在内容模型树中查找子元素的出现约束
*/
function findChildOccurrence(model: DtdContentModel, childTagName: string): string {
function findChildOccurrence(model: DtdContentModel, childTagName: string, parentRepeatable = false): string {
const isRepeatable = parentRepeatable || model.occurrence === 'zeroOrMore' || model.occurrence === 'oneOrMore'
if (model.type === 'elementRef' && model.name === childTagName) {
if (isRepeatable) {
return model.occurrence === 'oneOrMore' || model.occurrence === 'once'
? 'oneOrMore'
: 'zeroOrMore'
}
return model.occurrence
}
if (model.children) {
for (const child of model.children) {
const result = findChildOccurrence(child, childTagName)
const result = findChildOccurrence(child, childTagName, isRepeatable)
if (result !== 'unknown') return result
}
}
......
import type { XmlNode } from '@/types/xmlNode'
import { useEditorStore, nodeSelectedRefs } from '@/store/editor'
import { LIST_ITEM_TAGS, HEADER_TAGS, ROMAN_LOOKUP } from '../constants'
import { ALERT_AND_EFF_TAGS, ALERT_BLOCK_TAGS, COMPOSITE_CONTAINER_MAP } from '@/configs/xmlTags'
import { ALERT_AND_EFF_TAGS, ALERT_BLOCK_TAGS, COMPOSITE_CONTAINER_MAP, INLINE_ELEMENTS } from '@/configs/xmlTags'
import { useI18n } from 'vue-i18n'
// 警示块级节点集合(WARNING / CAUTION / NOTE),用于注入 insideAlert 上下文
const ALERT_ROOT_TAGS = new Set(ALERT_BLOCK_TAGS)
const INLINE_ELEMENTS_SET = new Set(INLINE_ELEMENTS)
export function useDocNodeRenderer(props: { node: XmlNode; parent?: XmlNode | null; isInline?: boolean; insideRefBlock?: boolean }) {
const editorStore = useEditorStore()
......@@ -55,10 +56,14 @@ export function useDocNodeRenderer(props: { node: XmlNode; parent?: XmlNode | nu
provide('insideChinese', true)
}
const renderInline = computed(() => {
return props.isInline || INLINE_ELEMENTS_SET.has(props.node.tagName)
})
// 判断是否是列表容器 (需要排除表格、主题、选项以及通过复合 Map 特殊渲染的各种复合父节点/容器)
const isContainer = computed(() => {
return (
!props.isInline &&
!renderInline.value &&
props.node.children &&
props.node.children.length > 0 &&
props.node.tagName !== 'TABLE' &&
......@@ -365,6 +370,7 @@ export function useDocNodeRenderer(props: { node: XmlNode; parent?: XmlNode | nu
editorStore,
isSelected,
isContainer,
renderInline,
isListItem,
isHeaderTag,
isInsideAlert,
......
......@@ -1145,6 +1145,7 @@ export function useNodeTree(
editorStore.setSelectedNodeId(parent.id)
editorStore.rebuildNodeMap()
} else {
editorStore.setSelectedNodeId(realNodeId)
editorStore.deleteSelectedNode()
}
window.$message?.success('删除成功')
......
......@@ -1699,6 +1699,12 @@ export function useTableEditor(props: { node: XmlNode }) {
return styles
}
const getRowNonEntryChildren = (rowId: string): XmlNode[] => {
const rowNodeObj = store.nodeMap.get(rowId)
if (!rowNodeObj || !rowNodeObj.node.children) return []
return rowNodeObj.node.children.filter((c) => c.tagName !== 'ENTRY')
}
return {
structure,
selectedCellIds,
......@@ -1739,6 +1745,7 @@ export function useTableEditor(props: { node: XmlNode }) {
splitCell,
insertedRowIds,
insertedCellIds,
getRowNonEntryChildren,
// 样式计算
colWidthStyles,
tableFrameClass,
......
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