feat:edit page header
This commit is contained in:
@@ -62,8 +62,9 @@ export class Cursor {
|
|||||||
// 设置光标代理
|
// 设置光标代理
|
||||||
const height = this.draw.getHeight()
|
const height = this.draw.getHeight()
|
||||||
const pageGap = this.draw.getPageGap()
|
const pageGap = this.draw.getPageGap()
|
||||||
const { metrics, coordinate: { leftTop, rightTop }, ascent, pageNo } = cursorPosition
|
const { metrics, coordinate: { leftTop, rightTop }, ascent } = cursorPosition
|
||||||
const preY = pageNo * (height + pageGap)
|
const curPageNo = this.draw.getPageNo()
|
||||||
|
const preY = curPageNo * (height + pageGap)
|
||||||
// 增加1/4字体大小
|
// 增加1/4字体大小
|
||||||
const offsetHeight = metrics.height / 4
|
const offsetHeight = metrics.height / 4
|
||||||
const cursorHeight = metrics.height + offsetHeight * 2
|
const cursorHeight = metrics.height + offsetHeight * 2
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
import { version } from '../../../../package.json'
|
import { version } from '../../../../package.json'
|
||||||
import { ZERO } from '../../dataset/constant/Common'
|
import { ZERO } from '../../dataset/constant/Common'
|
||||||
import { RowFlex } from '../../dataset/enum/Row'
|
import { RowFlex } from '../../dataset/enum/Row'
|
||||||
import { IDrawOption, IDrawRowPayload, IPainterOptions } from '../../interface/Draw'
|
import { IDrawOption, IDrawPagePayload, IDrawRowPayload, IPainterOptions } from '../../interface/Draw'
|
||||||
import { IEditorDrawData, IEditorOption, IEditorResult } from '../../interface/Editor'
|
import { IEditorData, IEditorOption, IEditorResult } from '../../interface/Editor'
|
||||||
import { IElement, IElementMetrics, IElementPosition, IElementFillRect, IElementStyle } from '../../interface/Element'
|
import { IElement, IElementMetrics, IElementFillRect, IElementStyle } 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 { Cursor } from '../cursor/Cursor'
|
import { Cursor } from '../cursor/Cursor'
|
||||||
@@ -35,7 +35,7 @@ import { SubscriptParticle } from './particle/Subscript'
|
|||||||
import { SeparatorParticle } from './particle/Separator'
|
import { SeparatorParticle } from './particle/Separator'
|
||||||
import { PageBreakParticle } from './particle/PageBreak'
|
import { PageBreakParticle } from './particle/PageBreak'
|
||||||
import { Watermark } from './frame/Watermark'
|
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 { Control } from './control/Control'
|
||||||
import { zipElementList } from '../../utils/element'
|
import { zipElementList } from '../../utils/element'
|
||||||
import { CheckboxParticle } from './particle/CheckboxParticle'
|
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 { EDITOR_COMPONENT, EDITOR_PREFIX } from '../../dataset/constant/Editor'
|
||||||
import { I18n } from '../i18n/I18n'
|
import { I18n } from '../i18n/I18n'
|
||||||
import { ImageObserver } from '../observer/ImageObserver'
|
import { ImageObserver } from '../observer/ImageObserver'
|
||||||
|
import { Zone } from '../zone/Zone'
|
||||||
|
|
||||||
export class Draw {
|
export class Draw {
|
||||||
|
|
||||||
@@ -61,6 +62,7 @@ export class Draw {
|
|||||||
private mode: EditorMode
|
private mode: EditorMode
|
||||||
private options: DeepRequired<IEditorOption>
|
private options: DeepRequired<IEditorOption>
|
||||||
private position: Position
|
private position: Position
|
||||||
|
private zone: Zone
|
||||||
private headerElementList: IElement[]
|
private headerElementList: IElement[]
|
||||||
private elementList: IElement[]
|
private elementList: IElement[]
|
||||||
private footerElementList: IElement[]
|
private footerElementList: IElement[]
|
||||||
@@ -112,7 +114,7 @@ export class Draw {
|
|||||||
constructor(
|
constructor(
|
||||||
rootContainer: HTMLElement,
|
rootContainer: HTMLElement,
|
||||||
options: DeepRequired<IEditorOption>,
|
options: DeepRequired<IEditorOption>,
|
||||||
data: IEditorDrawData,
|
data: IEditorData,
|
||||||
listener: Listener
|
listener: Listener
|
||||||
) {
|
) {
|
||||||
this.container = this._wrapContainer(rootContainer)
|
this.container = this._wrapContainer(rootContainer)
|
||||||
@@ -133,6 +135,7 @@ export class Draw {
|
|||||||
this.i18n = new I18n()
|
this.i18n = new I18n()
|
||||||
this.historyManager = new HistoryManager()
|
this.historyManager = new HistoryManager()
|
||||||
this.position = new Position(this)
|
this.position = new Position(this)
|
||||||
|
this.zone = new Zone()
|
||||||
this.range = new RangeManager(this)
|
this.range = new RangeManager(this)
|
||||||
this.margin = new Margin(this)
|
this.margin = new Margin(this)
|
||||||
this.background = new Background(this)
|
this.background = new Background(this)
|
||||||
@@ -212,6 +215,12 @@ export class Draw {
|
|||||||
return Math.floor(this.getOriginalHeight() * this.options.scale)
|
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 {
|
public getCanvasWidth(pageNo = -1): number {
|
||||||
const page = this.getPage(pageNo)
|
const page = this.getPage(pageNo)
|
||||||
return page.width
|
return page.width
|
||||||
@@ -343,6 +352,10 @@ export class Draw {
|
|||||||
return this.position
|
return this.position
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public getZone(): Zone {
|
||||||
|
return this.zone
|
||||||
|
}
|
||||||
|
|
||||||
public getRange(): RangeManager {
|
public getRange(): RangeManager {
|
||||||
return this.range
|
return this.range
|
||||||
}
|
}
|
||||||
@@ -351,12 +364,35 @@ export class Draw {
|
|||||||
return this.headerElementList
|
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[] {
|
public getElementList(): IElement[] {
|
||||||
const positionContext = this.position.getPositionContext()
|
const positionContext = this.position.getPositionContext()
|
||||||
if (positionContext.isTable) {
|
const elementList = this.getOriginalElementList()
|
||||||
const { index, trIndex, tdIndex } = positionContext
|
return positionContext.isTable
|
||||||
return this.elementList[index!].trList![trIndex!].tdList[tdIndex!].value
|
? 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
|
return this.elementList
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -406,10 +442,6 @@ export class Draw {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public getOriginalElementList() {
|
|
||||||
return this.elementList
|
|
||||||
}
|
|
||||||
|
|
||||||
public getCanvasEvent(): CanvasEvent {
|
public getCanvasEvent(): CanvasEvent {
|
||||||
return this.canvasEvent
|
return this.canvasEvent
|
||||||
}
|
}
|
||||||
@@ -434,6 +466,10 @@ export class Draw {
|
|||||||
return this.tableTool
|
return this.tableTool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public getHeader(): Header {
|
||||||
|
return this.header
|
||||||
|
}
|
||||||
|
|
||||||
public getHyperlinkParticle(): HyperlinkParticle {
|
public getHyperlinkParticle(): HyperlinkParticle {
|
||||||
return this.hyperlinkParticle
|
return this.hyperlinkParticle
|
||||||
}
|
}
|
||||||
@@ -610,7 +646,7 @@ export class Draw {
|
|||||||
// 配置
|
// 配置
|
||||||
const { width, height, margins, watermark } = this.options
|
const { width, height, margins, watermark } = this.options
|
||||||
// 数据
|
// 数据
|
||||||
const data: IEditorDrawData = {
|
const data: IEditorData = {
|
||||||
header: zipElementList(this.headerElementList),
|
header: zipElementList(this.headerElementList),
|
||||||
main: zipElementList(this.elementList)
|
main: zipElementList(this.elementList)
|
||||||
}
|
}
|
||||||
@@ -768,7 +804,7 @@ export class Draw {
|
|||||||
metrics.boundingBoxAscent = 0
|
metrics.boundingBoxAscent = 0
|
||||||
// 表格分页处理(拆分表格)
|
// 表格分页处理(拆分表格)
|
||||||
const margins = this.getMargins()
|
const margins = this.getMargins()
|
||||||
const height = this.getHeight()
|
const height = this.getOriginalMainHeight()
|
||||||
const marginHeight = margins[0] + margins[2]
|
const marginHeight = margins[0] + margins[2]
|
||||||
let curPagePreHeight = marginHeight
|
let curPagePreHeight = marginHeight
|
||||||
for (let r = 0; r < rowList.length; r++) {
|
for (let r = 0; r < rowList.length; r++) {
|
||||||
@@ -826,13 +862,13 @@ export class Draw {
|
|||||||
} else if (element.type === ElementType.SEPARATOR) {
|
} else if (element.type === ElementType.SEPARATOR) {
|
||||||
element.width = innerWidth
|
element.width = innerWidth
|
||||||
metrics.width = innerWidth
|
metrics.width = innerWidth
|
||||||
metrics.height = this.options.defaultSize
|
metrics.height = defaultSize
|
||||||
metrics.boundingBoxAscent = -rowMargin
|
metrics.boundingBoxAscent = -rowMargin
|
||||||
metrics.boundingBoxDescent = -rowMargin
|
metrics.boundingBoxDescent = -rowMargin
|
||||||
} else if (element.type === ElementType.PAGE_BREAK) {
|
} else if (element.type === ElementType.PAGE_BREAK) {
|
||||||
element.width = innerWidth
|
element.width = innerWidth
|
||||||
metrics.width = innerWidth
|
metrics.width = innerWidth
|
||||||
metrics.height = this.options.defaultSize
|
metrics.height = defaultSize
|
||||||
} else if (
|
} else if (
|
||||||
element.type === ElementType.CHECKBOX ||
|
element.type === ElementType.CHECKBOX ||
|
||||||
element.controlComponent === ControlComponent.CHECKBOX
|
element.controlComponent === ControlComponent.CHECKBOX
|
||||||
@@ -860,7 +896,7 @@ export class Draw {
|
|||||||
metrics.boundingBoxAscent = 0
|
metrics.boundingBoxAscent = 0
|
||||||
} else {
|
} else {
|
||||||
// 设置上下标真实字体尺寸
|
// 设置上下标真实字体尺寸
|
||||||
const size = element.size || this.options.defaultSize
|
const size = element.size || defaultSize
|
||||||
if (element.type === ElementType.SUPERSCRIPT || element.type === ElementType.SUBSCRIPT) {
|
if (element.type === ElementType.SUPERSCRIPT || element.type === ElementType.SUBSCRIPT) {
|
||||||
element.actualSize = Math.ceil(size * 0.6)
|
element.actualSize = Math.ceil(size * 0.6)
|
||||||
}
|
}
|
||||||
@@ -934,7 +970,7 @@ export class Draw {
|
|||||||
private _computePageList(): IRow[][] {
|
private _computePageList(): IRow[][] {
|
||||||
const pageRowList: IRow[][] = [[]]
|
const pageRowList: IRow[][] = [[]]
|
||||||
const { pageMode } = this.options
|
const { pageMode } = this.options
|
||||||
const height = this.getHeight()
|
const height = this.getOriginalMainHeight()
|
||||||
const margins = this.getMargins()
|
const margins = this.getMargins()
|
||||||
const marginHeight = margins[0] + margins[2]
|
const marginHeight = margins[0] + margins[2]
|
||||||
let pageHeight = marginHeight
|
let pageHeight = marginHeight
|
||||||
@@ -979,7 +1015,7 @@ export class Draw {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public drawRow(ctx: CanvasRenderingContext2D, payload: IDrawRowPayload) {
|
public drawRow(ctx: CanvasRenderingContext2D, payload: IDrawRowPayload) {
|
||||||
const { rowList, pageNo, positionList, startIndex } = payload
|
const { rowList, pageNo, elementList, positionList, startIndex, zone } = payload
|
||||||
const { scale, tdPadding } = this.options
|
const { scale, tdPadding } = this.options
|
||||||
const { isCrossRowCol, tableId } = this.range.getRange()
|
const { isCrossRowCol, tableId } = this.range.getRange()
|
||||||
let index = startIndex
|
let index = startIndex
|
||||||
@@ -1077,11 +1113,11 @@ export class Draw {
|
|||||||
this.highlight.render(ctx)
|
this.highlight.render(ctx)
|
||||||
}
|
}
|
||||||
// 选区记录
|
// 选区记录
|
||||||
const { startIndex, endIndex } = this.range.getRange()
|
const { zone: currentZone, startIndex, endIndex } = this.range.getRange()
|
||||||
if (startIndex !== endIndex && startIndex <= index && index <= endIndex) {
|
if (currentZone === zone && startIndex !== endIndex && startIndex <= index && index <= endIndex) {
|
||||||
// 从行尾开始-绘制最小宽度
|
// 从行尾开始-绘制最小宽度
|
||||||
if (startIndex === index) {
|
if (startIndex === index) {
|
||||||
const nextElement = this.elementList[startIndex + 1]
|
const nextElement = elementList[startIndex + 1]
|
||||||
if (nextElement && nextElement.value === ZERO) {
|
if (nextElement && nextElement.value === ZERO) {
|
||||||
rangeRecord.x = x + metrics.width
|
rangeRecord.x = x + metrics.width
|
||||||
rangeRecord.y = y
|
rangeRecord.y = y
|
||||||
@@ -1119,11 +1155,13 @@ export class Draw {
|
|||||||
for (let d = 0; d < tr.tdList!.length; d++) {
|
for (let d = 0; d < tr.tdList!.length; d++) {
|
||||||
const td = tr.tdList[d]
|
const td = tr.tdList[d]
|
||||||
this.drawRow(ctx, {
|
this.drawRow(ctx, {
|
||||||
|
elementList: td.value,
|
||||||
positionList: td.positionList!,
|
positionList: td.positionList!,
|
||||||
rowList: td.rowList!,
|
rowList: td.rowList!,
|
||||||
pageNo,
|
pageNo,
|
||||||
startIndex: 0,
|
startIndex: 0,
|
||||||
innerWidth: (td.width! - tdGap) * scale
|
innerWidth: (td.width! - tdGap) * scale,
|
||||||
|
zone
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1150,10 +1188,13 @@ export class Draw {
|
|||||||
this.blockParticle.clear()
|
this.blockParticle.clear()
|
||||||
}
|
}
|
||||||
|
|
||||||
private _drawPage(positionList: IElementPosition[], rowList: IRow[], pageNo: number) {
|
private _drawPage(payload: IDrawPagePayload) {
|
||||||
const { pageMode } = this.options
|
const { elementList, positionList, rowList, pageNo } = payload
|
||||||
|
const { inactiveAlpha, pageMode } = this.options
|
||||||
const innerWidth = this.getInnerWidth()
|
const innerWidth = this.getInnerWidth()
|
||||||
const ctx = this.ctxList[pageNo]
|
const ctx = this.ctxList[pageNo]
|
||||||
|
// 判断当前激活区域-激活页眉时主题元素透明度降低
|
||||||
|
ctx.globalAlpha = this.zone.isHeaderActive() ? inactiveAlpha : 1
|
||||||
this._clearPage(pageNo)
|
this._clearPage(pageNo)
|
||||||
// 绘制背景
|
// 绘制背景
|
||||||
this.background.render(ctx)
|
this.background.render(ctx)
|
||||||
@@ -1162,14 +1203,16 @@ export class Draw {
|
|||||||
// 渲染元素
|
// 渲染元素
|
||||||
const index = rowList[0].startIndex
|
const index = rowList[0].startIndex
|
||||||
this.drawRow(ctx, {
|
this.drawRow(ctx, {
|
||||||
|
elementList,
|
||||||
positionList,
|
positionList,
|
||||||
rowList,
|
rowList,
|
||||||
pageNo,
|
pageNo,
|
||||||
startIndex: index,
|
startIndex: index,
|
||||||
innerWidth
|
innerWidth,
|
||||||
|
zone: EditorZone.MAIN
|
||||||
})
|
})
|
||||||
// 绘制页眉
|
// 绘制页眉
|
||||||
this.header.render(ctx)
|
this.header.render(ctx, pageNo)
|
||||||
// 绘制页码
|
// 绘制页码
|
||||||
this.pageNumber.render(ctx, pageNo)
|
this.pageNumber.render(ctx, pageNo)
|
||||||
// 搜索匹配绘制
|
// 搜索匹配绘制
|
||||||
@@ -1183,14 +1226,20 @@ export class Draw {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private _lazyRender() {
|
private _lazyRender() {
|
||||||
const positionList = this.position.getOriginalPositionList()
|
const positionList = this.position.getOriginalMainPositionList()
|
||||||
|
const elementList = this.getOriginalMainElementList()
|
||||||
this.lazyRenderIntersectionObserver?.disconnect()
|
this.lazyRenderIntersectionObserver?.disconnect()
|
||||||
this.lazyRenderIntersectionObserver = new IntersectionObserver((entries) => {
|
this.lazyRenderIntersectionObserver = new IntersectionObserver((entries) => {
|
||||||
entries.forEach(entry => {
|
entries.forEach(entry => {
|
||||||
if (entry.isIntersecting) {
|
if (entry.isIntersecting) {
|
||||||
const index = Number((<HTMLCanvasElement>entry.target).dataset.index)
|
const index = Number((<HTMLCanvasElement>entry.target).dataset.index)
|
||||||
this.header.render(this.ctxList[index])
|
this.header.render(this.ctxList[index], index)
|
||||||
this._drawPage(positionList, this.pageRowList[index], index)
|
this._drawPage({
|
||||||
|
elementList,
|
||||||
|
positionList,
|
||||||
|
rowList: this.pageRowList[index],
|
||||||
|
pageNo: index
|
||||||
|
})
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@@ -1200,9 +1249,15 @@ export class Draw {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private _immediateRender() {
|
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++) {
|
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
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1236,7 +1291,6 @@ export class Draw {
|
|||||||
this.imageObserver.clearAll()
|
this.imageObserver.clearAll()
|
||||||
this.cursor.recoveryCursor()
|
this.cursor.recoveryCursor()
|
||||||
// 创建纸张
|
// 创建纸张
|
||||||
const positionList = this.position.getOriginalPositionList()
|
|
||||||
for (let i = 0; i < this.pageRowList.length; i++) {
|
for (let i = 0; i < this.pageRowList.length; i++) {
|
||||||
if (!this.pageList[i]) {
|
if (!this.pageList[i]) {
|
||||||
this._createPage(i)
|
this._createPage(i)
|
||||||
@@ -1260,20 +1314,19 @@ export class Draw {
|
|||||||
}
|
}
|
||||||
// 光标重绘
|
// 光标重绘
|
||||||
if (isSetCursor) {
|
if (isSetCursor) {
|
||||||
|
const positionList = this.position.getPositionList()
|
||||||
const positionContext = this.position.getPositionContext()
|
const positionContext = this.position.getPositionContext()
|
||||||
if (positionContext.isTable) {
|
if (positionContext.isTable) {
|
||||||
const { index, trIndex, tdIndex } = positionContext
|
const { index, trIndex, tdIndex } = positionContext
|
||||||
const tablePositionList = this.elementList[index!].trList?.[trIndex!].tdList[tdIndex!].positionList
|
const elementList = this.getElementList()
|
||||||
|
const tablePositionList = elementList[index!].trList?.[trIndex!].tdList[tdIndex!].positionList
|
||||||
if (curIndex === undefined && tablePositionList) {
|
if (curIndex === undefined && tablePositionList) {
|
||||||
curIndex = tablePositionList.length - 1
|
curIndex = tablePositionList.length - 1
|
||||||
}
|
}
|
||||||
const tablePosition = tablePositionList?.[curIndex!]
|
const tablePosition = tablePositionList?.[curIndex!]
|
||||||
this.position.setCursorPosition(tablePosition || null)
|
this.position.setCursorPosition(tablePosition || null)
|
||||||
} else {
|
} else {
|
||||||
if (curIndex === undefined) {
|
this.position.setCursorPosition(curIndex !== undefined ? positionList[curIndex] : null)
|
||||||
curIndex = positionList.length - 1
|
|
||||||
}
|
|
||||||
this.position.setCursorPosition(positionList[curIndex!] || null)
|
|
||||||
}
|
}
|
||||||
this.cursor.drawCursor()
|
this.cursor.drawCursor()
|
||||||
}
|
}
|
||||||
@@ -1281,12 +1334,16 @@ export class Draw {
|
|||||||
if (isSubmitHistory) {
|
if (isSubmitHistory) {
|
||||||
const self = this
|
const self = this
|
||||||
const oldElementList = deepClone(this.elementList)
|
const oldElementList = deepClone(this.elementList)
|
||||||
|
const oldHeaderElementList = deepClone(this.header.getElementList())
|
||||||
const { startIndex, endIndex } = this.range.getRange()
|
const { startIndex, endIndex } = this.range.getRange()
|
||||||
const pageNo = this.pageNo
|
const pageNo = this.pageNo
|
||||||
const oldPositionContext = deepClone(this.position.getPositionContext())
|
const oldPositionContext = deepClone(this.position.getPositionContext())
|
||||||
|
const zone = this.zone.getZone()
|
||||||
this.historyManager.execute(function () {
|
this.historyManager.execute(function () {
|
||||||
|
self.zone.setZone(zone)
|
||||||
self.setPageNo(pageNo)
|
self.setPageNo(pageNo)
|
||||||
self.position.setPositionContext(oldPositionContext)
|
self.position.setPositionContext(oldPositionContext)
|
||||||
|
self.header.setElementList(oldHeaderElementList)
|
||||||
self.elementList = deepClone(oldElementList)
|
self.elementList = deepClone(oldElementList)
|
||||||
self.range.setRange(startIndex, endIndex)
|
self.range.setRange(startIndex, endIndex)
|
||||||
self.render({ curIndex, isSubmitHistory: false })
|
self.render({ curIndex, isSubmitHistory: false })
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
import { maxHeightRadioMapping } from '../../../dataset/constant/Header'
|
||||||
|
import { EditorZone } from '../../../dataset/enum/Editor'
|
||||||
import { DeepRequired } from '../../../interface/Common'
|
import { DeepRequired } from '../../../interface/Common'
|
||||||
import { IEditorOption } from '../../../interface/Editor'
|
import { IEditorOption } from '../../../interface/Editor'
|
||||||
import { IElement, IElementPosition } from '../../../interface/Element'
|
import { IElement, IElementPosition } from '../../../interface/Element'
|
||||||
@@ -25,6 +27,18 @@ export class Header {
|
|||||||
this.positionList = []
|
this.positionList = []
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public setElementList(elementList: IElement[]) {
|
||||||
|
this.elementList = elementList
|
||||||
|
}
|
||||||
|
|
||||||
|
public getElementList(): IElement[] {
|
||||||
|
return this.elementList
|
||||||
|
}
|
||||||
|
|
||||||
|
public getPositionList(): IElementPosition[] {
|
||||||
|
return this.positionList
|
||||||
|
}
|
||||||
|
|
||||||
public compute() {
|
public compute() {
|
||||||
this._recovery()
|
this._recovery()
|
||||||
this._computeRowList()
|
this._computeRowList()
|
||||||
@@ -46,7 +60,7 @@ export class Header {
|
|||||||
const innerWidth = this.draw.getInnerWidth()
|
const innerWidth = this.draw.getInnerWidth()
|
||||||
const margins = this.draw.getMargins()
|
const margins = this.draw.getMargins()
|
||||||
const startX = margins[3]
|
const startX = margins[3]
|
||||||
const startY = margins[0] + top
|
const startY = top
|
||||||
this.position.computePageRowPosition({
|
this.position.computePageRowPosition({
|
||||||
positionList: this.positionList,
|
positionList: this.positionList,
|
||||||
rowList: this.rowList,
|
rowList: this.rowList,
|
||||||
@@ -58,14 +72,53 @@ export class Header {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
public render(ctx: CanvasRenderingContext2D) {
|
public getMaxHeight(): number {
|
||||||
|
const { header: { maxHeightRadio }, height } = this.options
|
||||||
|
return 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 rowHeight = this.getRowHeight()
|
||||||
|
const margins = this.draw.getOriginalMargins()
|
||||||
|
const extraHeight = headerTop + rowHeight - margins[0]
|
||||||
|
return extraHeight <= 0 ? 0 : extraHeight
|
||||||
|
}
|
||||||
|
|
||||||
|
public render(ctx: CanvasRenderingContext2D, pageNo: number) {
|
||||||
|
ctx.globalAlpha = 1
|
||||||
const innerWidth = this.draw.getInnerWidth()
|
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, {
|
this.draw.drawRow(ctx, {
|
||||||
|
elementList: this.elementList,
|
||||||
positionList: this.positionList,
|
positionList: this.positionList,
|
||||||
rowList: this.rowList,
|
rowList,
|
||||||
pageNo: 0,
|
pageNo,
|
||||||
startIndex: 0,
|
startIndex: 0,
|
||||||
innerWidth
|
innerWidth,
|
||||||
|
zone: EditorZone.HEADER
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -147,8 +147,8 @@ export class CanvasEvent {
|
|||||||
keydown(evt, this)
|
keydown(evt, this)
|
||||||
}
|
}
|
||||||
|
|
||||||
public dblclick() {
|
public dblclick(evt: MouseEvent) {
|
||||||
click.dblclick(this)
|
click.dblclick(this, evt)
|
||||||
}
|
}
|
||||||
|
|
||||||
public threeClick() {
|
public threeClick() {
|
||||||
|
|||||||
@@ -2,9 +2,25 @@ import { ZERO } from '../../../dataset/constant/Common'
|
|||||||
import { LETTER_REG, NUMBER_LIKE_REG } from '../../../dataset/constant/Regular'
|
import { LETTER_REG, NUMBER_LIKE_REG } from '../../../dataset/constant/Regular'
|
||||||
import { CanvasEvent } from '../CanvasEvent'
|
import { CanvasEvent } from '../CanvasEvent'
|
||||||
|
|
||||||
function dblclick(host: CanvasEvent) {
|
function dblclick(host: CanvasEvent, evt: MouseEvent) {
|
||||||
|
// 切换区域
|
||||||
const draw = host.getDraw()
|
const draw = host.getDraw()
|
||||||
const position = draw.getPosition()
|
const position = draw.getPosition()
|
||||||
|
const positionContext = position.getPositionByXY({
|
||||||
|
x: evt.offsetX,
|
||||||
|
y: evt.offsetY
|
||||||
|
})
|
||||||
|
if (!~positionContext.index && positionContext.zone) {
|
||||||
|
const zoneManager = draw.getZone()
|
||||||
|
zoneManager.setZone(positionContext.zone)
|
||||||
|
draw.render({
|
||||||
|
isSubmitHistory: false,
|
||||||
|
isSetCursor: false,
|
||||||
|
isCompute: false
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// 自动扩选文字
|
||||||
const cursorPosition = position.getCursorPosition()
|
const cursorPosition = position.getCursorPosition()
|
||||||
if (!cursorPosition) return
|
if (!cursorPosition) return
|
||||||
const { value, index } = cursorPosition
|
const { value, index } = cursorPosition
|
||||||
|
|||||||
@@ -21,10 +21,12 @@ function dragover(evt: DragEvent | MouseEvent, host: CanvasEvent) {
|
|||||||
draw.setPageNo(Number(pageIndex))
|
draw.setPageNo(Number(pageIndex))
|
||||||
}
|
}
|
||||||
const position = draw.getPosition()
|
const position = draw.getPosition()
|
||||||
const { isTable, tdValueIndex, index } = position.adjustPositionContext({
|
const positionContext = position.adjustPositionContext({
|
||||||
x: evt.offsetX,
|
x: evt.offsetX,
|
||||||
y: evt.offsetY
|
y: evt.offsetY
|
||||||
})
|
})
|
||||||
|
if (!positionContext) return
|
||||||
|
const { isTable, tdValueIndex, index } = positionContext
|
||||||
// 设置选区及光标位置
|
// 设置选区及光标位置
|
||||||
const positionList = position.getPositionList()
|
const positionList = position.getPositionList()
|
||||||
const curIndex = isTable ? tdValueIndex! : index
|
const curIndex = isTable ? tdValueIndex! : index
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ export function mousedown(evt: MouseEvent, host: CanvasEvent) {
|
|||||||
x: evt.offsetX,
|
x: evt.offsetX,
|
||||||
y: evt.offsetY
|
y: evt.offsetY
|
||||||
})
|
})
|
||||||
|
if (!positionResult) return
|
||||||
const {
|
const {
|
||||||
index,
|
index,
|
||||||
isDirectHit,
|
isDirectHit,
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ export function mousemove(evt: MouseEvent, host: CanvasEvent) {
|
|||||||
x: evt.offsetX,
|
x: evt.offsetX,
|
||||||
y: evt.offsetY
|
y: evt.offsetY
|
||||||
})
|
})
|
||||||
|
if (!~positionResult.index) return
|
||||||
const {
|
const {
|
||||||
index,
|
index,
|
||||||
isTable,
|
isTable,
|
||||||
|
|||||||
@@ -3,9 +3,10 @@ import { ZERO } from '../../dataset/constant/Common'
|
|||||||
import { ControlComponent, ImageDisplay } from '../../dataset/enum/Control'
|
import { ControlComponent, ImageDisplay } from '../../dataset/enum/Control'
|
||||||
import { IComputePageRowPositionPayload, IComputePageRowPositionResult } from '../../interface/Position'
|
import { IComputePageRowPositionPayload, IComputePageRowPositionResult } from '../../interface/Position'
|
||||||
import { IEditorOption } from '../../interface/Editor'
|
import { IEditorOption } from '../../interface/Editor'
|
||||||
import { IElementPosition } from '../../interface/Element'
|
import { IElement, IElementPosition } from '../../interface/Element'
|
||||||
import { ICurrentPosition, IGetPositionByXYPayload, IPositionContext } from '../../interface/Position'
|
import { ICurrentPosition, IGetPositionByXYPayload, IPositionContext } from '../../interface/Position'
|
||||||
import { Draw } from '../draw/Draw'
|
import { Draw } from '../draw/Draw'
|
||||||
|
import { EditorZone } from '../../dataset/enum/Editor'
|
||||||
|
|
||||||
export class Position {
|
export class Position {
|
||||||
|
|
||||||
@@ -28,17 +29,32 @@ export class Position {
|
|||||||
this.options = draw.getOptions()
|
this.options = draw.getOptions()
|
||||||
}
|
}
|
||||||
|
|
||||||
public getOriginalPositionList(): IElementPosition[] {
|
public getTablePositionList(sourceElementList: IElement[]): IElementPosition[] {
|
||||||
return this.positionList
|
const { index, trIndex, tdIndex } = this.positionContext
|
||||||
|
return sourceElementList[index!].trList![trIndex!].tdList[tdIndex!].positionList || []
|
||||||
}
|
}
|
||||||
|
|
||||||
public getPositionList(): IElementPosition[] {
|
public getPositionList(): IElementPosition[] {
|
||||||
const { isTable } = this.positionContext
|
const elementList = this.draw.getElementList()
|
||||||
if (isTable) {
|
return this.positionContext.isTable
|
||||||
const { index, trIndex, tdIndex } = this.positionContext
|
? this.getTablePositionList(elementList)
|
||||||
const elementList = this.draw.getOriginalElementList()
|
: this.getOriginalPositionList()
|
||||||
return elementList[index!].trList![trIndex!].tdList[tdIndex!].positionList || []
|
}
|
||||||
}
|
|
||||||
|
public getMainPositionList(): IElementPosition[] {
|
||||||
|
const elementList = this.draw.getMainElementList()
|
||||||
|
return this.positionContext.isTable
|
||||||
|
? this.getTablePositionList(elementList)
|
||||||
|
: 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
|
return this.positionList
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -130,7 +146,10 @@ export class Position {
|
|||||||
const pageRowList = this.draw.getPageRowList()
|
const pageRowList = this.draw.getPageRowList()
|
||||||
const margins = this.draw.getMargins()
|
const margins = this.draw.getMargins()
|
||||||
const startX = margins[3]
|
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++) {
|
for (let i = 0; i < pageRowList.length; i++) {
|
||||||
const rowList = pageRowList[i]
|
const rowList = pageRowList[i]
|
||||||
const startIndex = rowList[0].startIndex
|
const startIndex = rowList[0].startIndex
|
||||||
@@ -169,12 +188,14 @@ export class Position {
|
|||||||
elementList = this.draw.getOriginalElementList()
|
elementList = this.draw.getOriginalElementList()
|
||||||
}
|
}
|
||||||
if (!positionList) {
|
if (!positionList) {
|
||||||
positionList = this.positionList
|
positionList = this.getOriginalPositionList()
|
||||||
}
|
}
|
||||||
|
const zoneManager = this.draw.getZone()
|
||||||
const curPageNo = this.draw.getPageNo()
|
const curPageNo = this.draw.getPageNo()
|
||||||
|
const positionNo = zoneManager.isMainActive() ? curPageNo : 0
|
||||||
for (let j = 0; j < positionList.length; j++) {
|
for (let j = 0; j < positionList.length; j++) {
|
||||||
const { index, pageNo, coordinate: { leftTop, rightTop, leftBottom } } = positionList[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) {
|
if (leftTop[0] <= x && rightTop[0] >= x && leftTop[1] <= y && leftBottom[1] >= y) {
|
||||||
let curPositionIndex = j
|
let curPositionIndex = j
|
||||||
@@ -267,15 +288,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++) {
|
for (let j = 0; j < firstLetterList.length; j++) {
|
||||||
const { index, pageNo, coordinate: { leftTop, leftBottom } } = firstLetterList[j]
|
const { index, pageNo, coordinate: { leftTop, leftBottom } } = firstLetterList[j]
|
||||||
if (curPageNo !== pageNo) continue
|
if (positionNo !== pageNo) continue
|
||||||
if (y > leftTop[1] && y <= leftBottom[1]) {
|
if (y > leftTop[1] && y <= leftBottom[1]) {
|
||||||
const isHead = x < this.options.margins[3]
|
const isHead = x < this.options.margins[3]
|
||||||
// 是否在头部
|
// 是否在头部
|
||||||
if (isHead) {
|
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
|
curPositionIndex = ~headIndex ? headIndex - 1 : index
|
||||||
} else {
|
} else {
|
||||||
curPositionIndex = index
|
curPositionIndex = index
|
||||||
@@ -285,8 +306,28 @@ export class Position {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!isLastArea) {
|
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 {
|
return {
|
||||||
index: curPositionIndex,
|
index: curPositionIndex,
|
||||||
@@ -294,13 +335,10 @@ export class Position {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public adjustPositionContext(payload: Pick<IGetPositionByXYPayload, 'x' | 'y'>): ICurrentPosition {
|
public adjustPositionContext(payload: IGetPositionByXYPayload): ICurrentPosition | null {
|
||||||
const isReadonly = this.draw.isReadonly()
|
const isReadonly = this.draw.isReadonly()
|
||||||
const { x, y } = payload
|
const positionResult = this.getPositionByXY(payload)
|
||||||
const positionResult = this.getPositionByXY({
|
if (!~positionResult.index) return null
|
||||||
x,
|
|
||||||
y
|
|
||||||
})
|
|
||||||
// 移动控件内光标
|
// 移动控件内光标
|
||||||
if (positionResult.isControl && !isReadonly) {
|
if (positionResult.isControl && !isReadonly) {
|
||||||
const {
|
const {
|
||||||
|
|||||||
@@ -90,6 +90,7 @@ export class RangeManager {
|
|||||||
this.range.startTrIndex = startTrIndex
|
this.range.startTrIndex = startTrIndex
|
||||||
this.range.endTrIndex = endTrIndex
|
this.range.endTrIndex = endTrIndex
|
||||||
this.range.isCrossRowCol = !!(startTdIndex || endTdIndex || startTrIndex || endTrIndex)
|
this.range.isCrossRowCol = !!(startTdIndex || endTdIndex || startTrIndex || endTrIndex)
|
||||||
|
this.range.zone = this.draw.getZone().getZone()
|
||||||
// 激活控件
|
// 激活控件
|
||||||
const control = this.draw.getControl()
|
const control = this.draw.getControl()
|
||||||
if (~startIndex && ~endIndex) {
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -2,6 +2,12 @@ import { IHeader } from '../../interface/Header'
|
|||||||
import { HeaderMaxHeightRatio } from '../enum/Header'
|
import { HeaderMaxHeightRatio } from '../enum/Header'
|
||||||
|
|
||||||
export const defaultHeaderOption: Readonly<Required<IHeader>> = {
|
export const defaultHeaderOption: Readonly<Required<IHeader>> = {
|
||||||
top: -50,
|
top: 30,
|
||||||
maxHeightRadio: HeaderMaxHeightRatio.HALF
|
maxHeightRadio: HeaderMaxHeightRatio.HALF
|
||||||
|
}
|
||||||
|
|
||||||
|
export const maxHeightRadioMapping: Record<HeaderMaxHeightRatio, number> = {
|
||||||
|
[HeaderMaxHeightRatio.HALF]: 1 / 2,
|
||||||
|
[HeaderMaxHeightRatio.ONE_THIRD]: 1 / 3,
|
||||||
|
[HeaderMaxHeightRatio.QUARTER]: 1 / 4
|
||||||
}
|
}
|
||||||
+2
-1
@@ -39,7 +39,7 @@ export default class Editor {
|
|||||||
public register: Register
|
public register: Register
|
||||||
public destroy: Function
|
public destroy: Function
|
||||||
|
|
||||||
constructor(container: HTMLDivElement, data: IEditorData, options: IEditorOption = {}) {
|
constructor(container: HTMLDivElement, data: IEditorData | IElement[], options: IEditorOption = {}) {
|
||||||
const headerOptions: Required<IHeader> = {
|
const headerOptions: Required<IHeader> = {
|
||||||
...defaultHeaderOption,
|
...defaultHeaderOption,
|
||||||
...options.header
|
...options.header
|
||||||
@@ -96,6 +96,7 @@ export default class Editor {
|
|||||||
defaultHyperlinkColor: '#0000FF',
|
defaultHyperlinkColor: '#0000FF',
|
||||||
headerTop: 50,
|
headerTop: 50,
|
||||||
paperDirection: PaperDirection.VERTICAL,
|
paperDirection: PaperDirection.VERTICAL,
|
||||||
|
inactiveAlpha: 0.6,
|
||||||
...options,
|
...options,
|
||||||
header: headerOptions,
|
header: headerOptions,
|
||||||
watermark: waterMarkOptions,
|
watermark: waterMarkOptions,
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { IElementPosition } from './Element'
|
import { EditorZone } from '../dataset/enum/Editor'
|
||||||
|
import { IElement, IElementPosition } from './Element'
|
||||||
import { IRow } from './Row'
|
import { IRow } from './Row'
|
||||||
|
|
||||||
export interface IDrawOption {
|
export interface IDrawOption {
|
||||||
@@ -16,11 +17,20 @@ export interface IDrawImagePayload {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface IDrawRowPayload {
|
export interface IDrawRowPayload {
|
||||||
|
elementList: IElement[];
|
||||||
positionList: IElementPosition[];
|
positionList: IElementPosition[];
|
||||||
rowList: IRow[];
|
rowList: IRow[];
|
||||||
pageNo: number;
|
pageNo: number;
|
||||||
startIndex: number;
|
startIndex: number;
|
||||||
innerWidth: number;
|
innerWidth: number;
|
||||||
|
zone: EditorZone;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IDrawPagePayload {
|
||||||
|
elementList: IElement[];
|
||||||
|
positionList: IElementPosition[];
|
||||||
|
rowList: IRow[];
|
||||||
|
pageNo: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IPainterOptions {
|
export interface IPainterOptions {
|
||||||
|
|||||||
@@ -7,14 +7,12 @@ import { IHeader } from './Header'
|
|||||||
import { IMargin } from './Margin'
|
import { IMargin } from './Margin'
|
||||||
import { IWatermark } from './Watermark'
|
import { IWatermark } from './Watermark'
|
||||||
|
|
||||||
export interface IEditorDrawData {
|
export interface IEditorData {
|
||||||
header?: IElement[];
|
header?: IElement[];
|
||||||
main: IElement[];
|
main: IElement[];
|
||||||
footer?: IElement[];
|
footer?: IElement[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export type IEditorData = IEditorDrawData | IElement[]
|
|
||||||
|
|
||||||
export interface IEditorOption {
|
export interface IEditorOption {
|
||||||
mode?: EditorMode;
|
mode?: EditorMode;
|
||||||
defaultType?: string;
|
defaultType?: string;
|
||||||
@@ -50,6 +48,7 @@ export interface IEditorOption {
|
|||||||
defaultHyperlinkColor?: string;
|
defaultHyperlinkColor?: string;
|
||||||
headerTop?: number;
|
headerTop?: number;
|
||||||
paperDirection?: PaperDirection;
|
paperDirection?: PaperDirection;
|
||||||
|
inactiveAlpha?: number;
|
||||||
header?: IHeader;
|
header?: IHeader;
|
||||||
watermark?: IWatermark;
|
watermark?: IWatermark;
|
||||||
control?: IControlOption;
|
control?: IControlOption;
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { IElement } from '..'
|
import { IElement } from '..'
|
||||||
|
import { EditorZone } from '../dataset/enum/Editor'
|
||||||
import { IElementPosition } from './Element'
|
import { IElementPosition } from './Element'
|
||||||
import { IRow } from './Row'
|
import { IRow } from './Row'
|
||||||
import { ITd } from './table/Td'
|
import { ITd } from './table/Td'
|
||||||
@@ -16,6 +17,7 @@ export interface ICurrentPosition {
|
|||||||
tdId?: string;
|
tdId?: string;
|
||||||
trId?: string;
|
trId?: string;
|
||||||
tableId?: string;
|
tableId?: string;
|
||||||
|
zone?: EditorZone;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IGetPositionByXYPayload {
|
export interface IGetPositionByXYPayload {
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
import { EditorZone } from '../dataset/enum/Editor'
|
||||||
|
|
||||||
export interface IRange {
|
export interface IRange {
|
||||||
startIndex: number;
|
startIndex: number;
|
||||||
endIndex: number;
|
endIndex: number;
|
||||||
@@ -7,6 +9,7 @@ export interface IRange {
|
|||||||
endTdIndex?: number;
|
endTdIndex?: number;
|
||||||
startTrIndex?: number;
|
startTrIndex?: number;
|
||||||
endTrIndex?: number;
|
endTrIndex?: number;
|
||||||
|
zone?: EditorZone;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type RangeRowMap = Map<number, Set<number>>
|
export type RangeRowMap = Map<number, Set<number>>
|
||||||
|
|||||||
+9
-3
@@ -15,10 +15,16 @@ window.onload = function () {
|
|||||||
container,
|
container,
|
||||||
{
|
{
|
||||||
header: [{
|
header: [{
|
||||||
value: '人民医院门诊',
|
value: '第一人民医院',
|
||||||
size: 14,
|
size: 32,
|
||||||
color: '#AAAAAA',
|
|
||||||
rowFlex: RowFlex.CENTER
|
rowFlex: RowFlex.CENTER
|
||||||
|
}, {
|
||||||
|
value: '\n门诊病历',
|
||||||
|
size: 18,
|
||||||
|
rowFlex: RowFlex.CENTER
|
||||||
|
}, {
|
||||||
|
value: '\n',
|
||||||
|
type: ElementType.SEPARATOR
|
||||||
}],
|
}],
|
||||||
main: <IElement[]>data
|
main: <IElement[]>data
|
||||||
},
|
},
|
||||||
|
|||||||
+8
-28
@@ -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体格检查:\nT:39.5℃,P:80bpm,R:20次/分,BP:120/80mmHg;\n辅助检查:\n2020年6月10日,普放:血细胞比容36.50%(偏低)40~50;单核细胞绝对值0.75*10/L(偏高)参考值:0.1~0.6;\n门诊诊断:\n1.高血压\n2.糖尿病\n3.病毒性感冒\n4.过敏性鼻炎\n5.过敏性鼻息肉\n处置治疗:\n1.超声引导下甲状腺细针穿刺术;\n2.乙型肝炎表面抗体测定;\n3.膜式病变细胞采集术、后颈皮下肤层;\n电子签名:【】\n其他记录:`
|
const text = `主诉:\n发热三天,咳嗽五天。\n现病史:\n患者于三天前无明显诱因,感冒后发现面部水肿,无皮疹,尿量减少,出现乏力,在外治疗无好转,现来我院就诊。\n既往史:\n有糖尿病10年,有高血压2年,有传染性疾病1年。报告其他既往疾病。\n流行病史:\n否认14天内接触过确诊患者、疑似患者、无症状感染者及其密切接触者;否认14天内去过以下场所:水产、肉类批发市场,农贸市场,集市,大型超市,夜市;否认14天内与以下场所工作人员密切接触:水产、肉类批发市场,农贸市场,集市,大型超市;否认14天内周围(如家庭、办公室)有2例以上聚集性发病;否认14天内接触过有发热或呼吸道症状的人员;否认14天内自身有发热或呼吸道症状;否认14天内接触过纳入隔离观察的人员及其他可能与新冠肺炎关联的情形;陪同家属无以上情况。\n体格检查:\nT:39.5℃,P:80bpm,R:20次/分,BP:120/80mmHg;\n辅助检查:\n2020年6月10日,普放:血细胞比容36.50%(偏低)40~50;单核细胞绝对值0.75*10/L(偏高)参考值:0.1~0.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 boldText = ['主诉:', '现病史:', '既往史:', '流行病史:', '体格检查:', '辅助检查:', '门诊诊断:', '处置治疗:', '电子签名:', '其他记录:']
|
const boldText = ['主诉:', '现病史:', '既往史:', '流行病史:', '体格检查:', '辅助检查:', '门诊诊断:', '处置治疗:', '电子签名:', '其他记录:']
|
||||||
@@ -32,13 +25,6 @@ const highlightIndex: number[] = highlightText.map(b => {
|
|||||||
|
|
||||||
// 组合纯文本数据
|
// 组合纯文本数据
|
||||||
const elementList: IElement[] = text.split('').map((value, index) => {
|
const elementList: IElement[] = text.split('').map((value, index) => {
|
||||||
if (centerIndex.includes(index)) {
|
|
||||||
return {
|
|
||||||
value,
|
|
||||||
size: 32,
|
|
||||||
rowFlex: RowFlex.CENTER
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (boldIndex.includes(index)) {
|
if (boldIndex.includes(index)) {
|
||||||
return {
|
return {
|
||||||
value,
|
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,
|
type: ElementType.CONTROL,
|
||||||
value: '',
|
value: '',
|
||||||
control: {
|
control: {
|
||||||
@@ -85,7 +65,7 @@ elementList.splice(24, 0, {
|
|||||||
})
|
})
|
||||||
|
|
||||||
// 模拟下拉控件
|
// 模拟下拉控件
|
||||||
elementList.splice(112, 0, {
|
elementList.splice(102, 0, {
|
||||||
type: ElementType.CONTROL,
|
type: ElementType.CONTROL,
|
||||||
value: '',
|
value: '',
|
||||||
control: {
|
control: {
|
||||||
@@ -109,7 +89,7 @@ elementList.splice(112, 0, {
|
|||||||
})
|
})
|
||||||
|
|
||||||
// 模拟超链接
|
// 模拟超链接
|
||||||
elementList.splice(138, 0, {
|
elementList.splice(128, 0, {
|
||||||
type: ElementType.HYPERLINK,
|
type: ElementType.HYPERLINK,
|
||||||
value: '',
|
value: '',
|
||||||
valueList: [{
|
valueList: [{
|
||||||
@@ -129,20 +109,20 @@ elementList.splice(138, 0, {
|
|||||||
})
|
})
|
||||||
|
|
||||||
// 模拟下标
|
// 模拟下标
|
||||||
elementList.splice(371, 0, {
|
elementList.splice(361, 0, {
|
||||||
value: '∆',
|
value: '∆',
|
||||||
color: '#FF0000',
|
color: '#FF0000',
|
||||||
type: ElementType.SUBSCRIPT
|
type: ElementType.SUBSCRIPT
|
||||||
})
|
})
|
||||||
|
|
||||||
// 模拟上标
|
// 模拟上标
|
||||||
elementList.splice(459, 0, {
|
elementList.splice(449, 0, {
|
||||||
value: '9',
|
value: '9',
|
||||||
type: ElementType.SUPERSCRIPT
|
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==`,
|
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,
|
width: 89,
|
||||||
height: 32,
|
height: 32,
|
||||||
|
|||||||
Reference in New Issue
Block a user