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 = [ ...@@ -67,7 +67,10 @@ export const INLINE_ELEMENTS = [
'CON', 'CON',
'NCON', 'NCON',
'REVST', 'REVST',
'REVEND' 'REVEND',
'EXPD',
'EXPDNAME',
'ITEMNBR'
] ]
// 段落类节点标签(PARA 为英文段落,PARAC 为中文段落) // 段落类节点标签(PARA 为英文段落,PARAC 为中文段落)
...@@ -149,7 +152,8 @@ export const COMPOSITE_CONTAINER_MAP: Record<string, string[]> = { ...@@ -149,7 +152,8 @@ export const COMPOSITE_CONTAINER_MAP: Record<string, string[]> = {
TED: ['TOOLNAME', 'TOOLNBR'], TED: ['TOOLNAME', 'TOOLNBR'],
CON: ['CONNAME', 'CONNBR'], CON: ['CONNAME', 'CONNBR'],
GRAPHIC: ['TITLE'], GRAPHIC: ['TITLE'],
EINDATA: ['EIN'] EINDATA: ['EIN'],
EXPD: ['EXPDNAME', 'CSN', 'ITEMNBR']
} }
// 动态派生出所有复合容器节点标签集 // 动态派生出所有复合容器节点标签集
......
...@@ -226,14 +226,21 @@ export function getMinChildCount(parentTagName: string, childTagName: string): n ...@@ -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 (model.type === 'elementRef' && model.name === childTagName) {
if (isRepeatable) {
return model.occurrence === 'oneOrMore' || model.occurrence === 'once'
? 'oneOrMore'
: 'zeroOrMore'
}
return model.occurrence return model.occurrence
} }
if (model.children) { if (model.children) {
for (const child of model.children) { for (const child of model.children) {
const result = findChildOccurrence(child, childTagName) const result = findChildOccurrence(child, childTagName, isRepeatable)
if (result !== 'unknown') return result if (result !== 'unknown') return result
} }
} }
......
import type { XmlNode } from '@/types/xmlNode' import type { XmlNode } from '@/types/xmlNode'
import { useEditorStore, nodeSelectedRefs } from '@/store/editor' import { useEditorStore, nodeSelectedRefs } from '@/store/editor'
import { LIST_ITEM_TAGS, HEADER_TAGS, ROMAN_LOOKUP } from '../constants' 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' import { useI18n } from 'vue-i18n'
// 警示块级节点集合(WARNING / CAUTION / NOTE),用于注入 insideAlert 上下文 // 警示块级节点集合(WARNING / CAUTION / NOTE),用于注入 insideAlert 上下文
const ALERT_ROOT_TAGS = new Set(ALERT_BLOCK_TAGS) 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 }) { export function useDocNodeRenderer(props: { node: XmlNode; parent?: XmlNode | null; isInline?: boolean; insideRefBlock?: boolean }) {
const editorStore = useEditorStore() const editorStore = useEditorStore()
...@@ -55,10 +56,14 @@ export function useDocNodeRenderer(props: { node: XmlNode; parent?: XmlNode | nu ...@@ -55,10 +56,14 @@ export function useDocNodeRenderer(props: { node: XmlNode; parent?: XmlNode | nu
provide('insideChinese', true) provide('insideChinese', true)
} }
const renderInline = computed(() => {
return props.isInline || INLINE_ELEMENTS_SET.has(props.node.tagName)
})
// 判断是否是列表容器 (需要排除表格、主题、选项以及通过复合 Map 特殊渲染的各种复合父节点/容器) // 判断是否是列表容器 (需要排除表格、主题、选项以及通过复合 Map 特殊渲染的各种复合父节点/容器)
const isContainer = computed(() => { const isContainer = computed(() => {
return ( return (
!props.isInline && !renderInline.value &&
props.node.children && props.node.children &&
props.node.children.length > 0 && props.node.children.length > 0 &&
props.node.tagName !== 'TABLE' && props.node.tagName !== 'TABLE' &&
...@@ -365,6 +370,7 @@ export function useDocNodeRenderer(props: { node: XmlNode; parent?: XmlNode | nu ...@@ -365,6 +370,7 @@ export function useDocNodeRenderer(props: { node: XmlNode; parent?: XmlNode | nu
editorStore, editorStore,
isSelected, isSelected,
isContainer, isContainer,
renderInline,
isListItem, isListItem,
isHeaderTag, isHeaderTag,
isInsideAlert, isInsideAlert,
......
<template> <template>
<component <component
:is="isInline ? 'span' : 'div'" :is="renderInline ? 'span' : 'div'"
:data-node-id="node.id" :data-node-id="node.id"
class="doc-node-wrapper relative transition-all" class="doc-node-wrapper relative transition-all"
:class="[ :class="[
isInline ? 'inline align-baseline mx-0.5' : 'block my-1', renderInline ? 'inline align-baseline mx-0.5' : 'block my-1',
isSelected ? 'ring-2 ring-primary ring-offset-1 rounded-sm bg-primary/5' : '', isSelected ? 'ring-2 ring-primary ring-offset-1 rounded-sm bg-primary/5' : '',
!isInline && isContainer ? 'py-1 px-1' : '' !renderInline && isContainer ? 'py-1 px-1' : ''
]" ]"
:style="node.attributes?.MERGED === 'TRUE' ? { backgroundColor: 'yellow' } : {}" :style="node.attributes?.MERGED === 'TRUE' ? { backgroundColor: 'yellow' } : {}"
@click.stop="editorStore.setSelectedNodeId(node.id)" @click.stop="editorStore.setSelectedNodeId(node.id)"
...@@ -44,7 +44,7 @@ ...@@ -44,7 +44,7 @@
<!-- 2. EFFECT / CONEFFECT (适用性) 特殊处理 --> <!-- 2. EFFECT / CONEFFECT (适用性) 特殊处理 -->
<template v-else-if="node.tagName === 'EFFECT' || node.tagName === 'CONEFFECT'"> <template v-else-if="node.tagName === 'EFFECT' || node.tagName === 'CONEFFECT'">
<span v-if="isInline" class="font-bold text-xs select-none py-1 uppercase mx-1 italic" style="color: red"> <span v-if="renderInline" class="font-bold text-xs select-none py-1 uppercase mx-1 italic" style="color: red">
** {{ node.tagName === 'EFFECT' ? 'ON A/C' : 'CONF' }}: {{ formatEff(node.attributes.EFFRG || node.textContent) }} ** {{ node.tagName === 'EFFECT' ? 'ON A/C' : 'CONF' }}: {{ formatEff(node.attributes.EFFRG || node.textContent) }}
</span> </span>
<div <div
...@@ -58,7 +58,7 @@ ...@@ -58,7 +58,7 @@
<!-- 3. SBEFF / SBEFFC (服务通告适用性) 处理 --> <!-- 3. SBEFF / SBEFFC (服务通告适用性) 处理 -->
<template v-else-if="node.tagName === 'SBEFF' || node.tagName === 'SBEFFC'"> <template v-else-if="node.tagName === 'SBEFF' || node.tagName === 'SBEFFC'">
<span v-if="isInline" class="font-bold text-xs select-none py-1 uppercase mx-1 italic" style="color: red"> <span v-if="renderInline" class="font-bold text-xs select-none py-1 uppercase mx-1 italic" style="color: red">
** SB: {{ node.attributes.SBCOND }} SB {{ node.attributes.SBNBR }} for A/C {{ formatEff(node.attributes.EFFRG) }} ** SB: {{ node.attributes.SBCOND }} SB {{ node.attributes.SBNBR }} for A/C {{ formatEff(node.attributes.EFFRG) }}
</span> </span>
<div <div
...@@ -175,22 +175,124 @@ ...@@ -175,22 +175,124 @@
</span> </span>
</template> </template>
<!-- 8. REFINT / REFEXT (引用链接) 特殊处理 --> <!-- 8. REFINT (内部引用链接) 特殊处理 -->
<template v-else-if="node.tagName === 'REFINT' || node.tagName === 'REFEXT'"> <template v-else-if="node.tagName === 'REFINT'">
<span <span
class="inline-ref font-mono font-medium hover:underline cursor-pointer select-all" class="inline-ref font-mono font-medium hover:underline cursor-pointer select-all"
style="color: blue" style="color: blue"
@click.stop="editorStore.setSelectedNodeId(node.id)" @click.stop="editorStore.setSelectedNodeId(node.id)"
> >
<template v-if="!insideRefBlock"> <template v-if="!insideRefBlock">
{{ isChineseContext ? '(参考: ' : '(Ref: ' }}{{ node.textContent || node.attributes.REFLOC || '' }}{{ ')' }} {{ isChineseContext ? '(参考: ' : '(Ref: ' }}
<template v-if="node.mixedContent && node.mixedContent.length > 0">
<template v-for="(item, index) in node.mixedContent" :key="index">
<span
v-if="item.type === 'text'"
contenteditable="true"
class="focus:outline-none focus:bg-fill-3 px-0.5 rounded inline"
style="color: blue"
@blur="handleMixedTextBlur(index, $event)"
v-text="item.text"
></span>
<DocNodeRenderer
v-else-if="item.type === 'element' && getChildNode(item.nodeId!)"
:node="getChildNode(item.nodeId!)!"
:parent="node"
is-inline
:inside-ref-block="insideRefBlock"
/>
</template>
</template>
<template v-else-if="node.children && node.children.length > 0">
<DocNodeRenderer
v-for="child in node.children"
:key="child.id"
:node="child"
:parent="node"
is-inline
:inside-ref-block="insideRefBlock"
/>
</template> </template>
<template v-else> <template v-else>
{{ node.textContent || node.attributes.REFLOC || '' }} <span
contenteditable="true"
class="focus:outline-none focus:bg-fill-3 px-0.5 rounded inline"
@blur="handleTextBlur"
v-text="node.textContent || node.attributes.REFID || '—'"
></span>
</template>
{{ ')' }}
</template>
<template v-else>
<template v-if="node.mixedContent && node.mixedContent.length > 0">
<template v-for="(item, index) in node.mixedContent" :key="index">
<span
v-if="item.type === 'text'"
contenteditable="true"
class="focus:outline-none focus:bg-fill-3 px-0.5 rounded inline"
style="color: blue"
@blur="handleMixedTextBlur(index, $event)"
v-text="item.text"
></span>
<DocNodeRenderer
v-else-if="item.type === 'element' && getChildNode(item.nodeId!)"
:node="getChildNode(item.nodeId!)!"
:parent="node"
is-inline
:inside-ref-block="insideRefBlock"
/>
</template>
</template>
<template v-else-if="node.children && node.children.length > 0">
<DocNodeRenderer
v-for="child in node.children"
:key="child.id"
:node="child"
:parent="node"
is-inline
:inside-ref-block="insideRefBlock"
/>
</template>
<template v-else>
<span
contenteditable="true"
class="focus:outline-none focus:bg-fill-3 px-0.5 rounded inline"
@blur="handleTextBlur"
v-text="node.textContent || node.attributes.REFID || '—'"
></span>
</template>
</template> </template>
</span> </span>
</template> </template>
<!-- 8.2 REFEXT (外部引用链接) 特殊处理 -->
<template v-else-if="node.tagName === 'REFEXT'">
<span
class="inline-ref font-mono font-medium hover:underline cursor-pointer select-all"
style="color: blue"
@click.stop="editorStore.setSelectedNodeId(node.id)"
>
<template v-if="!insideRefBlock">
{{ isChineseContext ? '(参考: ' : '(Ref: '
}}<span
contenteditable="true"
class="focus:outline-none focus:bg-fill-3 px-0.5 rounded inline"
@blur="handleTextBlur"
v-text="node.textContent || node.attributes.REFLOC || '—'"
></span>{{ ')' }}
</template>
<template v-else>
<span
contenteditable="true"
class="focus:outline-none focus:bg-fill-3 px-0.5 rounded inline"
@blur="handleTextBlur"
v-text="node.textContent || node.attributes.REFLOC || '—'"
></span>
</template>
</span>
</template>
<!-- 8.5 GRPHCREF (图形交叉引用) 特殊处理 --> <!-- 8.5 GRPHCREF (图形交叉引用) 特殊处理 -->
<template v-else-if="node.tagName === 'GRPHCREF'"> <template v-else-if="node.tagName === 'GRPHCREF'">
<span <span
...@@ -199,37 +301,85 @@ ...@@ -199,37 +301,85 @@
@click.stop="editorStore.setSelectedNodeId(node.id)" @click.stop="editorStore.setSelectedNodeId(node.id)"
> >
<template v-if="!insideRefBlock"> <template v-if="!insideRefBlock">
{{ isChineseContext ? '(参考: ' : '(Ref: ' {{ isChineseContext ? '(参考: ' : '(Ref: ' }}
}}{{ <template v-if="node.mixedContent && node.mixedContent.length > 0">
(node.mixedContent && node.mixedContent.length > 0 <template v-for="(item, index) in node.mixedContent" :key="index">
? node.mixedContent <span
.filter((m) => m.type === 'text') v-if="item.type === 'text'"
.map((m) => m.text || '') contenteditable="true"
.join('') class="focus:outline-none focus:bg-fill-3 px-0.5 rounded inline"
.trim() style="color: blue"
: node.textContent || '' @blur="handleMixedTextBlur(index, $event)"
).trim() || v-text="item.text"
node.attributes.REFID || ></span>
node.attributes.STRUCTID || <DocNodeRenderer
'—' v-else-if="item.type === 'element' && getChildNode(item.nodeId!)"
}} :node="getChildNode(item.nodeId!)!"
:parent="node"
is-inline
:inside-ref-block="insideRefBlock"
/>
</template>
</template>
<template v-else-if="node.children && node.children.length > 0">
<DocNodeRenderer
v-for="child in node.children"
:key="child.id"
:node="child"
:parent="node"
is-inline
:inside-ref-block="insideRefBlock"
/>
</template>
<template v-else>
<span
contenteditable="true"
class="focus:outline-none focus:bg-fill-3 px-0.5 rounded inline"
@blur="handleTextBlur"
v-text="node.textContent || node.attributes.REFID || node.attributes.STRUCTID || '—'"
></span>
</template>
<template v-if="node.attributes.SHEETNBR">[Sh.{{ node.attributes.SHEETNBR }}]</template> <template v-if="node.attributes.SHEETNBR">[Sh.{{ node.attributes.SHEETNBR }}]</template>
{{ ')' }} {{ ')' }}
</template> </template>
<template v-else> <template v-else>
{{ <template v-if="node.mixedContent && node.mixedContent.length > 0">
(node.mixedContent && node.mixedContent.length > 0 <template v-for="(item, index) in node.mixedContent" :key="index">
? node.mixedContent <span
.filter((m) => m.type === 'text') v-if="item.type === 'text'"
.map((m) => m.text || '') contenteditable="true"
.join('') class="focus:outline-none focus:bg-fill-3 px-0.5 rounded inline"
.trim() style="color: blue"
: node.textContent || '' @blur="handleMixedTextBlur(index, $event)"
).trim() || v-text="item.text"
node.attributes.REFID || ></span>
node.attributes.STRUCTID || <DocNodeRenderer
'—' v-else-if="item.type === 'element' && getChildNode(item.nodeId!)"
}} :node="getChildNode(item.nodeId!)!"
:parent="node"
is-inline
:inside-ref-block="insideRefBlock"
/>
</template>
</template>
<template v-else-if="node.children && node.children.length > 0">
<DocNodeRenderer
v-for="child in node.children"
:key="child.id"
:node="child"
:parent="node"
is-inline
:inside-ref-block="insideRefBlock"
/>
</template>
<template v-else>
<span
contenteditable="true"
class="focus:outline-none focus:bg-fill-3 px-0.5 rounded inline"
@blur="handleTextBlur"
v-text="node.textContent || node.attributes.REFID || node.attributes.STRUCTID || '—'"
></span>
</template>
<template v-if="node.attributes.SHEETNBR">[Sh.{{ node.attributes.SHEETNBR }}]</template> <template v-if="node.attributes.SHEETNBR">[Sh.{{ node.attributes.SHEETNBR }}]</template>
</template> </template>
</span> </span>
...@@ -300,6 +450,32 @@ ...@@ -300,6 +450,32 @@
</span> </span>
</template> </template>
<!-- 13.5 EXPD (消耗品数据组合) 统一配置化渲染 -->
<template v-else-if="node.tagName === 'EXPD'">
<span
class="text-color1 cursor-pointer select-none inline-flex items-center space-x-1"
@click.stop="editorStore.setSelectedNodeId(node.id)"
>
<template v-if="node.children && node.children.length > 0">
<template v-for="childTag in COMPOSITE_CONTAINER_MAP[node.tagName]" :key="childTag">
<template v-if="node.children.find((c) => c.tagName === childTag)">
<span v-if="childTag === 'CSN'" class="text-color3 select-none mx-0.5">
(Fin:
</span>
<span v-else-if="childTag === 'ITEMNBR'" class="text-color3 select-none mx-0.5">
(Nbr:
</span>
<DocNodeRenderer :node="node.children.find((c) => c.tagName === childTag)!" :parent="node" is-inline />
<span v-if="childTag === 'CSN' || childTag === 'ITEMNBR'" class="text-color3 select-none mx-0.5">)</span>
</template>
</template>
</template>
<template v-else>
<span class="text-color3 italic">[EXPD]</span>
</template>
</span>
</template>
<!-- 15. CB / CBNAME / CBLOC (断路器信息) 特殊处理 --> <!-- 15. CB / CBNAME / CBLOC (断路器信息) 特殊处理 -->
<template v-else-if="CB_COMPONENT_SET.has(node.tagName)"> <template v-else-if="CB_COMPONENT_SET.has(node.tagName)">
<span <span
...@@ -749,7 +925,7 @@ ...@@ -749,7 +925,7 @@
<!-- 27. 兜底未匹配的普通文本标签 --> <!-- 27. 兜底未匹配的普通文本标签 -->
<template v-else> <template v-else>
<span <span
v-if="isInline" v-if="renderInline"
contenteditable="true" contenteditable="true"
class="focus:outline-none focus:bg-fill-3 px-0.5 rounded" class="focus:outline-none focus:bg-fill-3 px-0.5 rounded"
@blur="handleTextBlur" @blur="handleTextBlur"
...@@ -822,6 +998,7 @@ const { ...@@ -822,6 +998,7 @@ const {
editorStore, editorStore,
isSelected, isSelected,
isContainer, isContainer,
renderInline,
isListItem, isListItem,
isHeaderTag, isHeaderTag,
isInsideAlert, isInsideAlert,
......
...@@ -1145,6 +1145,7 @@ export function useNodeTree( ...@@ -1145,6 +1145,7 @@ export function useNodeTree(
editorStore.setSelectedNodeId(parent.id) editorStore.setSelectedNodeId(parent.id)
editorStore.rebuildNodeMap() editorStore.rebuildNodeMap()
} else { } else {
editorStore.setSelectedNodeId(realNodeId)
editorStore.deleteSelectedNode() editorStore.deleteSelectedNode()
} }
window.$message?.success('删除成功') window.$message?.success('删除成功')
......
...@@ -1699,6 +1699,12 @@ export function useTableEditor(props: { node: XmlNode }) { ...@@ -1699,6 +1699,12 @@ export function useTableEditor(props: { node: XmlNode }) {
return styles 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 { return {
structure, structure,
selectedCellIds, selectedCellIds,
...@@ -1739,6 +1745,7 @@ export function useTableEditor(props: { node: XmlNode }) { ...@@ -1739,6 +1745,7 @@ export function useTableEditor(props: { node: XmlNode }) {
splitCell, splitCell,
insertedRowIds, insertedRowIds,
insertedCellIds, insertedCellIds,
getRowNonEntryChildren,
// 样式计算 // 样式计算
colWidthStyles, colWidthStyles,
tableFrameClass, tableFrameClass,
......
...@@ -28,9 +28,23 @@ ...@@ -28,9 +28,23 @@
class="transition-all" class="transition-all"
:class="[isNodeSelected(structure.theadId) ? 'outline outline-2 outline-primary outline-offset-[-2px] bg-primary/5' : '']" :class="[isNodeSelected(structure.theadId) ? 'outline outline-2 outline-primary outline-offset-[-2px] bg-primary/5' : '']"
> >
<template v-for="(row, rIdx) in structure.theadRows" :key="row.id">
<!-- 如果 ROW 拥有非 ENTRY 子节点 (如 EFFECT, CONEFFECT, REVST, REVEND) -->
<tr v-if="getRowNonEntryChildren(row.id).length > 0" class="bg-fill-1">
<th class="p-1 border border-divider bg-fill-4"></th>
<th :colspan="structure.cols" class="p-1 border border-divider text-left align-middle space-x-1 font-normal">
<DocNodeRenderer
v-for="child in getRowNonEntryChildren(row.id)"
:key="child.id"
:node="child"
:parent="editorStore.nodeMap.get(row.id)?.node"
is-inline
/>
</th>
<th class="p-1 border border-divider bg-fill-4"></th>
</tr>
<tr <tr
v-for="(row, rIdx) in structure.theadRows"
:key="row.id"
:data-node-id="row.id" :data-node-id="row.id"
class="border-b border-divider hover:bg-fill-3 group transition-colors cursor-pointer transition-all" class="border-b border-divider hover:bg-fill-3 group transition-colors cursor-pointer transition-all"
:class="[ :class="[
...@@ -90,6 +104,7 @@ ...@@ -90,6 +104,7 @@
</CommonButton> </CommonButton>
</th> </th>
</tr> </tr>
</template>
</thead> </thead>
<!-- TBODY 渲染 --> <!-- TBODY 渲染 -->
...@@ -99,9 +114,23 @@ ...@@ -99,9 +114,23 @@
class="transition-all" class="transition-all"
:class="[isNodeSelected(structure.tbodyId) ? 'outline outline-2 outline-primary outline-offset-[-2px] bg-primary/5' : '']" :class="[isNodeSelected(structure.tbodyId) ? 'outline outline-2 outline-primary outline-offset-[-2px] bg-primary/5' : '']"
> >
<template v-for="(row, rIdx) in structure.tbodyRows" :key="row.id">
<!-- 如果 ROW 拥有非 ENTRY 子节点 (如 EFFECT, CONEFFECT, REVST, REVEND) -->
<tr v-if="getRowNonEntryChildren(row.id).length > 0" class="bg-fill-1">
<td class="p-1 border border-divider bg-fill-4"></td>
<td :colspan="structure.cols" class="p-1 border border-divider text-left align-middle space-x-1">
<DocNodeRenderer
v-for="child in getRowNonEntryChildren(row.id)"
:key="child.id"
:node="child"
:parent="editorStore.nodeMap.get(row.id)?.node"
is-inline
/>
</td>
<td class="p-1 border border-divider"></td>
</tr>
<tr <tr
v-for="(row, rIdx) in structure.tbodyRows"
:key="row.id"
:data-node-id="row.id" :data-node-id="row.id"
class="border-b border-divider hover:bg-fill-3 group transition-colors cursor-pointer transition-all" class="border-b border-divider hover:bg-fill-3 group transition-colors cursor-pointer transition-all"
:class="[ :class="[
...@@ -161,6 +190,7 @@ ...@@ -161,6 +190,7 @@
</CommonButton> </CommonButton>
</td> </td>
</tr> </tr>
</template>
<!-- 列删除快捷按钮行 --> <!-- 列删除快捷按钮行 -->
<tr class="hover:bg-transparent"> <tr class="hover:bg-transparent">
...@@ -240,6 +270,7 @@ const { ...@@ -240,6 +270,7 @@ const {
batchDeleteColumns, batchDeleteColumns,
insertedRowIds, insertedRowIds,
insertedCellIds, insertedCellIds,
getRowNonEntryChildren,
colWidthStyles, colWidthStyles,
tableFrameClass, tableFrameClass,
getCellStyle getCellStyle
......
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