Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
V
vue3_onlineEditor
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
pangchong
vue3_onlineEditor
Commits
b909fba1
Commit
b909fba1
authored
Apr 01, 2025
by
qlintonger xeno
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat: 新增双向对比基本算法逻辑
parent
09a08709
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
188 additions
and
66 deletions
+188
-66
src/assets/file/CES-QEC-V250-A.xml
+4
-0
src/assets/file/Trans-Convert.xml
+20
-16
src/lib/XMLProcessor/src/core/Processing.ts
+143
-49
src/lib/XMLProcessor/src/index.ts
+2
-1
src/lib/XMLProcessor/src/typing/index.d.ts
+19
-0
No files found.
src/assets/file/CES-QEC-V250-A.xml
View file @
b909fba1
...
...
@@ -69,6 +69,10 @@
<PARA>
Ref. EM TASK 71-00-02-000-026-B00 (A5-PPBU) - Remove The EBU Fan Case Brackets, Removal-026.
</PARA>
</L2ITEM>
<L2ITEM>
<PARAC>
拆卸EBU风扇机匣支架,按EM TASK 71-00-02-000-026-B00--EDC。
</PARAC>
<PARA>
Ref. EM TASK 71-00-02-000-026-B00 (A5-PPBU) - Remove The EBU Fan Case Brackets, Removal-026--EDC.
</PARA>
</L2ITEM>
<L2ITEM>
<PARAC>
拆卸低压中压机匣支架,按EM TASK 71-00-02-000-027-B00。
</PARAC>
<PARA>
Ref. EM TASK 71-00-02-000-027-B00 (A5-PPBU) - Remove The LP Compressor/Intermediate Case Brackets, Removal-027.
</PARA>
</L2ITEM>
...
...
src/assets/file/Trans-Convert.xml
View file @
b909fba1
...
...
@@ -9,17 +9,17 @@
<CEP>
<EFFECT
EFFRG=
"001999"
></EFFECT>
<TITLEC>
发动机QEC拆卸(V2500-A5系列)
</TITLEC>
<TITLE>
Remove the Engine's QEC(V2500-A5 series)
</TITLE>
<TITLE>
Remove the Engine's QEC(V2500-A5 series)
123
</TITLE>
<TOPIC
CK-LEVEL=
"C"
>
<TITLEC>
飞机/发动机基本信息
123
</TITLEC>
<TITLEC>
飞机/发动机基本信息
</TITLEC>
<TITLE>
AIRCRAFT/ENGINE INFORMATION
</TITLE>
<STEP
CK-LEVEL=
"C"
>
<EFFECT
EFFRG=
"001999"
></EFFECT>
<RECORD-LINE
>
<PARAC>
发动机序号
</PARAC
>
<PARA>
Engine SN
</PARA
>
<RECORD></RECORD
>
</RECORD-LINE
>
<!-- <RECORD-LINE>--
>
<!-- <PARAC>发动机序号</PARAC>--
>
<!-- <PARA>Engine SN</PARA>--
>
<!-- <RECORD></RECORD>--
>
<!-- </RECORD-LINE>--
>
<NOTE>
<PARAC>
开始工作前请记录。
</PARAC>
<PARA>
Please record before starting work.
</PARA>
...
...
@@ -49,7 +49,7 @@
</STEP>
<STEP
CK-LEVEL=
"C"
>
<EFFECT
EFFRG=
"001999"
></EFFECT>
<PARAC>
按照EB-2020-V250-70-201最新版,完成发动机的出库检查
---修改1
。
</PARAC>
<PARAC>
按照EB-2020-V250-70-201最新版,完成发动机的出库检查。
</PARAC>
<PARA>
Finish the engine outgoing check ref thelatest version of EB-2020-V250-70-201.
</PARA>
<SIGNOFF/>
</STEP>
...
...
@@ -69,6 +69,10 @@
<PARA>
Ref. EM TASK 71-00-02-000-026-B00 (A5-PPBU) - Remove The EBU Fan Case Brackets, Removal-026.
</PARA>
</L2ITEM>
<L2ITEM>
<PARAC>
拆卸EBU风扇机匣支架,按EM TASK 71-00-02-000-026-B00--EDC。
</PARAC>
<PARA>
Ref. EM TASK 71-00-02-000-026-B00 (A5-PPBU) - Remove The EBU Fan Case Brackets, Removal-026--EDC.
</PARA>
</L2ITEM>
<L2ITEM>
<PARAC>
拆卸低压中压机匣支架,按EM TASK 71-00-02-000-027-B00。
</PARAC>
<PARA>
Ref. EM TASK 71-00-02-000-027-B00 (A5-PPBU) - Remove The LP Compressor/Intermediate Case Brackets, Removal-027.
</PARA>
</L2ITEM>
...
...
@@ -286,10 +290,10 @@
<PARAC>
发动机QEC零件故检,清洗,集件和导线修理
</PARAC>
<PARA>
Remove the Engine's QEC
</PARA>
<LIST1>
<!-- <L1ITEM>--
>
<!-- <PARAC>使用清洗剂清洗拆下QEC件</PARAC>--
>
<!-- <PARA>Clean all QEC parts with cleanser.</PARA>--
>
<!-- </L1ITEM>--
>
<L1ITEM
>
<PARAC>
使用清洗剂清洗拆下QEC件
</PARAC
>
<PARA>
Clean all QEC parts with cleanser.
</PARA
>
</L1ITEM
>
<L1ITEM>
<PARAC>
检查右侧空气系统管路,对开口处堵上堵盖。参考EM 71-00-02。
</PARAC>
<PARA>
Inspect the air system tubes which installed on the engine
’
s right side, Ref EM manual 71-00-02.
</PARA>
...
...
@@ -314,10 +318,10 @@
<PARAC>
目视检查IDG。对开口处堵上堵盖。
</PARAC>
<PARA>
Visual inspect IDG.
</PARA>
</L1ITEM>
<!-- <L1ITEM>--
>
<!-- <PARAC>目视检查液压泵。</PARAC>--
>
<!-- <PARA>Visual inspect hydraulic pump.</PARA>--
>
<!-- </L1ITEM>--
>
<L1ITEM
>
<PARAC>
目视检查液压泵。
</PARAC
>
<PARA>
Visual inspect hydraulic pump.
</PARA
>
</L1ITEM
>
<L1ITEM>
<PARAC>
目视检查高压活门。对开口处堵上堵盖。
</PARAC>
<PARA>
Visual inspect high pressure bleed valve.
</PARA>
...
...
src/lib/XMLProcessor/src/core/Processing.ts
View file @
b909fba1
// 引入 TreeRenderResult 类型,该类型定义在 @/lib/XMLProcessor/src/typing 模块中
import
{
TreeRenderResult
}
from
'@/lib/XMLProcessor/src/typing'
;
import
{
NewTreeModification
,
OldTreeModification
,
TreeRenderResult
,
TreeRenderResultFlatted
}
from
'@/lib/XMLProcessor/src/typing'
// 引入 UUID 类用于生成唯一标识符
import
{
UUID
}
from
'uuidjs'
;
import
{
UUID
}
from
'uuidjs'
import
{
md5
}
from
'js-md5'
// 定义 Processing 类,用于处理 XML 数据
export
class
Processing
{
// 私有属性,用于解析 XML 字符串为 DOM 对象
private
domParser
:
DOMParser
;
private
domParser
:
DOMParser
private
xmlSerializer
:
XMLSerializer
// 构造函数,初始化 DOMParser 实例
constructor
()
{
this
.
domParser
=
new
DOMParser
()
;
this
.
xmlSerializer
=
new
XMLSerializer
()
;
this
.
domParser
=
new
DOMParser
()
this
.
xmlSerializer
=
new
XMLSerializer
()
}
serializeXML
(
xmlDOM
:
Document
):
string
{
return
this
.
xmlSerializer
.
serializeToString
(
xmlDOM
)
;
return
this
.
xmlSerializer
.
serializeToString
(
xmlDOM
)
}
dualCompareFromString
(
xmlStringA
:
string
,
xmlStringB
:
string
,
bothHandledNode
:
string
[])
{
const
treeA
=
this
.
domParser
.
parseFromString
(
xmlStringA
,
'text/xml'
);
const
treeB
=
this
.
domParser
.
parseFromString
(
xmlStringB
,
'text/xml'
);
const
resultA
=
this
.
innerHandle
(
treeA
.
documentElement
,
bothHandledNode
);
private
flattenTree
(
renderResult
:
TreeRenderResult
[]):
TreeRenderResultFlatted
[]
{
const
resp
:
TreeRenderResultFlatted
[]
=
[]
for
(
const
item
of
renderResult
)
{
resp
.
push
({
key
:
item
.
key
,
label
:
item
.
label
,
hash
:
item
.
hash
,
index
:
item
.
index
,
chained
:
item
.
chained
})
if
(
item
.
children
)
{
resp
.
push
(...
this
.
flattenTree
(
item
.
children
))
}
}
return
resp
}
dualCompareFromString
(
xmlStringOld
:
string
,
xmlStringNew
:
string
,
bothHandledNode
:
string
[]
):
{
dataForNew
:
NewTreeModification
dataForOld
:
OldTreeModification
domOld
:
Document
domNew
:
Document
treeOld
:
TreeRenderResult
[]
treeNew
:
TreeRenderResult
[]
}
{
const
treeA
=
this
.
domParser
.
parseFromString
(
xmlStringOld
,
'text/xml'
)
const
treeB
=
this
.
domParser
.
parseFromString
(
xmlStringNew
,
'text/xml'
)
const
resultA
=
this
.
innerHandle
(
treeA
.
documentElement
,
bothHandledNode
)
const
resultB
=
this
.
innerHandle
(
treeB
.
documentElement
,
bothHandledNode
)
treeA
.
documentElement
.
querySelectorAll
(
':not([data-key])'
).
forEach
((
node
)
=>
node
.
remove
())
treeB
.
documentElement
.
querySelectorAll
(
':not([data-key])'
).
forEach
((
node
)
=>
node
.
remove
())
console
.
log
(
'both -res'
,
{
resultA
,
resultB
})
// 扁平化所有节点
const
resultAFlatted
=
this
.
flattenTree
(
resultA
)
const
resultBFlatted
=
this
.
flattenTree
(
resultB
)
const
dataForOld
:
OldTreeModification
=
{
Changed
:
[],
Deleted
:
[]
}
const
dataForNew
:
NewTreeModification
=
{
Changed
:
[],
Added
:
[]
}
// 获取老节点中hash不存在的节点
let
nonExistedHashNodeForOld
:
TreeRenderResultFlatted
[]
=
resultAFlatted
.
filter
((
item
)
=>
{
return
!
resultBFlatted
.
find
((
itemB
)
=>
itemB
.
hash
===
item
.
hash
&&
itemB
.
chained
.
join
(
'$'
)
===
item
.
chained
.
join
(
'$'
))
})
let
nonExistedHashNodeForNew
:
TreeRenderResultFlatted
[]
=
resultBFlatted
.
filter
((
item
)
=>
{
return
!
resultAFlatted
.
find
((
itemA
)
=>
itemA
.
hash
===
item
.
hash
&&
itemA
.
chained
.
join
(
'$'
)
===
item
.
chained
.
join
(
'$'
))
})
const
hashDiffInOld
:
TreeRenderResultFlatted
[]
=
nonExistedHashNodeForOld
.
filter
(
(
a
)
=>
!
nonExistedHashNodeForNew
.
find
((
v
)
=>
v
.
hash
===
a
.
hash
)
)
const
hashDiffInNew
:
TreeRenderResultFlatted
[]
=
nonExistedHashNodeForNew
.
filter
(
(
a
)
=>
!
nonExistedHashNodeForOld
.
find
((
v
)
=>
v
.
hash
===
a
.
hash
)
)
let
nodeUpdatedForOld
:
TreeRenderResultFlatted
[]
=
[]
let
nodeUpdatedForNew
:
TreeRenderResultFlatted
[]
=
[]
for
(
const
item
of
hashDiffInOld
)
{
const
sameIndexFound
=
hashDiffInNew
.
find
((
a
)
=>
a
.
chained
.
join
(
'$'
)
===
item
.
chained
.
join
(
'$'
))
if
(
sameIndexFound
)
{
nodeUpdatedForOld
.
push
(
item
)
nodeUpdatedForNew
.
push
(
sameIndexFound
)
}
}
let
newNodeInserted
:
TreeRenderResultFlatted
[]
=
[]
for
(
const
item
of
hashDiffInNew
)
{
if
(
!
nodeUpdatedForOld
.
find
(
a
=>
a
.
hash
===
item
.
hash
)
&&
!
nodeUpdatedForNew
.
find
(
a
=>
a
.
hash
===
item
.
hash
))
{
newNodeInserted
.
push
(
item
)
}
}
let
oldNodeDeleted
:
TreeRenderResultFlatted
[]
=
[]
for
(
const
item
of
hashDiffInOld
)
{
if
(
!
nodeUpdatedForNew
.
find
(
a
=>
a
.
hash
===
item
.
hash
)
&&
!
nodeUpdatedForOld
.
find
(
a
=>
a
.
hash
===
item
.
hash
))
{
oldNodeDeleted
.
push
(
item
)
}
}
dataForOld
.
Changed
=
nodeUpdatedForOld
dataForOld
.
Deleted
=
oldNodeDeleted
dataForNew
.
Changed
=
nodeUpdatedForNew
dataForNew
.
Added
=
newNodeInserted
return
{
dataForNew
,
dataForOld
,
domOld
:
treeA
,
domNew
:
treeB
,
treeOld
:
resultA
,
treeNew
:
resultB
}
}
// 处理 XML 字符串的方法,返回树形数据和 XML DOM 对象
processXML
(
xmlContent
:
string
,
handledNode
:
string
[]):
{
treeData
:
TreeRenderResult
[];
xmlDOM
:
Document
;
processXML
(
xmlContent
:
string
,
handledNode
:
string
[]
):
{
treeData
:
TreeRenderResult
[]
xmlDOM
:
Document
xmlContent
:
string
}
{
// 使用 DOMParser 解析 XML 字符串
const
parsedTree
=
this
.
domParser
.
parseFromString
(
xmlContent
,
'text/xml'
)
;
const
parsedTree
=
this
.
domParser
.
parseFromString
(
xmlContent
,
'text/xml'
)
// 获取 XML 文档的根元素
const
rootElement
=
parsedTree
.
documentElement
;
const
rootElement
=
parsedTree
.
documentElement
const
result
=
{
// 调用 innerHandle 方法处理根元素,生成树形数据
treeData
:
this
.
innerHandle
(
rootElement
,
handledNode
),
...
...
@@ -54,41 +142,48 @@ export class Processing {
}
// 异步处理 XML 文件的方法,返回包含树形数据和 XML DOM 对象的 Promise
async
processFile
(
xmlFile
:
File
,
handledNode
:
string
[]):
Promise
<
{
treeData
:
TreeRenderResult
[];
xmlDOM
:
Document
;
xmlContent
:
string
}
>
{
async
processFile
(
xmlFile
:
File
,
handledNode
:
string
[]
):
Promise
<
{
treeData
:
TreeRenderResult
[]
xmlDOM
:
Document
xmlContent
:
string
}
>
{
// 检查文件是否为有效的 XML 文件
if
(
!
(
xmlFile
instanceof
File
)
||
!
xmlFile
.
type
.
includes
(
'xml'
))
{
return
Promise
.
reject
(
'The file is not a valid XML file.'
)
;
return
Promise
.
reject
(
'The file is not a valid XML file.'
)
}
return
new
Promise
((
resolve
,
reject
)
=>
{
const
fr
=
new
FileReader
()
;
const
fr
=
new
FileReader
()
// 当文件读取完成时触发的事件处理函数
fr
.
onload
=
()
=>
{
const
content
=
fr
.
result
as
string
;
const
content
=
fr
.
result
as
string
try
{
// 调用 processXML 方法处理读取的文件内容
const
{
treeData
,
xmlDOM
,
xmlContent
}
=
this
.
processXML
(
content
,
handledNode
)
;
const
{
treeData
,
xmlDOM
,
xmlContent
}
=
this
.
processXML
(
content
,
handledNode
)
// 解析成功,返回树形数据和 XML DOM 对象
resolve
({
treeData
,
xmlDOM
,
xmlContent
})
;
resolve
({
treeData
,
xmlDOM
,
xmlContent
})
}
catch
(
error
)
{
// 解析失败,拒绝 Promise 并返回错误信息
reject
(
error
)
;
reject
(
error
)
}
}
;
}
// 当文件读取出错时触发的事件处理函数
fr
.
onerror
=
()
=>
{
reject
(
'Error reading file.'
)
;
}
;
reject
(
'Error reading file.'
)
}
// 以文本形式读取文件
fr
.
readAsText
(
xmlFile
)
;
})
;
fr
.
readAsText
(
xmlFile
)
})
}
// 私有方法,用于递归处理单个 DOM 节点,生成树形数据
private
innerHandle
(
domNode
:
Element
,
handledNode
:
string
[]):
TreeRenderResult
[]
{
let
treeData
:
TreeRenderResult
[]
=
[]
;
let
treeData
:
TreeRenderResult
[]
=
[]
// 生成唯一的 key
let
targetKey
=
domNode
.
getAttribute
(
'data-key'
)
;
let
targetKey
=
domNode
.
getAttribute
(
'data-key'
)
if
(
!
targetKey
)
{
targetKey
=
'g-'
+
UUID
.
generate
()
}
...
...
@@ -100,37 +195,37 @@ export class Processing {
index
:
0
,
chained
:
[
0
],
hash
:
md5
.
hex
(
domNode
.
textContent
!
||
''
)
}
;
}
// 为 DOM 节点设置 data-key 属性
domNode
.
setAttribute
(
'data-key'
,
targetKey
)
;
domNode
.
setAttribute
(
'data-key'
,
targetKey
)
domNode
.
setAttribute
(
'data-w-e-type'
,
domNode
.
nodeName
)
domNode
.
setAttribute
(
'data-indent-level'
,
'0'
)
// 递归处理子节点
treeItem
.
children
=
this
.
innerGroupHandle
(
domNode
.
children
,
handledNode
,
[
0
])
;
treeItem
.
children
=
this
.
innerGroupHandle
(
domNode
.
children
,
handledNode
,
[
0
])
// 将树形数据项添加到结果数组中
treeData
.
push
(
treeItem
)
;
treeData
.
push
(
treeItem
)
return
treeData
;
return
treeData
}
// 私有方法,用于递归处理一组 DOM 节点,生成树形数据
private
innerGroupHandle
(
nodeSet
:
HTMLCollection
,
handledNode
:
string
[],
startChained
:
number
[]):
TreeRenderResult
[]
{
let
targetResult
:
TreeRenderResult
[]
=
[]
;
let
realIndex
=
-
1
;
let
targetResult
:
TreeRenderResult
[]
=
[]
let
realIndex
=
-
1
// 遍历节点集合
for
(
let
i
=
0
;
i
<
nodeSet
.
length
;
i
++
)
{
const
node
=
nodeSet
[
i
]
as
Element
;
const
node
=
nodeSet
[
i
]
as
Element
// 检查节点是否在处理列表中
if
(
!
handledNode
.
includes
(
node
.
nodeName
))
{
// 如果节点有子节点,递归处理子节点
if
(
node
.
children
.
length
)
{
targetResult
.
push
(...
this
.
innerGroupHandle
(
node
.
children
,
handledNode
,
startChained
))
;
targetResult
.
push
(...
this
.
innerGroupHandle
(
node
.
children
,
handledNode
,
startChained
))
}
continue
;
continue
}
realIndex
++
;
realIndex
++
// 生成唯一的 key
let
targetKey
=
node
.
getAttribute
(
'data-key'
)
;
let
targetKey
=
node
.
getAttribute
(
'data-key'
)
if
(
!
targetKey
)
{
targetKey
=
'g-'
+
UUID
.
generate
()
}
...
...
@@ -141,18 +236,18 @@ export class Processing {
index
:
realIndex
,
chained
:
[...
startChained
,
realIndex
],
hash
:
md5
.
hex
(
node
.
textContent
!
||
''
)
}
;
}
// 为 DOM 节点设置 data-key 属性
node
.
setAttribute
(
'data-key'
,
targetKey
)
;
node
.
setAttribute
(
'data-key'
,
targetKey
)
node
.
setAttribute
(
'data-w-e-type'
,
node
.
nodeName
)
node
.
setAttribute
(
'data-indent-level'
,
startChained
.
length
.
toString
())
// 如果节点有子节点,递归处理子节点
if
(
node
.
children
.
length
>
0
)
{
treeItem
.
children
=
this
.
innerGroupHandle
(
node
.
children
,
handledNode
,
[...
startChained
,
realIndex
])
;
treeItem
.
children
=
this
.
innerGroupHandle
(
node
.
children
,
handledNode
,
[...
startChained
,
realIndex
])
}
// 将树形数据项添加到结果数组中
targetResult
.
push
(
treeItem
)
;
targetResult
.
push
(
treeItem
)
}
return
targetResult
;
return
targetResult
}
}
\ No newline at end of file
}
src/lib/XMLProcessor/src/index.ts
View file @
b909fba1
...
...
@@ -7,11 +7,12 @@ import {nodeSet} from '@/views/editor/constants/nodeParsed.ts'
const
p
=
new
Processing
()
// @ts-ignore
window
.
$p
=
function
()
{
p
.
dualCompareFromString
(
let
nodeV
=
p
.
dualCompareFromString
(
TextA
,
TextB
,
nodeSet
)
console
.
log
(
'v-h'
,
nodeV
)
}
export
const
XMLProcessing
:
Plugin
=
function
(
app
)
{
app
.
provide
(
'xmlProcessing'
,
p
);
...
...
src/lib/XMLProcessor/src/typing/index.d.ts
View file @
b909fba1
...
...
@@ -5,4 +5,22 @@ export type TreeRenderResult = {
hash
:
string
,
index
:
number
,
chained
:
number
[]
}
export
type
TreeRenderResultFlatted
=
{
key
:
string
,
label
:
string
,
hash
:
string
,
index
:
number
,
chained
:
number
[]
}
export
type
OldTreeModification
=
{
Changed
:
TreeRenderResultFlatted
[],
Deleted
:
TreeRenderResultFlatted
[]
}
export
type
NewTreeModification
=
{
Added
:
TreeRenderResultFlatted
[],
Changed
:
TreeRenderResultFlatted
[],
}
\ No newline at end of file
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment