Commit fae3e8cf by pangchong

feat(editor): 优化任务号渲染及支持TASK-HEADER虚拟节点

- 修改CEP和TASK节点中任务号的渲染样式,统一为普通字体且更紧凑的间距
- 新增TASK-HEADER虚拟节点用于EditorPanel中仿PDF样式展示任务号标题行
- TASK节点渲染新增递归子节点功能,确保完整展示任务结构
- 添加CHGDESC节点渲染,编辑区显示斜体变更说明且PDF中隐藏
- 更新getCepTaskNumber函数,支持CONFLTR和VARNBR属性拼接后缀,提升任务号生成正确性
- EditorPanel函数增加TASK节点处理,生成对应的TASK-HEADER虚拟节点
- NodeTree显示摘要中支持TASK和JC-TASK节点,任务号拼接规则与getCepTaskNumber保持一致
parent 5dda8631
......@@ -524,11 +524,14 @@ export const getSplitListChildren = (children?: XmlNode[]) => {
}
export const getCepTaskNumber = (node: XmlNode): string => {
const { CHAPPREF, CHAPNBR, SECTNBR, SUBJNBR, FUNC, SEQ, CONFLTR } = node.attributes || {}
const parts = [CHAPPREF, CHAPNBR, SECTNBR, SUBJNBR, FUNC, SEQ, CONFLTR].filter(Boolean)
const { CHAPPREF, CHAPNBR, SECTNBR, SUBJNBR, FUNC, SEQ, CONFLTR, VARNBR } = node.attributes || {}
// 仿照 PDF XSL generateTaskTitle:CONFLTR 和 VARNBR 拼接不加 "-",例如 A01
const suffix = CONFLTR ? `${CONFLTR}${VARNBR && VARNBR !== '0' ? VARNBR : ''}` : VARNBR && VARNBR !== '0' ? VARNBR : ''
const parts = [CHAPPREF, CHAPNBR, SECTNBR, SUBJNBR, FUNC, SEQ, suffix].filter(Boolean)
return parts.join('-')
}
export const isAllEinDataSameEffect = (einlst: XmlNode): boolean => {
if (!einlst.children || einlst.children.length === 0) return true
......
......@@ -1322,21 +1322,52 @@
<!-- 25.5 CEP-HEADER 虚拟节点(任务号)展现 -->
<template v-else-if="node.tagName === 'CEP-HEADER'">
<div class="my-2">
<div class="text-sm font-bold text-color1">任务 {{ getCepTaskNumber(node) }}</div>
<div class="my-1 py-0.5">
<span class="text-sm font-normal select-none">任务 {{ getCepTaskNumber(node) }}</span>
</div>
</template>
<!-- 25.6 CEP 节点(打印预览模式下展现任务号并递归渲染子节点) -->
<template v-else-if="node.tagName === 'CEP'">
<div class="space-y-1">
<div class="my-2">
<div class="text-sm font-bold text-color1">任务 {{ getCepTaskNumber(node) }}</div>
<div class="my-1 py-0.5">
<span class="text-sm font-normal select-none">任务 {{ getCepTaskNumber(node) }}</span>
</div>
<DocNodeRenderer v-for="child in node.children" :key="child.id" :node="child" :parent="node" />
</div>
</template>
<!-- 25.7 TASK-HEADER 虚拟节点(任务号标题行)展现 -->
<!-- EditorPanel 为每个 TASK 节点生成,仿 PDF 样式展示 "TASK XX-XX-XX-XXX-XXX-A01" -->
<template v-else-if="node.tagName === 'TASK-HEADER'">
<div class="my-1 py-0.5">
<span class="text-sm font-normal select-none">任务 {{ getCepTaskNumber(node) }}</span>
</div>
</template>
<!-- 25.8 TASK 节点直接渲染(非 EditorPanel 虚拟滚动路径,例如嵌在父节点内部) -->
<template v-else-if="node.tagName === 'TASK'">
<div class="space-y-1">
<div class="my-1 py-0.5">
<span class="text-sm font-normal select-none">任务 {{ getCepTaskNumber(node) }}</span>
</div>
<DocNodeRenderer v-for="child in node.children" :key="child.id" :node="child" :parent="node" />
</div>
</template>
<!-- 25.9 CHGDESC(变更说明):PDF 中该节点模板输出为空,编辑区以小字斜体提示样式展示 -->
<!-- 仿照 PDF 注释中的意图:italic 显示,前缀 "CHGDESC:" -->
<template v-else-if="node.tagName === 'CHGDESC'">
<div
class="text-xs italic select-none py-0.5 pl-1"
style="color: color-mix(in srgb, currentColor 50%, transparent)"
:title="'变更说明 (PDF 中隐藏)'"
>
<span class="font-semibold not-italic mr-1">CHGDESC:</span>{{ node.textContent }}
</div>
</template>
<!-- 26. 其它所有容器节点(如 JOBCARD, TFMATR, SUBTASK, LIST1... -->
<template v-else-if="isContainer">
<div class="space-y-1">
......
......@@ -80,6 +80,19 @@ export function useEditorPanel() {
}
blocks.push({ id: virtualHeaderNode.id, tagName: 'CEP-HEADER', rawNode: virtualHeaderNode })
n.children.forEach(walk)
} else if (n.tagName === 'TASK') {
// TASK 节点:创建虚拟 TASK-HEADER 展示任务编号,然后穿透子节点
const virtualTaskHeaderNode: XmlNode = {
id: n.id,
tagName: 'TASK-HEADER',
attributes: n.attributes || {},
textContent: '',
children: [],
mixedContent: [],
parentId: n.parentId
}
blocks.push({ id: virtualTaskHeaderNode.id, tagName: 'TASK-HEADER', rawNode: virtualTaskHeaderNode })
n.children.forEach(walk)
} else if (TRANSPARENT_TAGS_SET.has(n.tagName)) {
n.children.forEach(walk)
} else if (n.tagName === 'TOPIC') {
......
......@@ -18,7 +18,6 @@ import {
} from '@vicons/ionicons5'
import { useEditorStore } from '@/store/editor'
import { useAppStore } from '@/store/app'
import { useStashStore } from '@/store/stash'
import type { XmlNode } from '@/types/xmlNode'
import type { CheckRuleData, InsertMode, FlatNode, TranslationResponse } from '../constants'
import { DOCUMENT_LIKE_TAGS } from '../constants'
......@@ -254,9 +253,11 @@ export function useNodeTree(
} else if (node.tagName === 'CBLST') {
const action = node.attributes.ACTION === 'verif-close' ? '确认关闭' : node.attributes.ACTION === 'open' ? '断开' : '操作'
attrSummary = `行动: ${action}`
} else if (node.tagName === 'CEP' || node.tagName === 'SUBTASK') {
const { CHAPPREF, CHAPNBR, SECTNBR, SUBJNBR, FUNC, SEQ, CONFLTR } = node.attributes || {}
const parts = [CHAPPREF, CHAPNBR, SECTNBR, SUBJNBR, FUNC, SEQ, CONFLTR].filter(Boolean)
} else if (node.tagName === 'CEP' || node.tagName === 'TASK' || node.tagName === 'JC-TASK' || node.tagName === 'SUBTASK') {
const { CHAPPREF, CHAPNBR, SECTNBR, SUBJNBR, FUNC, SEQ, CONFLTR, VARNBR } = node.attributes || {}
// 仿照 PDF XSL generateTaskTitle:CONFLTR 和 VARNBR 拼接不加 "-",例如 A01
const suffix = CONFLTR ? `${CONFLTR}${VARNBR && VARNBR !== '0' ? VARNBR : ''}` : VARNBR && VARNBR !== '0' ? VARNBR : ''
const parts = [CHAPPREF, CHAPNBR, SECTNBR, SUBJNBR, FUNC, SEQ, suffix].filter(Boolean)
attrSummary = parts.join('-')
} else if (node.tagName === 'UNIT-RECORD') {
attrSummary = `单位: ${node.attributes.UNIT || 'mm'}`
......
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