feat: improve ocd conflict merge ids
This commit is contained in:
parent
a946dc7ae8
commit
08d4e2a263
|
|
@ -72,6 +72,7 @@
|
||||||
"vue": "^3.2.45"
|
"vue": "^3.2.45"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"nanoid": "3.3.11",
|
||||||
"prismjs": "^1.27.0"
|
"prismjs": "^1.27.0"
|
||||||
},
|
},
|
||||||
"simple-git-hooks": {
|
"simple-git-hooks": {
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,9 @@ importers:
|
||||||
|
|
||||||
.:
|
.:
|
||||||
dependencies:
|
dependencies:
|
||||||
|
nanoid:
|
||||||
|
specifier: 3.3.11
|
||||||
|
version: 3.3.11
|
||||||
prismjs:
|
prismjs:
|
||||||
specifier: ^1.27.0
|
specifier: ^1.27.0
|
||||||
version: 1.30.0
|
version: 1.30.0
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,7 @@ import {
|
||||||
} from '../../interface/Element'
|
} from '../../interface/Element'
|
||||||
import { IRow, IRowElement } from '../../interface/Row'
|
import { IRow, IRowElement } from '../../interface/Row'
|
||||||
import { deepClone, getUUID, nextTick } from '../../utils'
|
import { deepClone, getUUID, nextTick } from '../../utils'
|
||||||
|
import { prepareOcdDocumentForSave } from '../../../utils/ocd'
|
||||||
import { Cursor } from '../cursor/Cursor'
|
import { Cursor } from '../cursor/Cursor'
|
||||||
import { CanvasEvent } from '../event/CanvasEvent'
|
import { CanvasEvent } from '../event/CanvasEvent'
|
||||||
import { GlobalEvent } from '../event/GlobalEvent'
|
import { GlobalEvent } from '../event/GlobalEvent'
|
||||||
|
|
@ -1196,7 +1197,7 @@ export class Draw {
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
version,
|
version,
|
||||||
data,
|
data: prepareOcdDocumentForSave(data),
|
||||||
options: deepClone(this.options)
|
options: deepClone(this.options)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ import { ICatalog } from '../../interface/Catalog'
|
||||||
import { IEditorResult } from '../../interface/Editor'
|
import { IEditorResult } from '../../interface/Editor'
|
||||||
import { IGetValueOption } from '../../interface/Draw'
|
import { IGetValueOption } from '../../interface/Draw'
|
||||||
import { deepClone } from '../../utils'
|
import { deepClone } from '../../utils'
|
||||||
|
import { prepareOcdDocumentForSave } from '../../../utils/ocd'
|
||||||
|
|
||||||
export class WorkerManager {
|
export class WorkerManager {
|
||||||
private draw: Draw
|
private draw: Draw
|
||||||
|
|
@ -78,7 +79,7 @@ export class WorkerManager {
|
||||||
this.valueWorker.onmessage = evt => {
|
this.valueWorker.onmessage = evt => {
|
||||||
resolve({
|
resolve({
|
||||||
version,
|
version,
|
||||||
data: evt.data,
|
data: prepareOcdDocumentForSave(evt.data),
|
||||||
options: deepClone(this.draw.getOptions())
|
options: deepClone(this.draw.getOptions())
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
||||||
22
src/main.ts
22
src/main.ts
|
|
@ -26,6 +26,10 @@ import { Dialog } from './components/dialog/Dialog'
|
||||||
import { formatPrismToken } from './utils/prism'
|
import { formatPrismToken } from './utils/prism'
|
||||||
import { Signature } from './components/signature/Signature'
|
import { Signature } from './components/signature/Signature'
|
||||||
import { debounce, nextTick, scrollIntoView } from './utils'
|
import { debounce, nextTick, scrollIntoView } from './utils'
|
||||||
|
import {
|
||||||
|
prepareOcdDocumentForOpen,
|
||||||
|
prepareOcdDocumentForSave
|
||||||
|
} from './utils/ocd'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 从本地文件URL中提取文件路径
|
* 从本地文件URL中提取文件路径
|
||||||
|
|
@ -249,7 +253,7 @@ window.onload = function () {
|
||||||
} catch {
|
} catch {
|
||||||
editorData = { main: [{ value: text }] }
|
editorData = { main: [{ value: text }] }
|
||||||
}
|
}
|
||||||
instance.command.executeSetValue(editorData)
|
instance.command.executeSetValue(prepareOcdDocumentForOpen(editorData))
|
||||||
console.log('[iframe] 通过 Electron 加载本地文件完成:', localFilePath)
|
console.log('[iframe] 通过 Electron 加载本地文件完成:', localFilePath)
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error('[iframe] 本地文件解析失败:', err)
|
console.error('[iframe] 本地文件解析失败:', err)
|
||||||
|
|
@ -273,7 +277,7 @@ window.onload = function () {
|
||||||
} catch {
|
} catch {
|
||||||
editorData = { main: [{ value: text }] }
|
editorData = { main: [{ value: text }] }
|
||||||
}
|
}
|
||||||
instance.command.executeSetValue(editorData)
|
instance.command.executeSetValue(prepareOcdDocumentForOpen(editorData))
|
||||||
console.log('[iframe] 根据 filePath 加载完成:', url)
|
console.log('[iframe] 根据 filePath 加载完成:', url)
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error('[iframe] 加载失败:', err)
|
console.error('[iframe] 加载失败:', err)
|
||||||
|
|
@ -334,7 +338,7 @@ window.onload = function () {
|
||||||
}
|
}
|
||||||
|
|
||||||
// 设置编辑器内容
|
// 设置编辑器内容
|
||||||
instance.command.executeSetValue(editorData)
|
instance.command.executeSetValue(prepareOcdDocumentForOpen(editorData))
|
||||||
console.log('文档已打开')
|
console.log('文档已打开')
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('打开文档失败:', error)
|
console.error('打开文档失败:', error)
|
||||||
|
|
@ -358,7 +362,11 @@ window.onload = function () {
|
||||||
try {
|
try {
|
||||||
// 获取编辑器内容
|
// 获取编辑器内容
|
||||||
const editorValue = instance.command.getValue()
|
const editorValue = instance.command.getValue()
|
||||||
const content = JSON.stringify(editorValue.data, null, 2)
|
const content = JSON.stringify(
|
||||||
|
prepareOcdDocumentForSave(editorValue.data),
|
||||||
|
null,
|
||||||
|
2
|
||||||
|
)
|
||||||
|
|
||||||
// 创建下载链接
|
// 创建下载链接
|
||||||
const blob = new Blob([content], { type: 'application/json' })
|
const blob = new Blob([content], { type: 'application/json' })
|
||||||
|
|
@ -391,7 +399,11 @@ window.onload = function () {
|
||||||
saveCallbackDom.onclick = function () {
|
saveCallbackDom.onclick = function () {
|
||||||
try {
|
try {
|
||||||
const editorValue = instance.command.getValue()
|
const editorValue = instance.command.getValue()
|
||||||
const content = JSON.stringify(editorValue.data, null, 2)
|
const content = JSON.stringify(
|
||||||
|
prepareOcdDocumentForSave(editorValue.data),
|
||||||
|
null,
|
||||||
|
2
|
||||||
|
)
|
||||||
|
|
||||||
const parentWin: any = window.parent || window
|
const parentWin: any = window.parent || window
|
||||||
const viewer =
|
const viewer =
|
||||||
|
|
|
||||||
100
src/utils/ocd.ts
Normal file
100
src/utils/ocd.ts
Normal file
|
|
@ -0,0 +1,100 @@
|
||||||
|
import { nanoid } from 'nanoid'
|
||||||
|
import { IEditorData } from '../editor'
|
||||||
|
|
||||||
|
const CONFLICT_MARKER_HIGHLIGHT = '#fff3cd'
|
||||||
|
const CONFLICT_MARKER_COLOR = '#b42318'
|
||||||
|
const CONFLICT_MARKER_REG = /^(<<<<<<<|=======|>>>>>>>)\b/
|
||||||
|
|
||||||
|
type UnknownRecord = Record<string, unknown>
|
||||||
|
|
||||||
|
function isRecord(value: unknown): value is UnknownRecord {
|
||||||
|
return Boolean(value) && typeof value === 'object' && !Array.isArray(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
function isElementList(value: unknown): value is UnknownRecord[] {
|
||||||
|
return Array.isArray(value) && value.every(isRecord)
|
||||||
|
}
|
||||||
|
|
||||||
|
function isConflictMarkerText(value: unknown) {
|
||||||
|
return typeof value === 'string' && CONFLICT_MARKER_REG.test(value.trim())
|
||||||
|
}
|
||||||
|
|
||||||
|
function normalizeConflictElement(element: UnknownRecord, isMarker: boolean) {
|
||||||
|
if (isMarker) {
|
||||||
|
element.highlight = CONFLICT_MARKER_HIGHLIGHT
|
||||||
|
element.color = CONFLICT_MARKER_COLOR
|
||||||
|
element.bold = true
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (element.highlight === CONFLICT_MARKER_HIGHLIGHT) {
|
||||||
|
delete element.highlight
|
||||||
|
}
|
||||||
|
if (element.color === CONFLICT_MARKER_COLOR) {
|
||||||
|
delete element.color
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function prepareElementList(elementList: UnknownRecord[]) {
|
||||||
|
for (const element of elementList) {
|
||||||
|
if (isElementList(element.valueList)) {
|
||||||
|
const isMarker =
|
||||||
|
element._ocdConflictMarker === true ||
|
||||||
|
element.valueList.some(item => isConflictMarkerText(item.value))
|
||||||
|
for (const item of element.valueList) {
|
||||||
|
if (typeof item.id !== 'string' || !item.id) {
|
||||||
|
item.id = nanoid()
|
||||||
|
}
|
||||||
|
normalizeConflictElement(item, isMarker || isConflictMarkerText(item.value))
|
||||||
|
prepareNestedElement(item)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
prepareNestedElement(element)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function prepareNestedElement(element: UnknownRecord) {
|
||||||
|
const trList = element.trList
|
||||||
|
if (Array.isArray(trList)) {
|
||||||
|
for (const tr of trList) {
|
||||||
|
if (!isRecord(tr) || !Array.isArray(tr.tdList)) continue
|
||||||
|
for (const td of tr.tdList) {
|
||||||
|
if (!isRecord(td) || !isElementList(td.value)) continue
|
||||||
|
prepareElementList(td.value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const control = element.control
|
||||||
|
if (isRecord(control) && isElementList(control.value)) {
|
||||||
|
prepareElementList(control.value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function cloneEditorData(data: IEditorData): IEditorData {
|
||||||
|
if (typeof structuredClone === 'function') {
|
||||||
|
return structuredClone(data) as IEditorData
|
||||||
|
}
|
||||||
|
return JSON.parse(JSON.stringify(data)) as IEditorData
|
||||||
|
}
|
||||||
|
|
||||||
|
export function prepareOcdDocumentForSave(data: IEditorData): IEditorData {
|
||||||
|
const prepared = cloneEditorData(data)
|
||||||
|
;(['header', 'main', 'footer'] as const).forEach(key => {
|
||||||
|
const elementList = prepared[key]
|
||||||
|
if (isElementList(elementList)) {
|
||||||
|
prepareElementList(elementList)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return prepared
|
||||||
|
}
|
||||||
|
|
||||||
|
export function prepareOcdDocumentForOpen(data: IEditorData): IEditorData {
|
||||||
|
if (!isRecord(data)) return data
|
||||||
|
;(['header', 'main', 'footer'] as const).forEach(key => {
|
||||||
|
const elementList = data[key]
|
||||||
|
if (isElementList(elementList)) {
|
||||||
|
prepareElementList(elementList)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return data
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user