Commit 9c439bf5 by pangchong

refactor(editor): 优化标签排序及公共标签组件替换

- 统一使用 CHINESE_FIRST_PARA_TAGS 替代硬编码的 ['PARAC', 'PARA'] 标签顺序
- 在表格结构初始化和单元格子元素排序中使用 CHINESE_FIRST_PARA_TAGS
- 批量翻译模块采用 TRANSLATE_TARGET_TAGS 作为默认目标标签列表
- 替换多处 vue 组件中 n-tag 为 CommonTag 以统一样式和功能
- 添加编辑器相关弹窗组件的 ref 暴露,简化调用逻辑
- 清理和优化部分 API 成功判断逻辑,移除无效判断条件
- 统一 viewXmlModal 和 checkRuleModal 等弹窗的打开方法调用
- 修复滚动条样式使用 CSS 变量,增强主题适配
- 删除无用或多余的 import 及属性声明,提高代码整洁度
parent f837beb0
...@@ -53,9 +53,6 @@ const createService = (baseURL: string) => { ...@@ -53,9 +53,6 @@ const createService = (baseURL: string) => {
if ( if (
json.code === 200 || json.code === 200 ||
json.code === '200' || json.code === '200' ||
json.code === 0 ||
json.code === '0' ||
json.success === true ||
(json.code === undefined && json.success === undefined) (json.code === undefined && json.success === undefined)
) { ) {
json.code = 200 json.code = 200
...@@ -86,9 +83,6 @@ const createService = (baseURL: string) => { ...@@ -86,9 +83,6 @@ const createService = (baseURL: string) => {
if ( if (
json.code === 200 || json.code === 200 ||
json.code === '200' || json.code === '200' ||
json.code === 0 ||
json.code === '0' ||
json.success === true ||
(json.code === undefined && json.success === undefined) (json.code === undefined && json.success === undefined)
) { ) {
json.code = 200 json.code = 200
...@@ -307,7 +301,7 @@ const createService = (baseURL: string) => { ...@@ -307,7 +301,7 @@ const createService = (baseURL: string) => {
// 情况 B:返回的是 JSON 对象(预检查成功) // 情况 B:返回的是 JSON 对象(预检查成功)
const resData = result as any const resData = result as any
if (resData && typeof resData === 'object' && (resData.code === 200 || resData.code === 0 || resData.code === '200')) { if (resData && typeof resData === 'object' && (resData.code === 200 || resData.code === '200')) {
// 如果已经是带 down=Y 的请求返回了 JSON(可能是某些特殊接口),则不再重试 // 如果已经是带 down=Y 的请求返回了 JSON(可能是某些特殊接口),则不再重试
if (data?.down === 'Y') return true if (data?.down === 'Y') return true
......
...@@ -86,7 +86,7 @@ ...@@ -86,7 +86,7 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { ref, computed, watch, nextTick, onMounted, onUnmounted } from 'vue'
import { useEditorStore } from '@/store/editor' import { useEditorStore } from '@/store/editor'
import type { XmlNode } from '@/types/xmlNode' import type { XmlNode } from '@/types/xmlNode'
......
...@@ -137,3 +137,10 @@ export const STRUCTURAL_TAGS = [ ...@@ -137,3 +137,10 @@ export const STRUCTURAL_TAGS = [
'WARNING', 'CAUTION', 'NOTE', 'HNANOTE', 'WARNING', 'CAUTION', 'NOTE', 'HNANOTE',
'CBSUBLST', 'GRAPHIC', 'FTNOTE', 'APPEND' 'CBSUBLST', 'GRAPHIC', 'FTNOTE', 'APPEND'
] ]
// 中文段落优先的标签排序列表
export const CHINESE_FIRST_PARA_TAGS = ['PARAC', 'PARA']
// 默认翻译目标标签列表
export const TRANSLATE_TARGET_TAGS = ['PARAC', 'TITLEC']
import { markRaw, nextTick, type Ref } from 'vue' import type { Ref } from 'vue'
import type { XmlNode } from '@/types/xmlNode' import type { XmlNode } from '@/types/xmlNode'
import type { EditorState } from './types' import type { EditorState } from './types'
import { createDefaultAttributes, canAddChild } from '@/utils/dtdManager' import { createDefaultAttributes, canAddChild } from '@/utils/dtdManager'
import { parseXmlToTree } from '@/utils/xmlParser' import { parseXmlToTree } from '@/utils/xmlParser'
import { useAppStore } from '@/store/app' import { useAppStore } from '@/store/app'
import { CHINESE_FIRST_PARA_TAGS } from '@/configs/xmlTags'
export const nodeSelectedRefs = new Map<string, Ref<boolean>>() export const nodeSelectedRefs = new Map<string, Ref<boolean>>()
...@@ -41,7 +42,7 @@ export const createTableStructure = (rows: number, cols: number, cellChildTags: ...@@ -41,7 +42,7 @@ export const createTableStructure = (rows: number, cols: number, cellChildTags:
if (cellChildTags && cellChildTags.length > 0) { if (cellChildTags && cellChildTags.length > 0) {
// 按照 PARAC -> PARA 的顺序插入,以确保 PARAC 始终在 PARA 节点的前面 // 按照 PARAC -> PARA 的顺序插入,以确保 PARAC 始终在 PARA 节点的前面
const order = ['PARAC', 'PARA'] const order = CHINESE_FIRST_PARA_TAGS
for (const tag of order) { for (const tag of order) {
if (cellChildTags.includes(tag)) { if (cellChildTags.includes(tag)) {
const childId = crypto.randomUUID() const childId = crypto.randomUUID()
...@@ -167,7 +168,7 @@ const createDefaultNodeStructure = (tagName: string): XmlNode => { ...@@ -167,7 +168,7 @@ const createDefaultNodeStructure = (tagName: string): XmlNode => {
const attributes = createDefaultAttributes(tagName) const attributes = createDefaultAttributes(tagName)
if (tagName === 'TABLE') { if (tagName === 'TABLE') {
return createTableStructure(3, 3, ['PARAC', 'PARA']) return createTableStructure(3, 3, CHINESE_FIRST_PARA_TAGS)
} }
if (tagName === 'GRAPHIC') { if (tagName === 'GRAPHIC') {
......
...@@ -409,7 +409,7 @@ ...@@ -409,7 +409,7 @@
<n-icon><image-outline /></n-icon> <n-icon><image-outline /></n-icon>
<span>工卡附图 [GNBR: {{ node.children.find((c) => c.tagName === 'SHEET')?.attributes.GNBR || '无' }}]</span> <span>工卡附图 [GNBR: {{ node.children.find((c) => c.tagName === 'SHEET')?.attributes.GNBR || '无' }}]</span>
</span> </span>
<n-tag size="small" type="primary">GRAPHIC</n-tag> <CommonTag size="small" type="primary">GRAPHIC</CommonTag>
</div> </div>
<!-- 拟物化卡片模拟设计图 --> <!-- 拟物化卡片模拟设计图 -->
<div <div
...@@ -442,7 +442,7 @@ ...@@ -442,7 +442,7 @@
<!-- 20. RECORD-LINE (记录项) 处理 --> <!-- 20. RECORD-LINE (记录项) 处理 -->
<template v-else-if="node.tagName === 'RECORD-LINE'"> <template v-else-if="node.tagName === 'RECORD-LINE'">
<div class="my-2 p-2 bg-fill-3 rounded border border-divider flex items-center space-x-2"> <div class="my-2 p-2 bg-fill-3 rounded border border-divider flex items-center space-x-2">
<n-tag type="info" size="small" round>记录项</n-tag> <CommonTag type="info" size="small" round>记录项</CommonTag>
<div <div
contenteditable="true" contenteditable="true"
class="flex-1 text-sm text-color2 font-medium focus:outline-none focus:bg-fill-2 px-1 rounded" class="flex-1 text-sm text-color2 font-medium focus:outline-none focus:bg-fill-2 px-1 rounded"
...@@ -457,7 +457,7 @@ ...@@ -457,7 +457,7 @@
<template v-else-if="node.tagName === 'UNIT-RECORD'"> <template v-else-if="node.tagName === 'UNIT-RECORD'">
<div class="my-2 p-2 bg-fill-3 rounded border border-divider flex items-center justify-between"> <div class="my-2 p-2 bg-fill-3 rounded border border-divider flex items-center justify-between">
<div class="flex items-center space-x-2 flex-1"> <div class="flex items-center space-x-2 flex-1">
<n-tag type="success" size="small" round>单位记录项</n-tag> <CommonTag type="success" size="small" round>单位记录项</CommonTag>
<div <div
contenteditable="true" contenteditable="true"
class="flex-1 text-sm text-color2 font-medium focus:outline-none focus:bg-fill-2 px-1 rounded" class="flex-1 text-sm text-color2 font-medium focus:outline-none focus:bg-fill-2 px-1 rounded"
......
...@@ -162,10 +162,10 @@ const handleContextMenu = (e: MouseEvent) => { ...@@ -162,10 +162,10 @@ const handleContextMenu = (e: MouseEvent) => {
background: transparent; background: transparent;
} }
.scrollbar-thin::-webkit-scrollbar-thumb { .scrollbar-thin::-webkit-scrollbar-thumb {
background: #e0e0e0; background: var(--divider-color, #e0e0e0);
border-radius: 2px; border-radius: 2px;
} }
.scrollbar-thin::-webkit-scrollbar-thumb:hover { .scrollbar-thin::-webkit-scrollbar-thumb:hover {
background: #18a058; background: var(--primary-color, #18a058);
} }
</style> </style>
import { type TranslateXmlResponse, type TranslationStatusResponse } from '../constants' import { type TranslateXmlResponse, type TranslationStatusResponse } from '../constants'
import { useEditorStore } from '@/store/editor' import { useEditorStore } from '@/store/editor'
import { TRANSLATE_TARGET_TAGS } from '@/configs/xmlTags'
export function useBatchTranslate() { export function useBatchTranslate() {
const editorStore = useEditorStore() const editorStore = useEditorStore()
...@@ -20,7 +21,7 @@ export function useBatchTranslate() { ...@@ -20,7 +21,7 @@ export function useBatchTranslate() {
logs.value.push({ time, text }) logs.value.push({ time, text })
} }
const availableTags = ref<string[]>(['PARAC', 'TITLEC']) const availableTags = ref<string[]>([...TRANSLATE_TARGET_TAGS])
const availableTagOptions = computed(() => { const availableTagOptions = computed(() => {
return availableTags.value.map((tag) => ({ label: tag, value: tag })) return availableTags.value.map((tag) => ({ label: tag, value: tag }))
}) })
...@@ -28,7 +29,7 @@ export function useBatchTranslate() { ...@@ -28,7 +29,7 @@ export function useBatchTranslate() {
const form = ref({ const form = ref({
model_name: 'glm-4-flash', model_name: 'glm-4-flash',
search_direction: 'en_to_zh', search_direction: 'en_to_zh',
target_tags: ['PARAC', 'TITLEC'], target_tags: [...TRANSLATE_TARGET_TAGS],
suffix: '', suffix: '',
use_parallel_method: true, use_parallel_method: true,
save_to_database: false, save_to_database: false,
......
<template> <template>
<CommonModal v-model="showModal" title="批量 XML 翻译" :width="600" :show-confirm="false" :show-cancel="false"> <CommonModal v-model="showModal" title="批量 XML 翻译" :width="600" :show-confirm="false" :show-cancel="false">
<template #header-extra> <template #header-extra>
<n-tag :type="statusType" size="small">{{ statusLabel }}</n-tag> <CommonTag :type="statusType" size="small">{{ statusLabel }}</CommonTag>
</template> </template>
<n-form v-if="!loading && !completed" label-placement="left" label-width="120" size="medium"> <n-form v-if="!loading && !completed" label-placement="left" label-width="120" size="medium">
...@@ -99,7 +99,7 @@ ...@@ -99,7 +99,7 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { ref, watch, nextTick } from 'vue'
import { CheckmarkCircleOutline } from '@vicons/ionicons5' import { CheckmarkCircleOutline } from '@vicons/ionicons5'
import { useBatchTranslate } from './functionals' import { useBatchTranslate } from './functionals'
......
...@@ -43,9 +43,8 @@ ...@@ -43,9 +43,8 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { ref, reactive } from 'vue'
import type { FormInst, FormRules } from 'naive-ui' import type { FormInst, FormRules } from 'naive-ui'
import CommonCheckbox from '@/components/CommonCheckbox.vue' import { CHINESE_FIRST_PARA_TAGS } from '@/configs/xmlTags'
const emit = defineEmits<{ const emit = defineEmits<{
confirm: [rows: number, cols: number, cellChildTags: string[]] confirm: [rows: number, cols: number, cellChildTags: string[]]
...@@ -62,7 +61,7 @@ const formRef = ref<FormInst | null>(null) ...@@ -62,7 +61,7 @@ const formRef = ref<FormInst | null>(null)
const form = reactive({ const form = reactive({
rows: 3, rows: 3,
cols: 3, cols: 3,
cellChildTags: ['PARAC', 'PARA'] cellChildTags: [...CHINESE_FIRST_PARA_TAGS]
}) })
const rules: FormRules = { const rules: FormRules = {
...@@ -73,7 +72,7 @@ const rules: FormRules = { ...@@ -73,7 +72,7 @@ const rules: FormRules = {
const open = () => { const open = () => {
form.rows = 3 form.rows = 3
form.cols = 3 form.cols = 3
form.cellChildTags = ['PARAC', 'PARA'] form.cellChildTags = [...CHINESE_FIRST_PARA_TAGS]
show.value = true show.value = true
} }
......
...@@ -12,7 +12,6 @@ ...@@ -12,7 +12,6 @@
placeholder="输入要查询的技术英语文本或中文词汇..." placeholder="输入要查询的技术英语文本或中文词汇..."
size="large" size="large"
class="flex-1" class="flex-1"
clearable
@keyup.enter="handleSearch" @keyup.enter="handleSearch"
> >
<template #prefix> <template #prefix>
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
<!-- 顶部操作 --> <!-- 顶部操作 -->
<div class="flex items-center justify-between pb-2 border-b border-divider"> <div class="flex items-center justify-between pb-2 border-b border-divider">
<div class="flex items-center space-x-2"> <div class="flex items-center space-x-2">
<n-tag type="info" size="small">{{ node.tagName }}</n-tag> <CommonTag type="info" size="small">{{ node.tagName }}</CommonTag>
<span class="text-xs text-color3"> <span class="text-xs text-color3">
{{ isOrdered ? '有序' : '无序' }}列表编辑器 (子项共: {{ listItems.length }} 个) {{ isOrdered ? '有序' : '无序' }}列表编辑器 (子项共: {{ listItems.length }} 个)
</span> </span>
......
import type { FormInst } from 'naive-ui' import type { FormInst } from 'naive-ui'
import { getElementAttributes, createDefaultAttributes, isTextOnlyElement, isMixedContentElement } from '@/utils/dtdManager' import { getElementAttributes, createDefaultAttributes, isTextOnlyElement, isMixedContentElement } from '@/utils/dtdManager'
import { nextTick } from 'vue'
import { useEditorStore } from '@/store/editor' import { useEditorStore } from '@/store/editor'
import { useAppStore } from '@/store/app' import { useAppStore } from '@/store/app'
import type { XmlNode, DtdAttribute } from '@/types/xmlNode' import type { XmlNode, DtdAttribute } from '@/types/xmlNode'
......
...@@ -41,10 +41,19 @@ ...@@ -41,10 +41,19 @@
<script setup lang="ts"> <script setup lang="ts">
import type { FormInst } from 'naive-ui' import type { FormInst } from 'naive-ui'
import { addNodeVisible, addNodeMode } from '../../functionals' import { addNodeVisible, addNodeMode, addNodeTargetId, addNodeAllowedTags } from '../../functionals'
import { useAddNodeModal } from './functionals' import { useAddNodeModal } from './functionals'
const formRef = ref<FormInst | null>(null) const formRef = ref<FormInst | null>(null)
const { form, rules, saving, modalTitle, tagOptions, attributeDefs, showTextContentField, onTagChange, handleConfirm } = useAddNodeModal(formRef) const { form, rules, saving, modalTitle, tagOptions, attributeDefs, showTextContentField, onTagChange, handleConfirm } = useAddNodeModal(formRef)
const open = (mode: 'child' | 'before' | 'after' | 'edit', targetId: string, allowedTags: string[]) => {
addNodeMode.value = mode
addNodeTargetId.value = targetId
addNodeAllowedTags.value = allowedTags
addNodeVisible.value = true
}
defineExpose({ open })
</script> </script>
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
confirm-text="确认删除选中节点" confirm-text="确认删除选中节点"
@confirm="handleConfirm" @confirm="handleConfirm"
> >
<div class="flex flex-col gap-4 py-1 text-xs max-h-[500px] overflow-y-auto pr-1"> <div class="flex flex-col gap-4 py-1 text-xs pr-1">
<span class="text-color2 text-sm"> <span class="text-color2 text-sm">
系统检测到您选中的节点中,部分节点由于 DTD 规则要求无法删除。您可以选择勾选并删除其余合法节点: 系统检测到您选中的节点中,部分节点由于 DTD 规则要求无法删除。您可以选择勾选并删除其余合法节点:
</span> </span>
......
...@@ -19,4 +19,17 @@ import { checkRuleVisible, checkRuleData } from '../../functionals' ...@@ -19,4 +19,17 @@ import { checkRuleVisible, checkRuleData } from '../../functionals'
import { useCheckRuleModal } from './functionals' import { useCheckRuleModal } from './functionals'
const { formattedRule } = useCheckRuleModal() const { formattedRule } = useCheckRuleModal()
const open = (nodeName: string, rawModel: string, humanReadable: string, parsed: any) => {
checkRuleData.value = {
nodeName,
rawModel,
humanReadable,
parsed
}
checkRuleVisible.value = true
}
defineExpose({ open })
</script> </script>
...@@ -8,9 +8,9 @@ ...@@ -8,9 +8,9 @@
> >
<!-- 磨砂玻璃质感的顶部装饰条 --> <!-- 磨砂玻璃质感的顶部装饰条 -->
<div class="h-8 bg-fill-3 border-b border-divider flex items-center px-4 space-x-1.5 select-none shrink-0"> <div class="h-8 bg-fill-3 border-b border-divider flex items-center px-4 space-x-1.5 select-none shrink-0">
<div class="w-3 h-3 rounded-full bg-red-500/80"></div> <div class="w-3 h-3 rounded-full bg-danger/80"></div>
<div class="w-3 h-3 rounded-full bg-yellow-500/80"></div> <div class="w-3 h-3 rounded-full bg-warning/80"></div>
<div class="w-3 h-3 rounded-full bg-green-500/80"></div> <div class="w-3 h-3 rounded-full bg-success/80"></div>
</div> </div>
<div class="p-6 font-mono text-sm leading-relaxed overflow-x-auto max-h-[500px] scrollbar-thin select-all"> <div class="p-6 font-mono text-sm leading-relaxed overflow-x-auto max-h-[500px] scrollbar-thin select-all">
...@@ -42,6 +42,14 @@ const handleCopyXml = async () => { ...@@ -42,6 +42,14 @@ const handleCopyXml = async () => {
window.$message?.error('复制失败,请手动选择复制') window.$message?.error('复制失败,请手动选择复制')
} }
} }
const open = (title: string, content: string) => {
viewXmlTitle.value = title
viewXmlContent.value = content
viewXmlVisible.value = true
}
defineExpose({ open })
</script> </script>
<style scoped> <style scoped>
......
...@@ -28,12 +28,15 @@ import { STRUCTURAL_TAGS, WARNING_LIKE_TAGS, NOTE_AND_REF_TAGS, COLORED_TAGS } f ...@@ -28,12 +28,15 @@ import { STRUCTURAL_TAGS, WARNING_LIKE_TAGS, NOTE_AND_REF_TAGS, COLORED_TAGS } f
// ══════════════════════════════════════════════════════════ // ══════════════════════════════════════════════════════════
// 全局共享状态:查看规则弹窗 // 全局共享状态:查看规则弹窗
// ══════════════════════════════════════════════════════════ // ══════════════════════════════════════════════════════════
// 全局共享状态:查看规则弹窗
// ══════════════════════════════════════════════════════════
export const checkRuleVisible = ref(false) export const checkRuleVisible = ref(false)
export const checkRuleData = ref<CheckRuleData>({ export const checkRuleData = ref<CheckRuleData>({
nodeName: '', nodeName: '',
rawModel: '', rawModel: '',
humanReadable: '' humanReadable: ''
}) })
export const checkRuleModalRef = ref<any>(null)
// ══════════════════════════════════════════════════════════ // ══════════════════════════════════════════════════════════
// 全局共享状态:查看XML片段弹窗 // 全局共享状态:查看XML片段弹窗
...@@ -41,6 +44,7 @@ export const checkRuleData = ref<CheckRuleData>({ ...@@ -41,6 +44,7 @@ export const checkRuleData = ref<CheckRuleData>({
export const viewXmlVisible = ref(false) export const viewXmlVisible = ref(false)
export const viewXmlTitle = ref('') export const viewXmlTitle = ref('')
export const viewXmlContent = ref('') export const viewXmlContent = ref('')
export const viewXmlModalRef = ref<any>(null)
// ══════════════════════════════════════════════════════════ // ══════════════════════════════════════════════════════════
// 全局共享状态:添加子节点 / 插入兄弟节点弹窗 // 全局共享状态:添加子节点 / 插入兄弟节点弹窗
...@@ -49,6 +53,7 @@ export const addNodeVisible = ref(false) ...@@ -49,6 +53,7 @@ export const addNodeVisible = ref(false)
export const addNodeMode = ref<InsertMode>('child') export const addNodeMode = ref<InsertMode>('child')
export const addNodeTargetId = ref<string>('') export const addNodeTargetId = ref<string>('')
export const addNodeAllowedTags = ref<string[]>([]) export const addNodeAllowedTags = ref<string[]>([])
export const addNodeModalRef = ref<any>(null)
// 复制节点缓存 // 复制节点缓存
export const copyNodeCache = ref<XmlNode | null>(null) export const copyNodeCache = ref<XmlNode | null>(null)
...@@ -881,37 +886,27 @@ export function useNodeTree( ...@@ -881,37 +886,27 @@ export function useNodeTree(
switch (key) { switch (key) {
// ── 查看XML ── // ── 查看XML ──
case 'viewXml': { case 'viewXml': {
if (isVirtual) { const title = isVirtual ? `查看文本节点的 XML` : `查看节点 [${node.tagName}] 的 XML 片段`
viewXmlTitle.value = `查看文本节点的 XML` const content = isVirtual ? node.textContent : serializeTreeToXml(node)
viewXmlContent.value = node.textContent viewXmlModalRef.value?.open(title, content)
} else {
const xmlFragment = serializeTreeToXml(node)
viewXmlTitle.value = `查看节点 [${node.tagName}] 的 XML 片段`
viewXmlContent.value = xmlFragment
}
viewXmlVisible.value = true
break break
} }
// ── 查看规则 ── // ── 查看规则 ──
case 'checkRule': { case 'checkRule': {
const rule = getElementRule(node.tagName) const rule = getElementRule(node.tagName)
checkRuleData.value = { checkRuleModalRef.value?.open(
nodeName: node.tagName, node.tagName,
rawModel: rule?.contentModel.raw || '(#PCDATA)', rule?.contentModel.raw || '(#PCDATA)',
humanReadable: rule?.contentModel.humanReadable || '', rule?.contentModel.humanReadable || '',
parsed: rule?.contentModel.parsed || null rule?.contentModel.parsed || null
} )
checkRuleVisible.value = true
break break
} }
// ── 编辑节点:打开属性编辑弹窗 ── // ── 编辑节点:打开属性编辑弹窗 ──
case 'editNode': { case 'editNode': {
addNodeTargetId.value = nodeId addNodeModalRef.value?.open('edit', nodeId, [node.tagName])
addNodeMode.value = 'edit'
addNodeAllowedTags.value = [node.tagName]
addNodeVisible.value = true
break break
} }
...@@ -1169,10 +1164,7 @@ export function useNodeTree( ...@@ -1169,10 +1164,7 @@ export function useNodeTree(
} }
} }
allowed = sortChildrenByDtd(node.tagName, allowed) allowed = sortChildrenByDtd(node.tagName, allowed)
addNodeTargetId.value = nodeId addNodeModalRef.value?.open('child', nodeId, allowed)
addNodeMode.value = 'child'
addNodeAllowedTags.value = allowed
addNodeVisible.value = true
break break
} }
...@@ -1189,10 +1181,7 @@ export function useNodeTree( ...@@ -1189,10 +1181,7 @@ export function useNodeTree(
} }
} }
insertable = sortChildrenByDtd(parent.tagName, insertable) insertable = sortChildrenByDtd(parent.tagName, insertable)
addNodeTargetId.value = nodeId addNodeModalRef.value?.open('before', nodeId, insertable)
addNodeMode.value = 'before'
addNodeAllowedTags.value = insertable
addNodeVisible.value = true
break break
} }
...@@ -1209,10 +1198,7 @@ export function useNodeTree( ...@@ -1209,10 +1198,7 @@ export function useNodeTree(
} }
} }
insertable = sortChildrenByDtd(parent.tagName, insertable) insertable = sortChildrenByDtd(parent.tagName, insertable)
addNodeTargetId.value = nodeId addNodeModalRef.value?.open('after', nodeId, insertable)
addNodeMode.value = 'after'
addNodeAllowedTags.value = insertable
addNodeVisible.value = true
break break
} }
......
...@@ -180,13 +180,13 @@ ...@@ -180,13 +180,13 @@
/> />
<!-- 查看规则弹窗 --> <!-- 查看规则弹窗 -->
<CheckRuleModal /> <CheckRuleModal :ref="(el) => checkRuleModalRef = el" />
<!-- 查看XML片段弹窗 --> <!-- 查看XML片段弹窗 -->
<ViewXmlModal /> <ViewXmlModal :ref="(el) => viewXmlModalRef = el" />
<!-- 添加/插入节点弹窗 --> <!-- 添加/插入节点弹窗 -->
<AddNodeModal /> <AddNodeModal :ref="(el) => addNodeModalRef = el" />
<!-- 插入 XML 片段弹窗 --> <!-- 插入 XML 片段弹窗 -->
<InsertFragmentModal ref="insertFragmentModalRef" /> <InsertFragmentModal ref="insertFragmentModalRef" />
...@@ -199,7 +199,7 @@ ...@@ -199,7 +199,7 @@
<script setup lang="ts"> <script setup lang="ts">
import { SearchOutline, ListOutline, TrashOutline, CloseOutline, SyncOutline } from '@vicons/ionicons5' import { SearchOutline, ListOutline, TrashOutline, CloseOutline, SyncOutline } from '@vicons/ionicons5'
import { useEditorStore } from '@/store/editor' import { useEditorStore } from '@/store/editor'
import { useNodeTree, checkRuleVisible, viewXmlVisible, addNodeVisible, translatingNodeId } from './functionals' import { useNodeTree, checkRuleVisible, viewXmlVisible, addNodeVisible, translatingNodeId, checkRuleModalRef, viewXmlModalRef, addNodeModalRef } from './functionals'
import CheckRuleModal from './components/CheckRuleModal/index.vue' import CheckRuleModal from './components/CheckRuleModal/index.vue'
import AddNodeModal from './components/AddNodeModal/index.vue' import AddNodeModal from './components/AddNodeModal/index.vue'
import ViewXmlModal from './components/ViewXmlModal/index.vue' import ViewXmlModal from './components/ViewXmlModal/index.vue'
......
...@@ -3,7 +3,7 @@ import { useAppStore } from '@/store/app' ...@@ -3,7 +3,7 @@ import { useAppStore } from '@/store/app'
import type { XmlNode } from '@/types/xmlNode' import type { XmlNode } from '@/types/xmlNode'
import type { TableCellModel, TableRowModel, TableStructureModel, BatchModalRef, BatchActionMeta, CellParagraphModel } from '../constants' import type { TableCellModel, TableRowModel, TableStructureModel, BatchModalRef, BatchActionMeta, CellParagraphModel } from '../constants'
import { ACTION_META } from '../constants' import { ACTION_META } from '../constants'
import { COMPLEX_ENTRY_TAGS, PARA_TAGS } from '@/configs/xmlTags' import { COMPLEX_ENTRY_TAGS, PARA_TAGS, CHINESE_FIRST_PARA_TAGS } from '@/configs/xmlTags'
const getDeepText = (node: XmlNode): string => { const getDeepText = (node: XmlNode): string => {
if (node.mixedContent && node.mixedContent.length > 0) { if (node.mixedContent && node.mixedContent.length > 0) {
...@@ -304,7 +304,7 @@ export function useTableEditor(props: { node: XmlNode }) { ...@@ -304,7 +304,7 @@ export function useTableEditor(props: { node: XmlNode }) {
} }
if (cellChildTags && cellChildTags.length > 0) { if (cellChildTags && cellChildTags.length > 0) {
// 按照 PARAC -> PARA 的顺序插入,以确保 PARAC 始终在 PARA 节点的前面 // 按照 PARAC -> PARA 的顺序插入,以确保 PARAC 始终在 PARA 节点的前面
const order = ['PARAC', 'PARA'] const order = CHINESE_FIRST_PARA_TAGS
for (const tag of order) { for (const tag of order) {
if (cellChildTags.includes(tag)) { if (cellChildTags.includes(tag)) {
const childId = crypto.randomUUID() const childId = crypto.randomUUID()
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
<div class="flex-1 flex flex-col p-4 space-y-4 overflow-auto bg-transparent min-h-0" @click.stop @click="closeContextMenu"> <div class="flex-1 flex flex-col p-4 space-y-4 overflow-auto bg-transparent min-h-0" @click.stop @click="closeContextMenu">
<!-- 表格工具栏 --> <!-- 表格工具栏 -->
<div class="flex items-center pb-2 border-b border-divider space-x-2"> <div class="flex items-center pb-2 border-b border-divider space-x-2">
<n-tag type="info" size="small">{{ node.tagName }}</n-tag> <CommonTag type="info" size="small">{{ node.tagName }}</CommonTag>
<span class="text-xs text-color3">{{ CELL_EDIT_TIP }}</span> <span class="text-xs text-color3">{{ CELL_EDIT_TIP }}</span>
<span class="text-xs text-color3 select-none">· 右键单元格可快速操作</span> <span class="text-xs text-color3 select-none">· 右键单元格可快速操作</span>
</div> </div>
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
<!-- 头部节点提示 --> <!-- 头部节点提示 -->
<div class="flex items-center justify-between pb-2 border-b border-divider"> <div class="flex items-center justify-between pb-2 border-b border-divider">
<div class="flex items-center space-x-2"> <div class="flex items-center space-x-2">
<n-tag type="info" size="small">{{ node.tagName }}</n-tag> <CommonTag type="info" size="small">{{ node.tagName }}</CommonTag>
<span class="text-xs text-color3">{{ dtdDescription }}</span> <span class="text-xs text-color3">{{ dtdDescription }}</span>
</div> </div>
<div v-if="isMixed" class="text-xs text-color3">混合内容节点(支持嵌入行内元素)</div> <div v-if="isMixed" class="text-xs text-color3">混合内容节点(支持嵌入行内元素)</div>
...@@ -48,7 +48,7 @@ ...@@ -48,7 +48,7 @@
<!-- 1. 文本片段 --> <!-- 1. 文本片段 -->
<div v-if="item.type === 'text'" class="flex-1 flex items-center space-x-2"> <div v-if="item.type === 'text'" class="flex-1 flex items-center space-x-2">
<n-tag size="small" type="success" class="flex-shrink-0">文本</n-tag> <CommonTag size="small" type="success" class="flex-shrink-0">文本</CommonTag>
<div <div
contenteditable="true" contenteditable="true"
class="flex-1 min-h-[32px] px-2 py-1.5 rounded border border-divider focus:outline-none focus:ring-1 focus:ring-primary text-sm bg-fill-3 text-color2" class="flex-1 min-h-[32px] px-2 py-1.5 rounded border border-divider focus:outline-none focus:ring-1 focus:ring-primary text-sm bg-fill-3 text-color2"
...@@ -61,9 +61,9 @@ ...@@ -61,9 +61,9 @@
<div v-else-if="item.type === 'element'" class="flex-1 flex flex-col space-y-2"> <div v-else-if="item.type === 'element'" class="flex-1 flex flex-col space-y-2">
<div class="flex items-center justify-between"> <div class="flex items-center justify-between">
<div class="flex items-center space-x-2"> <div class="flex items-center space-x-2">
<n-tag size="small" type="warning" class="font-bold"> <CommonTag size="small" type="warning" class="font-bold">
{{ item.elementTagName }} {{ item.elementTagName }}
</n-tag> </CommonTag>
<span class="text-xs text-color3">行内嵌入元素</span> <span class="text-xs text-color3">行内嵌入元素</span>
</div> </div>
<div class="text-xs italic text-color3 max-w-md truncate"> <div class="text-xs italic text-color3 max-w-md truncate">
......
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