Merge pull request #147 from Hufe921/feature/header

Feature/header
pr675
Hufe 3 years ago committed by GitHub
commit 2350c84915
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -34,9 +34,7 @@ describe('控件-复选框', () => {
}
}])
const payload = editor.command.getValue()
const data = payload.data[0]
const data = editor.command.getValue().data.main[0]
expect(data.control!.code).to.be.eq('98175')
})

@ -41,9 +41,7 @@ describe('控件-列举型', () => {
.eq(0)
.click()
.then(() => {
const payload = editor.command.getValue()
const data = payload.data[0]
const data = editor.command.getValue().data.main[0]
expect(data.control!.value![0].value).to.be.eq(text)

@ -33,9 +33,7 @@ describe('控件-文本型', () => {
cy.get('.ce-inputarea')
.type(text)
.then(() => {
const payload = editor.command.getValue()
const data = payload.data[0]
const data = editor.command.getValue().data.main[0]
expect(data.control!.value![0].value).to.be.eq(text)
})

@ -19,9 +19,9 @@ describe('基础功能', () => {
cy.get('@canvas')
.type(text)
.then(() => {
const payload = editor.command.getValue()
const data = editor.command.getValue().data.main
expect(payload.data[0].value).to.eq(text)
expect(data[0].value).to.eq(text)
})
})
})

@ -28,9 +28,7 @@ describe('菜单-内容块', () => {
.eq(1)
.click()
.then(() => {
const payload = editor.command.getValue()
const data = payload.data
const data = editor.command.getValue().data.main
expect(data[0].type).to.eq('block')

@ -24,9 +24,7 @@ describe('菜单-复选框', () => {
}
}])
const payload = editor.command.getValue()
const data = payload.data[0]
const data = editor.command.getValue().data.main[0]
expect(data.checkbox?.value).to.eq(true)
})

@ -24,9 +24,7 @@ describe('菜单-代码块', () => {
.eq(1)
.click()
.then(() => {
const payload = editor.command.getValue()
const data = payload.data[2]
const data = editor.command.getValue().data.main[2]
expect(data.value).to.eq('log')

@ -20,9 +20,7 @@ describe('菜单-日期选择器', () => {
.first()
.click()
.then(() => {
const payload = editor.command.getValue()
const data = payload.data
const data = editor.command.getValue().data.main
expect(data[0].type).to.eq('date')
})

@ -28,9 +28,7 @@ describe('菜单-清除格式', () => {
cy.get('.menu-item__format')
.click()
.then(() => {
const payload = editor.command.getValue()
const data = payload.data
const data = editor.command.getValue().data.main
expect(data[0].italic).to.eq(false)

@ -27,9 +27,7 @@ describe('菜单-超链接', () => {
.eq(1)
.click()
.then(() => {
const payload = editor.command.getValue()
const data = payload.data
const data = editor.command.getValue().data.main
expect(data[0].type).to.eq('hyperlink')

@ -17,8 +17,8 @@ describe('菜单-图片', () => {
cy.get('#image').attachFile('test.png')
cy.wait(200).then(() => {
const payload = editor.command.getValue()
const data = payload.data
const data = editor.command.getValue().data.main
expect(data[0].type).to.eq('image')
})
})

@ -24,9 +24,7 @@ describe('菜单-LaTeX', () => {
.eq(1)
.click()
.then(() => {
const payload = editor.command.getValue()
const data = payload.data
const data = editor.command.getValue().data.main
expect(data[0].type).to.eq('latex')

@ -36,9 +36,7 @@ describe('菜单-格式刷', () => {
editor.command.executeApplyPainterStyle()
const payload = editor.command.getValue()
const data = payload.data
const data = editor.command.getValue().data.main
expect(data.length).to.eq(1)

@ -23,9 +23,7 @@ describe('菜单-行处理', () => {
cy.get('.menu-item__left')
.click()
.then(() => {
const payload = editor.command.getValue()
const data = payload.data
const data = editor.command.getValue().data.main
expect(data[0].rowFlex).to.eq('left')
})
@ -45,9 +43,7 @@ describe('菜单-行处理', () => {
cy.get('.menu-item__center')
.click()
.then(() => {
const payload = editor.command.getValue()
const data = payload.data
const data = editor.command.getValue().data.main
expect(data[0].rowFlex).to.eq('center')
})
@ -67,9 +63,7 @@ describe('菜单-行处理', () => {
cy.get('.menu-item__right')
.click()
.then(() => {
const payload = editor.command.getValue()
const data = payload.data
const data = editor.command.getValue().data.main
expect(data[0].rowFlex).to.eq('right')
})
@ -93,9 +87,7 @@ describe('菜单-行处理', () => {
.eq(1)
.click()
.then(() => {
const payload = editor.command.getValue()
const data = payload.data
const data = editor.command.getValue().data.main
expect(data[0].rowMargin).to.eq(1.25)
})

@ -93,9 +93,7 @@ describe('菜单-搜索', () => {
.find('button')
.click()
.then(() => {
const payload = editor.command.getValue()
const data = payload.data
const data = editor.command.getValue().data.main
// 普通文本
expect(data[0].value).to.be.eq(replaceText)

@ -20,9 +20,7 @@ describe('菜单-分割线', () => {
.eq(1)
.click()
.then(() => {
const payload = editor.command.getValue()
const data = payload.data
const data = editor.command.getValue().data.main
expect(data[0].type).to.eq('separator')

@ -16,9 +16,7 @@ describe('菜单-表格', () => {
editor.command.executeInsertTable(8, 8)
const payload = editor.command.getValue()
const data = payload.data
const data = editor.command.getValue().data.main
expect(data[0].type).to.eq('table')

@ -30,9 +30,7 @@ describe('菜单-文本处理', () => {
.eq(1)
.click()
.then(() => {
const payload = editor.command.getValue()
const data = payload.data
const data = editor.command.getValue().data.main
expect(data[0].font).to.eq('宋体')
})
@ -54,9 +52,7 @@ describe('菜单-文本处理', () => {
cy.get('.menu-item__size-add')
.click()
.then(() => {
const payload = editor.command.getValue()
const data = payload.data
const data = editor.command.getValue().data.main
expect(data[0].size).to.eq(18)
})
@ -78,9 +74,7 @@ describe('菜单-文本处理', () => {
cy.get('.menu-item__size-minus')
.click()
.then(() => {
const payload = editor.command.getValue()
const data = payload.data
const data = editor.command.getValue().data.main
expect(data[0].size).to.eq(14)
})
@ -102,9 +96,7 @@ describe('菜单-文本处理', () => {
cy.get('.menu-item__bold')
.click()
.then(() => {
const payload = editor.command.getValue()
const data = payload.data
const data = editor.command.getValue().data.main
expect(data[0].bold).to.eq(true)
})
@ -126,9 +118,7 @@ describe('菜单-文本处理', () => {
cy.get('.menu-item__italic')
.click()
.then(() => {
const payload = editor.command.getValue()
const data = payload.data
const data = editor.command.getValue().data.main
expect(data[0].italic).to.eq(true)
})
@ -150,9 +140,7 @@ describe('菜单-文本处理', () => {
cy.get('.menu-item__underline')
.click()
.then(() => {
const payload = editor.command.getValue()
const data = payload.data
const data = editor.command.getValue().data.main
expect(data[0].underline).to.eq(true)
})
@ -174,9 +162,7 @@ describe('菜单-文本处理', () => {
cy.get('.menu-item__strikeout')
.click()
.then(() => {
const payload = editor.command.getValue()
const data = payload.data
const data = editor.command.getValue().data.main
expect(data[0].strikeout).to.eq(true)
})
@ -198,9 +184,7 @@ describe('菜单-文本处理', () => {
cy.get('.menu-item__superscript')
.click()
.then(() => {
const payload = editor.command.getValue()
const data = payload.data
const data = editor.command.getValue().data.main
expect(data[0].type).to.eq('superscript')
})
@ -220,9 +204,7 @@ describe('菜单-文本处理', () => {
editor.command.executeSetRange(0, textLength)
cy.get('.menu-item__subscript').click().then(() => {
const payload = editor.command.getValue()
const data = payload.data
const data = editor.command.getValue().data.main
expect(data[0].type).to.eq('subscript')
})
@ -243,9 +225,7 @@ describe('菜单-文本处理', () => {
editor.command.executeColor('red')
const payload = editor.command.getValue()
const data = payload.data
const data = editor.command.getValue().data.main
expect(data[0].color).to.eq('red')
})
@ -265,9 +245,7 @@ describe('菜单-文本处理', () => {
editor.command.executeHighlight('red')
const payload = editor.command.getValue()
const data = payload.data
const data = editor.command.getValue().data.main
expect(data[0].highlight).to.eq('red')
})

@ -21,9 +21,9 @@ describe('菜单-撤销&重做', () => {
cy.get('.menu-item__undo')
.click()
.then(() => {
const payload = editor.command.getValue()
const data = editor.command.getValue().data.main
expect(payload.data[0].value).to.eq(text)
expect(data[0].value).to.eq(text)
})
})
})
@ -41,9 +41,9 @@ describe('菜单-撤销&重做', () => {
cy.get('.menu-item__redo')
.click()
.then(() => {
const payload = editor.command.getValue()
const data = editor.command.getValue().data.main
expect(payload.data[0].value).to.eq(`${text}1`)
expect(data[0].value).to.eq(`${text}1`)
})
})
})

@ -63,7 +63,9 @@ export class Cursor {
const height = this.draw.getHeight()
const pageGap = this.draw.getPageGap()
const { metrics, coordinate: { leftTop, rightTop }, ascent, pageNo } = cursorPosition
const preY = pageNo * (height + pageGap)
const zoneManager = this.draw.getZone()
const curPageNo = zoneManager.isMainActive() ? pageNo : this.draw.getPageNo()
const preY = curPageNo * (height + pageGap)
// 增加1/4字体大小
const offsetHeight = metrics.height / 4
const cursorHeight = metrics.height + offsetHeight * 2

@ -1,9 +1,9 @@
import { version } from '../../../../package.json'
import { ZERO } from '../../dataset/constant/Common'
import { RowFlex } from '../../dataset/enum/Row'
import { IDrawOption, IDrawRowPayload, IPainterOptions } from '../../interface/Draw'
import { IEditorOption, IEditorResult } from '../../interface/Editor'
import { IElement, IElementMetrics, IElementPosition, IElementFillRect, IElementStyle } from '../../interface/Element'
import { IDrawOption, IDrawPagePayload, IDrawRowPayload, IPainterOptions } from '../../interface/Draw'
import { IEditorData, IEditorOption, IEditorResult } from '../../interface/Editor'
import { IElement, IElementMetrics, IElementFillRect, IElementStyle } from '../../interface/Element'
import { IRow, IRowElement } from '../../interface/Row'
import { deepClone, getUUID, nextTick } from '../../utils'
import { Cursor } from '../cursor/Cursor'
@ -35,7 +35,7 @@ import { SubscriptParticle } from './particle/Subscript'
import { SeparatorParticle } from './particle/Separator'
import { PageBreakParticle } from './particle/PageBreak'
import { Watermark } from './frame/Watermark'
import { EditorComponent, EditorMode, PageMode, PaperDirection } from '../../dataset/enum/Editor'
import { EditorComponent, EditorMode, EditorZone, PageMode, PaperDirection } from '../../dataset/enum/Editor'
import { Control } from './control/Control'
import { zipElementList } from '../../utils/element'
import { CheckboxParticle } from './particle/CheckboxParticle'
@ -50,6 +50,7 @@ import { BlockParticle } from './particle/block/BlockParticle'
import { EDITOR_COMPONENT, EDITOR_PREFIX } from '../../dataset/constant/Editor'
import { I18n } from '../i18n/I18n'
import { ImageObserver } from '../observer/ImageObserver'
import { Zone } from '../zone/Zone'
export class Draw {
@ -61,7 +62,10 @@ export class Draw {
private mode: EditorMode
private options: DeepRequired<IEditorOption>
private position: Position
private zone: Zone
private headerElementList: IElement[]
private elementList: IElement[]
private footerElementList: IElement[]
private listener: Listener
private i18n: I18n
@ -110,7 +114,7 @@ export class Draw {
constructor(
rootContainer: HTMLElement,
options: DeepRequired<IEditorOption>,
elementList: IElement[],
data: IEditorData,
listener: Listener
) {
this.container = this._wrapContainer(rootContainer)
@ -119,7 +123,9 @@ export class Draw {
this.pageNo = 0
this.mode = options.mode
this.options = options
this.elementList = elementList
this.headerElementList = data.header || []
this.elementList = data.main
this.footerElementList = data.footer || []
this.listener = listener
this._formatContainer()
@ -129,6 +135,7 @@ export class Draw {
this.i18n = new I18n()
this.historyManager = new HistoryManager()
this.position = new Position(this)
this.zone = new Zone()
this.range = new RangeManager(this)
this.margin = new Margin(this)
this.background = new Background(this)
@ -208,6 +215,12 @@ export class Draw {
return Math.floor(this.getOriginalHeight() * this.options.scale)
}
public getOriginalMainHeight(): number {
const mainHeight = this.getOriginalHeight()
const extraHeight = this.header.getExtraHeight()
return mainHeight - extraHeight
}
public getCanvasWidth(pageNo = -1): number {
const page = this.getPage(pageNo)
return page.width
@ -339,19 +352,54 @@ export class Draw {
return this.position
}
public getZone(): Zone {
return this.zone
}
public getRange(): RangeManager {
return this.range
}
public getHeaderElementList(): IElement[] {
return this.headerElementList
}
public getTableElementList(sourceElementList: IElement[]): IElement[] {
const positionContext = this.position.getPositionContext()
const { index, trIndex, tdIndex } = positionContext
return sourceElementList[index!].trList![trIndex!].tdList[tdIndex!].value
}
public getElementList(): IElement[] {
const positionContext = this.position.getPositionContext()
if (positionContext.isTable) {
const { index, trIndex, tdIndex } = positionContext
return this.elementList[index!].trList![trIndex!].tdList[tdIndex!].value
}
const elementList = this.getOriginalElementList()
return positionContext.isTable
? this.getTableElementList(elementList)
: elementList
}
public getMainElementList(): IElement[] {
const positionContext = this.position.getPositionContext()
return positionContext.isTable
? this.getTableElementList(this.elementList)
: this.elementList
}
public getOriginalElementList() {
const zoneManager = this.getZone()
return zoneManager.isHeaderActive()
? this.header.getElementList()
: this.elementList
}
public getOriginalMainElementList(): IElement[] {
return this.elementList
}
public getFooterElementList(): IElement[] {
return this.footerElementList
}
public insertElementList(payload: IElement[]) {
if (!payload.length) return
const isPartRangeInControlOutside = this.control.isPartRangeInControlOutside()
@ -394,10 +442,6 @@ export class Draw {
}
}
public getOriginalElementList() {
return this.elementList
}
public getCanvasEvent(): CanvasEvent {
return this.canvasEvent
}
@ -422,6 +466,10 @@ export class Draw {
return this.tableTool
}
public getHeader(): Header {
return this.header
}
public getHyperlinkParticle(): HyperlinkParticle {
return this.hyperlinkParticle
}
@ -596,15 +644,17 @@ export class Draw {
public getValue(): IEditorResult {
// 配置
const { width, height, margins, watermark, header } = this.options
const { width, height, margins, watermark } = this.options
// 数据
const data = zipElementList(this.elementList)
const data: IEditorData = {
header: zipElementList(this.headerElementList),
main: zipElementList(this.elementList)
}
return {
version,
width,
height,
margins,
header: header.data ? header : undefined,
watermark: watermark.data ? watermark : undefined,
data
}
@ -670,7 +720,7 @@ export class Draw {
return `${el.italic ? 'italic ' : ''}${el.bold ? 'bold ' : ''}${size * scale}px ${font}`
}
private _computeRowList(innerWidth: number, elementList: IElement[]) {
public computeRowList(innerWidth: number, elementList: IElement[]) {
const { defaultSize, defaultRowMargin, scale, tdPadding, defaultTabWidth } = this.options
const defaultBasicRowMarginHeight = this.getDefaultBasicRowMarginHeight()
const canvas = document.createElement('canvas')
@ -726,7 +776,7 @@ export class Draw {
let maxTrHeight = 0
for (let d = 0; d < tr.tdList.length; d++) {
const td = tr.tdList[d]
const rowList = this._computeRowList((td.width! - tdGap) * scale, td.value)
const rowList = this.computeRowList((td.width! - tdGap) * scale, td.value)
const rowHeight = rowList.reduce((pre, cur) => pre + cur.height, 0)
td.rowList = rowList
// 移除缩放导致的行高变化-渲染时会进行缩放调整
@ -754,7 +804,7 @@ export class Draw {
metrics.boundingBoxAscent = 0
// 表格分页处理(拆分表格)
const margins = this.getMargins()
const height = this.getHeight()
const height = this.getOriginalMainHeight()
const marginHeight = margins[0] + margins[2]
let curPagePreHeight = marginHeight
for (let r = 0; r < rowList.length; r++) {
@ -812,13 +862,13 @@ export class Draw {
} else if (element.type === ElementType.SEPARATOR) {
element.width = innerWidth
metrics.width = innerWidth
metrics.height = this.options.defaultSize
metrics.height = defaultSize
metrics.boundingBoxAscent = -rowMargin
metrics.boundingBoxDescent = -rowMargin
} else if (element.type === ElementType.PAGE_BREAK) {
element.width = innerWidth
metrics.width = innerWidth
metrics.height = this.options.defaultSize
metrics.height = defaultSize
} else if (
element.type === ElementType.CHECKBOX ||
element.controlComponent === ControlComponent.CHECKBOX
@ -846,7 +896,7 @@ export class Draw {
metrics.boundingBoxAscent = 0
} else {
// 设置上下标真实字体尺寸
const size = element.size || this.options.defaultSize
const size = element.size || defaultSize
if (element.type === ElementType.SUPERSCRIPT || element.type === ElementType.SUBSCRIPT) {
element.actualSize = Math.ceil(size * 0.6)
}
@ -920,7 +970,7 @@ export class Draw {
private _computePageList(): IRow[][] {
const pageRowList: IRow[][] = [[]]
const { pageMode } = this.options
const height = this.getHeight()
const height = this.getOriginalMainHeight()
const margins = this.getMargins()
const marginHeight = margins[0] + margins[2]
let pageHeight = marginHeight
@ -964,8 +1014,8 @@ export class Draw {
this.textParticle.complete()
}
private _drawRow(ctx: CanvasRenderingContext2D, payload: IDrawRowPayload) {
const { rowList, pageNo, positionList, startIndex } = payload
public drawRow(ctx: CanvasRenderingContext2D, payload: IDrawRowPayload) {
const { rowList, pageNo, elementList, positionList, startIndex, zone } = payload
const { scale, tdPadding } = this.options
const { isCrossRowCol, tableId } = this.range.getRange()
let index = startIndex
@ -1063,11 +1113,11 @@ export class Draw {
this.highlight.render(ctx)
}
// 选区记录
const { startIndex, endIndex } = this.range.getRange()
if (startIndex !== endIndex && startIndex <= index && index <= endIndex) {
const { zone: currentZone, startIndex, endIndex } = this.range.getRange()
if (currentZone === zone && startIndex !== endIndex && startIndex <= index && index <= endIndex) {
// 从行尾开始-绘制最小宽度
if (startIndex === index) {
const nextElement = this.elementList[startIndex + 1]
const nextElement = elementList[startIndex + 1]
if (nextElement && nextElement.value === ZERO) {
rangeRecord.x = x + metrics.width
rangeRecord.y = y
@ -1104,12 +1154,14 @@ export class Draw {
const tr = element.trList![t]
for (let d = 0; d < tr.tdList!.length; d++) {
const td = tr.tdList[d]
this._drawRow(ctx, {
this.drawRow(ctx, {
elementList: td.value,
positionList: td.positionList!,
rowList: td.rowList!,
pageNo,
startIndex: 0,
innerWidth: (td.width! - tdGap) * scale
innerWidth: (td.width! - tdGap) * scale,
zone
})
}
}
@ -1136,10 +1188,13 @@ export class Draw {
this.blockParticle.clear()
}
private _drawPage(positionList: IElementPosition[], rowList: IRow[], pageNo: number) {
const { pageMode } = this.options
private _drawPage(payload: IDrawPagePayload) {
const { elementList, positionList, rowList, pageNo } = payload
const { inactiveAlpha, pageMode } = this.options
const innerWidth = this.getInnerWidth()
const ctx = this.ctxList[pageNo]
// 判断当前激活区域-激活页眉时主题元素透明度降低
ctx.globalAlpha = this.zone.isHeaderActive() ? inactiveAlpha : 1
this._clearPage(pageNo)
// 绘制背景
this.background.render(ctx)
@ -1147,15 +1202,17 @@ export class Draw {
this.margin.render(ctx, pageNo)
// 渲染元素
const index = rowList[0].startIndex
this._drawRow(ctx, {
this.drawRow(ctx, {
elementList,
positionList,
rowList,
pageNo,
startIndex: index,
innerWidth
innerWidth,
zone: EditorZone.MAIN
})
// 绘制页眉
this.header.render(ctx)
this.header.render(ctx, pageNo)
// 绘制页码
this.pageNumber.render(ctx, pageNo)
// 搜索匹配绘制
@ -1169,13 +1226,20 @@ export class Draw {
}
private _lazyRender() {
const positionList = this.position.getOriginalPositionList()
const positionList = this.position.getOriginalMainPositionList()
const elementList = this.getOriginalMainElementList()
this.lazyRenderIntersectionObserver?.disconnect()
this.lazyRenderIntersectionObserver = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
const index = Number((<HTMLCanvasElement>entry.target).dataset.index)
this._drawPage(positionList, this.pageRowList[index], index)
this.header.render(this.ctxList[index], index)
this._drawPage({
elementList,
positionList,
rowList: this.pageRowList[index],
pageNo: index
})
}
})
})
@ -1185,9 +1249,15 @@ export class Draw {
}
private _immediateRender() {
const positionList = this.position.getOriginalPositionList()
const positionList = this.position.getOriginalMainPositionList()
const elementList = this.getOriginalMainElementList()
for (let i = 0; i < this.pageRowList.length; i++) {
this._drawPage(positionList, this.pageRowList[i], i)
this._drawPage({
elementList,
positionList,
rowList: this.pageRowList[i],
pageNo: i
})
}
}
@ -1203,8 +1273,10 @@ export class Draw {
const innerWidth = this.getInnerWidth()
// 计算文档信息
if (isCompute) {
// 页眉信息
this.header.compute()
// 行信息
this.rowList = this._computeRowList(innerWidth, this.elementList)
this.rowList = this.computeRowList(innerWidth, this.elementList)
// 页面信息
this.pageRowList = this._computePageList()
// 位置信息
@ -1219,7 +1291,6 @@ export class Draw {
this.imageObserver.clearAll()
this.cursor.recoveryCursor()
// 创建纸张
const positionList = this.position.getOriginalPositionList()
for (let i = 0; i < this.pageRowList.length; i++) {
if (!this.pageList[i]) {
this._createPage(i)
@ -1243,20 +1314,19 @@ export class Draw {
}
// 光标重绘
if (isSetCursor) {
const positionList = this.position.getPositionList()
const positionContext = this.position.getPositionContext()
if (positionContext.isTable) {
const { index, trIndex, tdIndex } = positionContext
const tablePositionList = this.elementList[index!].trList?.[trIndex!].tdList[tdIndex!].positionList
const elementList = this.getOriginalElementList()
const tablePositionList = elementList[index!].trList?.[trIndex!].tdList[tdIndex!].positionList
if (curIndex === undefined && tablePositionList) {
curIndex = tablePositionList.length - 1
}
const tablePosition = tablePositionList?.[curIndex!]
this.position.setCursorPosition(tablePosition || null)
} else {
if (curIndex === undefined) {
curIndex = positionList.length - 1
}
this.position.setCursorPosition(positionList[curIndex!] || null)
this.position.setCursorPosition(curIndex !== undefined ? positionList[curIndex] : null)
}
this.cursor.drawCursor()
}
@ -1264,12 +1334,16 @@ export class Draw {
if (isSubmitHistory) {
const self = this
const oldElementList = deepClone(this.elementList)
const oldHeaderElementList = deepClone(this.header.getElementList())
const { startIndex, endIndex } = this.range.getRange()
const pageNo = this.pageNo
const oldPositionContext = deepClone(this.position.getPositionContext())
const zone = this.zone.getZone()
this.historyManager.execute(function () {
self.zone.setZone(zone)
self.setPageNo(pageNo)
self.position.setPositionContext(oldPositionContext)
self.header.setElementList(oldHeaderElementList)
self.elementList = deepClone(oldElementList)
self.range.setRange(startIndex, endIndex)
self.render({ curIndex, isSubmitHistory: false })

@ -1,31 +1,126 @@
import { maxHeightRadioMapping } from '../../../dataset/constant/Header'
import { EditorZone } from '../../../dataset/enum/Editor'
import { DeepRequired } from '../../../interface/Common'
import { IEditorOption } from '../../../interface/Editor'
import { IElement, IElementPosition } from '../../../interface/Element'
import { IRow } from '../../../interface/Row'
import { Position } from '../../position/Position'
import { Draw } from '../Draw'
export class Header {
private draw: Draw
private position: Position
private options: DeepRequired<IEditorOption>
private elementList: IElement[]
private rowList: IRow[]
private positionList: IElementPosition[]
constructor(draw: Draw) {
this.draw = draw
this.options = <DeepRequired<IEditorOption>>draw.getOptions()
}
public render(ctx: CanvasRenderingContext2D) {
const { header: { data, size, color, font }, scale } = this.options
if (!data) return
const width = this.draw.getWidth()
const top = this.draw.getHeaderTop()
ctx.save()
ctx.fillStyle = color
ctx.font = `${size! * scale}px ${font}`
// 文字长度
const textWidth = ctx.measureText(`${data}`).width
// 偏移量
const left = (width - textWidth) / 2
ctx.fillText(`${data}`, left < 0 ? 0 : left, top)
ctx.restore()
this.position = draw.getPosition()
this.options = draw.getOptions()
this.elementList = draw.getHeaderElementList()
this.rowList = []
this.positionList = []
}
public setElementList(elementList: IElement[]) {
this.elementList = elementList
}
public getElementList(): IElement[] {
return this.elementList
}
public getPositionList(): IElementPosition[] {
return this.positionList
}
public compute() {
this._recovery()
this._computeRowList()
this._computePositionList()
}
private _recovery() {
this.rowList = []
this.positionList = []
}
private _computeRowList() {
const innerWidth = this.draw.getInnerWidth()
this.rowList = this.draw.computeRowList(innerWidth, this.elementList)
}
private _computePositionList() {
const { header: { top } } = this.options
const innerWidth = this.draw.getInnerWidth()
const margins = this.draw.getMargins()
const startX = margins[3]
const startY = top
this.position.computePageRowPosition({
positionList: this.positionList,
rowList: this.rowList,
pageNo: 0,
startIndex: 0,
startX,
startY,
innerWidth
})
}
public getMaxHeight(): number {
const { header: { maxHeightRadio } } = this.options
const height = this.draw.getOriginalHeight()
return Math.floor(height * maxHeightRadioMapping[maxHeightRadio])
}
public getHeight(): number {
const maxHeight = this.getMaxHeight()
const rowHeight = this.getRowHeight()
return rowHeight > maxHeight ? maxHeight : rowHeight
}
public getRowHeight(): number {
return this.rowList.reduce((pre, cur) => pre + cur.height, 0)
}
public getExtraHeight(): number {
const { header: { top: headerTop } } = this.options
// 页眉上边距 + 实际高 - 页面上边距
const margins = this.draw.getOriginalMargins()
const headerHeight = this.getHeight()
const extraHeight = headerTop + headerHeight - margins[0]
return extraHeight <= 0 ? 0 : extraHeight
}
public render(ctx: CanvasRenderingContext2D, pageNo: number) {
ctx.globalAlpha = 1
const innerWidth = this.draw.getInnerWidth()
const maxHeight = this.getMaxHeight()
// 超出最大高度不渲染
const rowList: IRow[] = []
let curRowHeight = 0
for (let r = 0; r < this.rowList.length; r++) {
const row = this.rowList[r]
if (curRowHeight + row.height > maxHeight) {
break
}
rowList.push(row)
curRowHeight += row.height
}
this.draw.drawRow(ctx, {
elementList: this.elementList,
positionList: this.positionList,
rowList,
pageNo,
startIndex: 0,
innerWidth,
zone: EditorZone.HEADER
})
}
}

@ -147,8 +147,8 @@ export class CanvasEvent {
keydown(evt, this)
}
public dblclick() {
click.dblclick(this)
public dblclick(evt: MouseEvent) {
click.dblclick(this, evt)
}
public threeClick() {

@ -2,9 +2,25 @@ import { ZERO } from '../../../dataset/constant/Common'
import { LETTER_REG, NUMBER_LIKE_REG } from '../../../dataset/constant/Regular'
import { CanvasEvent } from '../CanvasEvent'
function dblclick(host: CanvasEvent) {
function dblclick(host: CanvasEvent, evt: MouseEvent) {
// 切换区域
const draw = host.getDraw()
const position = draw.getPosition()
const positionContext = position.getPositionByXY({
x: evt.offsetX,
y: evt.offsetY
})
if (!~positionContext.index && positionContext.zone) {
draw.getZone().setZone(positionContext.zone)
draw.getRange().clearRange()
draw.render({
isSubmitHistory: false,
isSetCursor: false,
isCompute: false
})
return
}
// 自动扩选文字
const cursorPosition = position.getCursorPosition()
if (!cursorPosition) return
const { value, index } = cursorPosition

@ -21,10 +21,12 @@ function dragover(evt: DragEvent | MouseEvent, host: CanvasEvent) {
draw.setPageNo(Number(pageIndex))
}
const position = draw.getPosition()
const { isTable, tdValueIndex, index } = position.adjustPositionContext({
const positionContext = position.adjustPositionContext({
x: evt.offsetX,
y: evt.offsetY
})
if (!positionContext) return
const { isTable, tdValueIndex, index } = positionContext
// 设置选区及光标位置
const positionList = position.getPositionList()
const curIndex = isTable ? tdValueIndex! : index

@ -36,6 +36,7 @@ export function mousedown(evt: MouseEvent, host: CanvasEvent) {
x: evt.offsetX,
y: evt.offsetY
})
if (!positionResult) return
const {
index,
isDirectHit,

@ -32,6 +32,7 @@ export function mousemove(evt: MouseEvent, host: CanvasEvent) {
x: evt.offsetX,
y: evt.offsetY
})
if (!~positionResult.index) return
const {
index,
isTable,

@ -3,9 +3,10 @@ import { ZERO } from '../../dataset/constant/Common'
import { ControlComponent, ImageDisplay } from '../../dataset/enum/Control'
import { IComputePageRowPositionPayload, IComputePageRowPositionResult } from '../../interface/Position'
import { IEditorOption } from '../../interface/Editor'
import { IElementPosition } from '../../interface/Element'
import { IElement, IElementPosition } from '../../interface/Element'
import { ICurrentPosition, IGetPositionByXYPayload, IPositionContext } from '../../interface/Position'
import { Draw } from '../draw/Draw'
import { EditorZone } from '../../dataset/enum/Editor'
export class Position {
@ -28,17 +29,30 @@ export class Position {
this.options = draw.getOptions()
}
public getOriginalPositionList(): IElementPosition[] {
return this.positionList
public getTablePositionList(sourceElementList: IElement[]): IElementPosition[] {
const { index, trIndex, tdIndex } = this.positionContext
return sourceElementList[index!].trList![trIndex!].tdList[tdIndex!].positionList || []
}
public getPositionList(): IElementPosition[] {
const { isTable } = this.positionContext
if (isTable) {
const { index, trIndex, tdIndex } = this.positionContext
const elementList = this.draw.getOriginalElementList()
return elementList[index!].trList![trIndex!].tdList[tdIndex!].positionList || []
}
return this.positionContext.isTable
? this.getTablePositionList(this.draw.getOriginalElementList())
: this.getOriginalPositionList()
}
public getMainPositionList(): IElementPosition[] {
return this.positionContext.isTable
? this.getTablePositionList(this.draw.getOriginalMainElementList())
: this.positionList
}
public getOriginalPositionList(): IElementPosition[] {
const zoneManager = this.draw.getZone()
const header = this.draw.getHeader()
return zoneManager.isHeaderActive() ? header.getPositionList() : this.positionList
}
public getOriginalMainPositionList(): IElementPosition[] {
return this.positionList
}
@ -46,7 +60,7 @@ export class Position {
this.positionList = payload
}
private computePageRowPosition(payload: IComputePageRowPositionPayload): IComputePageRowPositionResult {
public computePageRowPosition(payload: IComputePageRowPositionPayload): IComputePageRowPositionResult {
const { positionList, rowList, pageNo, startX, startY, startIndex, innerWidth } = payload
const { scale, tdPadding } = this.options
let x = startX
@ -130,7 +144,10 @@ export class Position {
const pageRowList = this.draw.getPageRowList()
const margins = this.draw.getMargins()
const startX = margins[3]
const startY = margins[0]
// 起始位置受页眉影响
const header = this.draw.getHeader()
const extraHeight = header.getExtraHeight()
const startY = margins[0] + extraHeight
for (let i = 0; i < pageRowList.length; i++) {
const rowList = pageRowList[i]
const startIndex = rowList[0].startIndex
@ -169,12 +186,14 @@ export class Position {
elementList = this.draw.getOriginalElementList()
}
if (!positionList) {
positionList = this.positionList
positionList = this.getOriginalPositionList()
}
const zoneManager = this.draw.getZone()
const curPageNo = this.draw.getPageNo()
const positionNo = zoneManager.isMainActive() ? curPageNo : 0
for (let j = 0; j < positionList.length; j++) {
const { index, pageNo, coordinate: { leftTop, rightTop, leftBottom } } = positionList[j]
if (curPageNo !== pageNo) continue
if (positionNo !== pageNo) continue
// 命中元素
if (leftTop[0] <= x && rightTop[0] >= x && leftTop[1] <= y && leftBottom[1] >= y) {
let curPositionIndex = j
@ -267,15 +286,15 @@ export class Position {
}
}
// 判断所属行是否存在元素
const firstLetterList = positionList.filter(p => p.isLastLetter && p.pageNo === curPageNo)
const firstLetterList = positionList.filter(p => p.isLastLetter && p.pageNo === positionNo)
for (let j = 0; j < firstLetterList.length; j++) {
const { index, pageNo, coordinate: { leftTop, leftBottom } } = firstLetterList[j]
if (curPageNo !== pageNo) continue
if (positionNo !== pageNo) continue
if (y > leftTop[1] && y <= leftBottom[1]) {
const isHead = x < this.options.margins[3]
// 是否在头部
if (isHead) {
const headIndex = positionList.findIndex(p => p.pageNo === curPageNo && p.rowNo === firstLetterList[j].rowNo)
const headIndex = positionList.findIndex(p => p.pageNo === positionNo && p.rowNo === firstLetterList[j].rowNo)
curPositionIndex = ~headIndex ? headIndex - 1 : index
} else {
curPositionIndex = index
@ -285,8 +304,28 @@ export class Position {
}
}
if (!isLastArea) {
// 判断所属位置是否属于header区域当前位置小于第一行的上边距
if (zoneManager.isMainActive()) {
if (y < firstLetterList[0].coordinate.leftTop[1]) {
return {
index: -1,
zone: EditorZone.HEADER
}
}
}
// 判断所属位置是否属于main区域当前位置大于第一行的上边距
if (zoneManager.isHeaderActive()) {
if (y > firstLetterList[0].coordinate.leftTop[1]) {
return {
index: -1,
zone: EditorZone.MAIN
}
}
}
// 当前页最后一行
return { index: firstLetterList[firstLetterList.length - 1]?.index || positionList.length - 1 }
return {
index: firstLetterList[firstLetterList.length - 1]?.index || positionList.length - 1,
}
}
return {
index: curPositionIndex,
@ -294,13 +333,10 @@ export class Position {
}
}
public adjustPositionContext(payload: Pick<IGetPositionByXYPayload, 'x' | 'y'>): ICurrentPosition {
public adjustPositionContext(payload: IGetPositionByXYPayload): ICurrentPosition | null {
const isReadonly = this.draw.isReadonly()
const { x, y } = payload
const positionResult = this.getPositionByXY({
x,
y
})
const positionResult = this.getPositionByXY(payload)
if (!~positionResult.index) return null
// 移动控件内光标
if (positionResult.isControl && !isReadonly) {
const {

@ -34,6 +34,10 @@ export class RangeManager {
return this.range
}
public clearRange() {
this.setRange(-1, -1)
}
public getSelection(): IElement[] | null {
const { startIndex, endIndex } = this.range
if (startIndex === endIndex) return null
@ -90,6 +94,7 @@ export class RangeManager {
this.range.startTrIndex = startTrIndex
this.range.endTrIndex = endTrIndex
this.range.isCrossRowCol = !!(startTdIndex || endTdIndex || startTrIndex || endTrIndex)
this.range.zone = this.draw.getZone().getZone()
// 激活控件
const control = this.draw.getControl()
if (~startIndex && ~endIndex) {

@ -0,0 +1,27 @@
import { EditorZone } from '../../dataset/enum/Editor'
export class Zone {
private currentZone: EditorZone
constructor() {
this.currentZone = EditorZone.MAIN
}
public isHeaderActive(): boolean {
return this.getZone() === EditorZone.HEADER
}
public isMainActive(): boolean {
return this.getZone() === EditorZone.MAIN
}
public getZone(): EditorZone {
return this.currentZone
}
public setZone(payload: EditorZone) {
this.currentZone = payload
}
}

@ -1,8 +1,13 @@
import { IHeader } from '../../interface/Header'
import { HeaderMaxHeightRatio } from '../enum/Header'
export const defaultHeaderOption: Readonly<Required<IHeader>> = {
data: '',
color: '#AAAAAA',
size: 14,
font: 'Yahei'
top: 30,
maxHeightRadio: HeaderMaxHeightRatio.HALF
}
export const maxHeightRadioMapping: Record<HeaderMaxHeightRatio, number> = {
[HeaderMaxHeightRatio.HALF]: 1 / 2,
[HeaderMaxHeightRatio.ONE_THIRD]: 1 / 3,
[HeaderMaxHeightRatio.QUARTER]: 1 / 4
}

@ -18,6 +18,12 @@ export enum EditorMode {
READONLY = 'readonly'
}
export enum EditorZone {
HEADER = 'header',
MAIN = 'main',
FOOTER = 'footer'
}
export enum PageMode {
PAGING = 'paging',
CONTINUITY = 'continuity'

@ -0,0 +1,5 @@
export enum HeaderMaxHeightRatio {
HALF = 'half',
ONE_THIRD = 'one-third',
QUARTER = 'quarter'
}

@ -1,5 +1,5 @@
import './assets/css/index.css'
import { IEditorOption, IEditorResult } from './interface/Editor'
import { IEditorData, IEditorOption, IEditorResult } from './interface/Editor'
import { IElement } from './interface/Element'
import { Draw } from './core/draw/Draw'
import { Command } from './core/command/Command'
@ -39,7 +39,7 @@ export default class Editor {
public register: Register
public destroy: Function
constructor(container: HTMLDivElement, elementList: IElement[], options: IEditorOption = {}) {
constructor(container: HTMLDivElement, data: IEditorData | IElement[], options: IEditorOption = {}) {
const headerOptions: Required<IHeader> = {
...defaultHeaderOption,
...options.header
@ -96,6 +96,7 @@ export default class Editor {
defaultHyperlinkColor: '#0000FF',
headerTop: 50,
paperDirection: PaperDirection.VERTICAL,
inactiveAlpha: 0.6,
...options,
header: headerOptions,
watermark: waterMarkOptions,
@ -103,13 +104,33 @@ export default class Editor {
checkbox: checkboxOptions,
cursor: cursorOptions
}
formatElementList(elementList, {
// 数据处理
let headerElementList: IElement[] = []
let mainElementList: IElement[] = []
if (Array.isArray(data)) {
mainElementList = data
} else {
headerElementList = data.header || []
mainElementList = data.main
}
formatElementList(headerElementList, {
editorOptions
})
formatElementList(mainElementList, {
editorOptions
})
// 监听
this.listener = new Listener()
// 启动
const draw = new Draw(container, editorOptions, elementList, this.listener)
const draw = new Draw(
container,
editorOptions,
{
header: headerElementList,
main: mainElementList
},
this.listener
)
// 命令
this.command = new Command(new CommandAdapt(draw))
// 菜单

@ -1,4 +1,5 @@
import { IElementPosition } from './Element'
import { EditorZone } from '../dataset/enum/Editor'
import { IElement, IElementPosition } from './Element'
import { IRow } from './Row'
export interface IDrawOption {
@ -16,11 +17,20 @@ export interface IDrawImagePayload {
}
export interface IDrawRowPayload {
elementList: IElement[];
positionList: IElementPosition[];
rowList: IRow[];
pageNo: number;
startIndex: number;
innerWidth: number;
zone: EditorZone;
}
export interface IDrawPagePayload {
elementList: IElement[];
positionList: IElementPosition[];
rowList: IRow[];
pageNo: number;
}
export interface IPainterOptions {

@ -7,6 +7,12 @@ import { IHeader } from './Header'
import { IMargin } from './Margin'
import { IWatermark } from './Watermark'
export interface IEditorData {
header?: IElement[];
main: IElement[];
footer?: IElement[];
}
export interface IEditorOption {
mode?: EditorMode;
defaultType?: string;
@ -42,6 +48,7 @@ export interface IEditorOption {
defaultHyperlinkColor?: string;
headerTop?: number;
paperDirection?: PaperDirection;
inactiveAlpha?: number;
header?: IHeader;
watermark?: IWatermark;
control?: IControlOption;
@ -54,7 +61,6 @@ export interface IEditorResult {
width: number;
height: number;
margins: IMargin;
header?: IHeader;
watermark?: IWatermark;
data: IElement[];
data: IEditorData;
}

@ -1,6 +1,6 @@
import { HeaderMaxHeightRatio } from '../dataset/enum/Header'
export interface IHeader {
data: string;
color?: string;
size?: number;
font?: string;
top?: number;
maxHeightRadio?: HeaderMaxHeightRatio;
}

@ -1,4 +1,5 @@
import { IElement } from '..'
import { EditorZone } from '../dataset/enum/Editor'
import { IElementPosition } from './Element'
import { IRow } from './Row'
import { ITd } from './table/Td'
@ -16,6 +17,7 @@ export interface ICurrentPosition {
tdId?: string;
trId?: string;
tableId?: string;
zone?: EditorZone;
}
export interface IGetPositionByXYPayload {

@ -1,3 +1,5 @@
import { EditorZone } from '../dataset/enum/Editor'
export interface IRange {
startIndex: number;
endIndex: number;
@ -7,6 +9,7 @@ export interface IRange {
endTdIndex?: number;
startTrIndex?: number;
endTrIndex?: number;
zone?: EditorZone;
}
export type RangeRowMap = Map<number, Set<number>>

@ -1,7 +1,7 @@
import { data, options } from './mock'
import './style.css'
import prism from 'prismjs'
import Editor, { BlockType, Command, ControlType, EditorMode, ElementType, IBlock, IElement, KeyMap, PageMode, PaperDirection } from './editor'
import Editor, { BlockType, Command, ControlType, EditorMode, ElementType, IBlock, IElement, KeyMap, PageMode, PaperDirection, RowFlex } from './editor'
import { Dialog } from './components/dialog/Dialog'
import { formatPrismToken } from './utils/prism'
import { Signature } from './components/signature/Signature'
@ -11,7 +11,25 @@ window.onload = function () {
// 1. 初始化编辑器
const container = document.querySelector<HTMLDivElement>('.editor')!
const instance = new Editor(container, <IElement[]>data, options)
const instance = new Editor(
container,
{
header: [{
value: '第一人民医院',
size: 32,
rowFlex: RowFlex.CENTER
}, {
value: '\n门诊病历',
size: 18,
rowFlex: RowFlex.CENTER
}, {
value: '\n',
type: ElementType.SEPARATOR
}],
main: <IElement[]>data
},
options
)
console.log('实例: ', instance)
// cypress使用
Reflect.set(window, 'editor', instance)

@ -1,13 +1,6 @@
import { ControlType, ElementType, IEditorOption, IElement, RowFlex } from './editor'
import { ControlType, ElementType, IEditorOption, IElement } from './editor'
const text = `人民医院门诊病历\n主诉\n发热三天咳嗽五天。\n现病史\n患者于三天前无明显诱因感冒后发现面部水肿无皮疹尿量减少出现乏力在外治疗无好转现来我院就诊。\n既往史\n有糖尿病10年有高血压2年有传染性疾病1年。报告其他既往疾病。\n流行病史\n否认14天内接触过确诊患者、疑似患者、无症状感染者及其密切接触者否认14天内去过以下场所水产、肉类批发市场农贸市场集市大型超市夜市否认14天内与以下场所工作人员密切接触水产、肉类批发市场农贸市场集市大型超市否认14天内周围如家庭、办公室有2例以上聚集性发病否认14天内接触过有发热或呼吸道症状的人员否认14天内自身有发热或呼吸道症状否认14天内接触过纳入隔离观察的人员及其他可能与新冠肺炎关联的情形陪同家属无以上情况。\n体格检查\nT39.5℃P80bpmR20次/分BP120/80mmHg\n辅助检查\n2020年6月10日普放血细胞比容36.50%偏低4050单核细胞绝对值0.75*10/L偏高参考值0.10.6\n门诊诊断\n1.高血压\n2.糖尿病\n3.病毒性感冒\n4.过敏性鼻炎\n5.过敏性鼻息肉\n处置治疗\n1.超声引导下甲状腺细针穿刺术;\n2.乙型肝炎表面抗体测定;\n3.膜式病变细胞采集术、后颈皮下肤层;\n电子签名【】\n其他记录`
// 模拟行居中
const centerText = ['人民医院门诊病历']
const centerIndex: number[] = centerText.map(c => {
const i = text.indexOf(c)
return ~i ? Array(c.length).fill(i).map((_, j) => i + j) : []
}).flat()
const text = `主诉:\n发热三天咳嗽五天。\n现病史\n患者于三天前无明显诱因感冒后发现面部水肿无皮疹尿量减少出现乏力在外治疗无好转现来我院就诊。\n既往史\n有糖尿病10年有高血压2年有传染性疾病1年。报告其他既往疾病。\n流行病史\n否认14天内接触过确诊患者、疑似患者、无症状感染者及其密切接触者否认14天内去过以下场所水产、肉类批发市场农贸市场集市大型超市夜市否认14天内与以下场所工作人员密切接触水产、肉类批发市场农贸市场集市大型超市否认14天内周围如家庭、办公室有2例以上聚集性发病否认14天内接触过有发热或呼吸道症状的人员否认14天内自身有发热或呼吸道症状否认14天内接触过纳入隔离观察的人员及其他可能与新冠肺炎关联的情形陪同家属无以上情况。\n体格检查\nT39.5℃P80bpmR20次/分BP120/80mmHg\n辅助检查\n2020年6月10日普放血细胞比容36.50%偏低4050单核细胞绝对值0.75*10/L偏高参考值0.10.6\n门诊诊断\n1.高血压\n2.糖尿病\n3.病毒性感冒\n4.过敏性鼻炎\n5.过敏性鼻息肉\n处置治疗\n1.超声引导下甲状腺细针穿刺术;\n2.乙型肝炎表面抗体测定;\n3.膜式病变细胞采集术、后颈皮下肤层;\n电子签名【】\n其他记录`
// 模拟加粗字
const boldText = ['主诉:', '现病史:', '既往史:', '流行病史:', '体格检查:', '辅助检查:', '门诊诊断:', '处置治疗:', '电子签名:', '其他记录:']
@ -32,13 +25,6 @@ const highlightIndex: number[] = highlightText.map(b => {
// 组合纯文本数据
const elementList: IElement[] = text.split('').map((value, index) => {
if (centerIndex.includes(index)) {
return {
value,
size: 32,
rowFlex: RowFlex.CENTER
}
}
if (boldIndex.includes(index)) {
return {
value,
@ -65,14 +51,8 @@ const elementList: IElement[] = text.split('').map((value, index) => {
}
})
// 模拟分隔符
elementList.splice(8, 0, {
value: '\n',
type: ElementType.SEPARATOR
})
// 模拟文本控件
elementList.splice(24, 0, {
elementList.splice(14, 0, {
type: ElementType.CONTROL,
value: '',
control: {
@ -85,7 +65,7 @@ elementList.splice(24, 0, {
})
// 模拟下拉控件
elementList.splice(112, 0, {
elementList.splice(102, 0, {
type: ElementType.CONTROL,
value: '',
control: {
@ -109,7 +89,7 @@ elementList.splice(112, 0, {
})
// 模拟超链接
elementList.splice(138, 0, {
elementList.splice(128, 0, {
type: ElementType.HYPERLINK,
value: '',
valueList: [{
@ -129,20 +109,20 @@ elementList.splice(138, 0, {
})
// 模拟下标
elementList.splice(371, 0, {
elementList.splice(361, 0, {
value: '∆',
color: '#FF0000',
type: ElementType.SUBSCRIPT
})
// 模拟上标
elementList.splice(459, 0, {
elementList.splice(449, 0, {
value: '9',
type: ElementType.SUPERSCRIPT
})
// 模拟图片
elementList.splice(585, 0, {
elementList.splice(575, 0, {
value: `data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFkAAAAgCAYAAAB5JtSmAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAQ0SURBVGhD7dhrUSNBFAVgvKACEVjAAhJQgAIUYAABGEAABvgfAdn6UnWou01PppOZhIXNj1P9vo9zH5PK1Waz2V5wWlxIPgMuJJ8Bi0h+fn7eXl9fb29ubrYPDw/dO/8DHh8fu/vB4kym4Orqaofb29vund8OSSbhemewSrugBMnG3vlvw9vb265yn56edmtz/t/f33+5C8MkixQSZSsl9UzLOHUmcwTYAN/Rpl5eXnY+pnIB0Xd3d7s5m3rvDsrkCGszNiQ7r/tr4v39fSc/uipOqRcqufTHBiO78GGdzG5xcLtIFmVde7L9NsvXRo9s84+Pj+79pUAwn5GcD1wIz5r+fYGeJdnjGiF9hwL7iWAcfX19/evtKVHJXrtN8Rf4A3TVczqhrut5i1mSZQgnIriSWtdzP2N+EvIhi3/GWqHWtWXuy2IYbheiKarJZIZknkxyrryc2Utrgal+9S8iScUXIx/3kcxfe/jotcuDezLFlIbARDrzHpytXdKnQr4xyc74Vu9YV5Ih2Q/tT7mDSEYw5ZU4wu3nJx64k/1z9umlUG0hah/JSbC6Jzi5exDJWoTHERoBxu8uf/pT1j3HDkUIJitjbRfRA/iwVzlgy1RCfSF5ili9xj7BUWKs9wJZ3MpditYu+lsc+/PRx53cVF9Pdg/syE9Hb6cS75PkmhUEUFofmTvLGEXKimHueJP9Y3swWQwGLUiA9xEbHKuvgs4pPe1+1myTAKlw81buJ8kigjAXKauXPLQPhEYgJSEYsgdTUR0BmTVgc6C359wcvKGnBrGO8dO5VlD1ZZ519nrBHvrwKVMCas9hgL0YUI2wV98fC4FqCWizzXyqF44A0ZKLHkilgvPs1zbiTuZIdZ414KvqGCKZYx4zple+MSrrJVncAyL02/TOqncJwVMglx5zI4QDZ5WPvBGEcNP+7TlEcqJIAQFGsIdQjmZt7MlYA5yiI3pOQTCQXUm2TuVmXgmewxDJQDgl6deJJoU5y7p9uwZagmu1mCvbNoOOBfkhOf6lRZjzPb8qRjBMMiUhM9GNMZQq5/oRXBP7Mlj/i12A7EMIaJGqDcl8I79+/N1xTvdINQ2TDAQSvI9Md479vdqCHKSFQKAfEmgBqCTDkjaSgOZXQkg2jy1ti0xApnBQJo/0obQRipeQXbN3CmxKGQch5xgki4Efghl/kFqzPD//2DnXIodIRpaoETaXxcmwGNO7N4I2Oyuc6b+xK/tL9IH3kY/E+r1JdST4yM+7VUiuJbuPZHBeHZcNvXtziMMV9mRuvUOX8Vg9IFjRx9dUYM3s2oJyNx9ahFfSWwyRHKHG3nmL2q/mojyFVAWnEdi2Hg7OBXwUCCKr1QEtoe0+/9jI3xqIiuF2QRD0zqcwpfQnge9TVSI4tWrNe79shj98F0xDC0N4bTUVF5LPgAvJJ8dm+wcP2iJuZNdC5QAAAABJRU5ErkJggg==`,
width: 89,
height: 32,
@ -312,9 +292,6 @@ export const data: IElement[] = elementList
export const options: IEditorOption = {
margins: [100, 120, 100, 120],
header: {
data: '人民医院门诊'
},
watermark: {
data: 'CANVAS-EDITOR',
size: 120

Loading…
Cancel
Save