158 lines
4.2 KiB
TypeScript
158 lines
4.2 KiB
TypeScript
// Copyright (c) 2024-present AI-Labs
|
|
|
|
// https://www.diagrams.com/doc/faq/embed-mode
|
|
class DiagramEditor {
|
|
frame: HTMLIFrameElement | undefined
|
|
container: string
|
|
domain = 'https://embed.diagrams.net'
|
|
// https://www.drawio.com/doc/faq/supported-url-parameters
|
|
params = {
|
|
ui: 'atlas',
|
|
proto: 'json',
|
|
libraries: 1,
|
|
configure: 1,
|
|
noSaveBtn: 1,
|
|
}
|
|
xml: string | null = null
|
|
format = 'xmlsvg'
|
|
data: any
|
|
|
|
constructor({
|
|
domain,
|
|
params,
|
|
container,
|
|
}: {
|
|
domain?: string
|
|
params?: Record<string, any>
|
|
container: string
|
|
}) {
|
|
this.domain = domain ?? this.domain
|
|
this.params = { ...params, ...this.params }
|
|
this.container = container
|
|
}
|
|
|
|
handleuseMessageEvent = (evt: MessageEvent) => {
|
|
if (
|
|
this.frame !== undefined &&
|
|
evt.source === this.frame.contentWindow &&
|
|
evt.data.length > 0
|
|
) {
|
|
try {
|
|
const msg = JSON.parse(evt.data)
|
|
if (msg) {
|
|
this.handleuseMessage(msg)
|
|
}
|
|
} catch (e) {
|
|
console.error(e)
|
|
}
|
|
}
|
|
}
|
|
|
|
// 编辑元素
|
|
edit(src: string) {
|
|
let fmt = this.format
|
|
if (src.substring(0, 15) === 'data:image/png;') {
|
|
fmt = 'xmlpng'
|
|
} else if (src.substring(0, 19) === 'data:image/svg+xml;') {
|
|
fmt = 'xmlsvg'
|
|
}
|
|
this.startEditing(src, fmt)
|
|
return this
|
|
}
|
|
|
|
// 创建 iframe
|
|
createFrame() {
|
|
const params = Object.keys(this.params)
|
|
.map((key) => `${key}=${this.params[key as keyof typeof this.params]}`)
|
|
.join('&')
|
|
const frame = document.createElement('iframe')
|
|
frame.setAttribute('class', 'uai-diagrams-iframe')
|
|
frame.setAttribute('src', `${this.domain}?${params}&lang=zh`)
|
|
return frame
|
|
}
|
|
|
|
// diagrams页面和当前页面通信
|
|
postMessage(msg: Record<string, any>) {
|
|
if (this.frame) {
|
|
this.frame.contentWindow?.postMessage(JSON.stringify(msg), '*')
|
|
}
|
|
}
|
|
handleuseMessage(msg: {
|
|
event: string
|
|
data: any
|
|
xml: string
|
|
exit: boolean
|
|
}) {
|
|
if (msg.event === 'configure') {
|
|
this.configureEditor()
|
|
} else if (msg.event === 'init') {
|
|
this.initializeEditor()
|
|
} else if (msg.event === 'save') {
|
|
this.export(msg.data)
|
|
this.xml = msg.xml
|
|
if (msg.exit) {
|
|
msg.event = 'exit'
|
|
} else {
|
|
this.postMessage({
|
|
action: 'status',
|
|
messageKey: 'allChangesSaved',
|
|
modified: false,
|
|
})
|
|
}
|
|
}
|
|
if (msg.event === 'exit') {
|
|
if (this.format !== 'xml') {
|
|
if (this.xml) {
|
|
this.postMessage({
|
|
action: 'export',
|
|
format: this.format,
|
|
xml: this.xml,
|
|
spinKey: 'export',
|
|
})
|
|
}
|
|
}
|
|
this.stopEditing()
|
|
}
|
|
}
|
|
|
|
// 开始编辑
|
|
startEditing(data: any, format: string) {
|
|
if (!this.frame) {
|
|
window.addEventListener('message', this.handleuseMessageEvent)
|
|
this.format = format ?? this.format
|
|
this.data = data
|
|
this.frame = this.createFrame()
|
|
const container = document.querySelector(this.container)
|
|
container?.appendChild(this.frame)
|
|
}
|
|
}
|
|
|
|
// 停止编辑
|
|
stopEditing() {
|
|
window.removeEventListener('message', this.handleuseMessageEvent)
|
|
this.frame = undefined
|
|
}
|
|
|
|
// 安装编辑器
|
|
initializeEditor() {
|
|
this.postMessage({
|
|
action: 'load',
|
|
autosave: 0,
|
|
saveAndExit: '1',
|
|
modified: 'unsavedChanges',
|
|
xml: this.data,
|
|
})
|
|
}
|
|
|
|
// 设置编辑器
|
|
configureEditor() {
|
|
this.postMessage({ action: 'configure', config: this.params.configure })
|
|
}
|
|
// 导出数据
|
|
export(data: any) {
|
|
return data
|
|
}
|
|
}
|
|
|
|
export default DiagramEditor
|