feat: add print mode #236
This commit is contained in:
@@ -34,7 +34,7 @@ Feature: Gets the base64 string of the current page image
|
|||||||
Usage:
|
Usage:
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
const base64StringList = await instance.command.getImage(pixelRatio?: number)
|
const base64StringList = await instance.command.getImage(option?: IGetImageOption)
|
||||||
```
|
```
|
||||||
|
|
||||||
## getWordCount
|
## getWordCount
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ new Editor(container, IEditorData | IElement[], {
|
|||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
interface IEditorOption {
|
interface IEditorOption {
|
||||||
mode?: EditorMode // Editor mode: Edit, Clean (Visual aids are not displayed, For example: page break), ReadOnly, Form (Only editable within the control). default: Edit
|
mode?: EditorMode // Editor mode: Edit, Clean (Visual aids are not displayed, For example: page break), ReadOnly, Form (Only editable within the control), Print (Visual aids are not displayed, Unwritten content control). default: Edit
|
||||||
defaultType?: string // Default element type. default: TEXT
|
defaultType?: string // Default element type. default: TEXT
|
||||||
defaultFont?: string // Default font. default: Yahei
|
defaultFont?: string // Default font. default: Yahei
|
||||||
defaultSize?: number // Default font size. default: 16
|
defaultSize?: number // Default font size. default: 16
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ const {
|
|||||||
用法:
|
用法:
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
const base64StringList = await instance.command.getImage(pixelRatio?: number)
|
const base64StringList = await instance.command.getImage(option?: IGetImageOption)
|
||||||
```
|
```
|
||||||
|
|
||||||
## getWordCount
|
## getWordCount
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ new Editor(container, IEditorData | IElement[], {
|
|||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
interface IEditorOption {
|
interface IEditorOption {
|
||||||
mode?: EditorMode // 编辑器模式:编辑、清洁(不显示视觉辅助元素。如:分页符)、只读、表单(仅控件内可编辑)。默认:编辑
|
mode?: EditorMode // 编辑器模式:编辑、清洁(不显示视觉辅助元素。如:分页符)、只读、表单(仅控件内可编辑)、打印(不显示辅助元素、未书写控件及前后括号)。默认:编辑
|
||||||
defaultType?: string // 默认元素类型。默认:TEXT
|
defaultType?: string // 默认元素类型。默认:TEXT
|
||||||
defaultFont?: string // 默认字体。默认:Yahei
|
defaultFont?: string // 默认字体。默认:Yahei
|
||||||
defaultSize?: number // 默认字号。默认:16
|
defaultSize?: number // 默认字号。默认:16
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ import { DeepRequired } from '../../interface/Common'
|
|||||||
import {
|
import {
|
||||||
IAppendElementListOption,
|
IAppendElementListOption,
|
||||||
IDrawImagePayload,
|
IDrawImagePayload,
|
||||||
|
IGetImageOption,
|
||||||
IGetValueOption,
|
IGetValueOption,
|
||||||
IPainterOption
|
IPainterOption
|
||||||
} from '../../interface/Draw'
|
} from '../../interface/Draw'
|
||||||
@@ -86,13 +87,7 @@ export class CommandAdapt {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public mode(payload: EditorMode) {
|
public mode(payload: EditorMode) {
|
||||||
const mode = this.draw.getMode()
|
|
||||||
if (mode === payload) return
|
|
||||||
this.draw.setMode(payload)
|
this.draw.setMode(payload)
|
||||||
this.draw.render({
|
|
||||||
isSetCursor: false,
|
|
||||||
isSubmitHistory: false
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public cut() {
|
public cut() {
|
||||||
@@ -1648,7 +1643,10 @@ export class CommandAdapt {
|
|||||||
}
|
}
|
||||||
const width = this.draw.getOriginalWidth()
|
const width = this.draw.getOriginalWidth()
|
||||||
const height = this.draw.getOriginalHeight()
|
const height = this.draw.getOriginalHeight()
|
||||||
const base64List = await this.draw.getDataURL(printPixelRatio)
|
const base64List = await this.draw.getDataURL({
|
||||||
|
pixelRatio: printPixelRatio,
|
||||||
|
mode: EditorMode.PRINT
|
||||||
|
})
|
||||||
printImageBase64(base64List, width, height)
|
printImageBase64(base64List, width, height)
|
||||||
if (scale !== 1) {
|
if (scale !== 1) {
|
||||||
this.draw.setPageScale(scale)
|
this.draw.setPageScale(scale)
|
||||||
@@ -1685,8 +1683,8 @@ export class CommandAdapt {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
public getImage(pixelRatio?: number): Promise<string[]> {
|
public getImage(payload?: IGetImageOption): Promise<string[]> {
|
||||||
return this.draw.getDataURL(pixelRatio)
|
return this.draw.getDataURL(payload)
|
||||||
}
|
}
|
||||||
|
|
||||||
public getValue(options?: IGetValueOption): IEditorResult {
|
public getValue(options?: IGetValueOption): IEditorResult {
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import {
|
|||||||
IDrawOption,
|
IDrawOption,
|
||||||
IDrawPagePayload,
|
IDrawPagePayload,
|
||||||
IDrawRowPayload,
|
IDrawRowPayload,
|
||||||
|
IGetImageOption,
|
||||||
IGetValueOption,
|
IGetValueOption,
|
||||||
IPainterOption
|
IPainterOption
|
||||||
} from '../../interface/Draw'
|
} from '../../interface/Draw'
|
||||||
@@ -142,6 +143,7 @@ export class Draw {
|
|||||||
private visiblePageNoList: number[]
|
private visiblePageNoList: number[]
|
||||||
private intersectionPageNo: number
|
private intersectionPageNo: number
|
||||||
private lazyRenderIntersectionObserver: IntersectionObserver | null
|
private lazyRenderIntersectionObserver: IntersectionObserver | null
|
||||||
|
private printModeData: Required<IEditorData> | null
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
rootContainer: HTMLElement,
|
rootContainer: HTMLElement,
|
||||||
@@ -217,6 +219,7 @@ export class Draw {
|
|||||||
this.visiblePageNoList = []
|
this.visiblePageNoList = []
|
||||||
this.intersectionPageNo = 0
|
this.intersectionPageNo = 0
|
||||||
this.lazyRenderIntersectionObserver = null
|
this.lazyRenderIntersectionObserver = null
|
||||||
|
this.printModeData = null
|
||||||
|
|
||||||
this.render({
|
this.render({
|
||||||
isInit: true,
|
isInit: true,
|
||||||
@@ -229,12 +232,34 @@ export class Draw {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public setMode(payload: EditorMode) {
|
public setMode(payload: EditorMode) {
|
||||||
|
if (this.mode === payload) return
|
||||||
|
// 设置打印模式
|
||||||
|
if (payload === EditorMode.PRINT) {
|
||||||
|
this.printModeData = {
|
||||||
|
header: this.header.getElementList(),
|
||||||
|
main: this.elementList,
|
||||||
|
footer: this.footer.getElementList()
|
||||||
|
}
|
||||||
|
this.setEditorData(
|
||||||
|
this.control.filterAssistElement(deepClone(this.printModeData))
|
||||||
|
)
|
||||||
|
}
|
||||||
|
// 取消打印模式
|
||||||
|
if (this.mode === EditorMode.PRINT && this.printModeData) {
|
||||||
|
this.setEditorData(this.printModeData)
|
||||||
|
this.printModeData = null
|
||||||
|
}
|
||||||
this.mode = payload
|
this.mode = payload
|
||||||
|
this.render({
|
||||||
|
isSetCursor: false,
|
||||||
|
isSubmitHistory: false
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
public isReadonly() {
|
public isReadonly() {
|
||||||
switch (this.mode) {
|
switch (this.mode) {
|
||||||
case EditorMode.READONLY:
|
case EditorMode.READONLY:
|
||||||
|
case EditorMode.PRINT:
|
||||||
return true
|
return true
|
||||||
case EditorMode.FORM:
|
case EditorMode.FORM:
|
||||||
return !this.control.isRangeWithinControl()
|
return !this.control.isRangeWithinControl()
|
||||||
@@ -650,10 +675,18 @@ export class Draw {
|
|||||||
return this.rowList.length
|
return this.rowList.length
|
||||||
}
|
}
|
||||||
|
|
||||||
public async getDataURL(pixelRatio?: number): Promise<string[]> {
|
public async getDataURL(payload: IGetImageOption = {}): Promise<string[]> {
|
||||||
|
const { pixelRatio, mode } = payload
|
||||||
|
// 放大像素比
|
||||||
if (pixelRatio) {
|
if (pixelRatio) {
|
||||||
this.setPagePixelRatio(pixelRatio)
|
this.setPagePixelRatio(pixelRatio)
|
||||||
}
|
}
|
||||||
|
// 不同模式
|
||||||
|
const currentMode = this.mode
|
||||||
|
const isSwitchMode = !!mode && currentMode !== mode
|
||||||
|
if (isSwitchMode) {
|
||||||
|
this.setMode(mode)
|
||||||
|
}
|
||||||
this.render({
|
this.render({
|
||||||
isLazy: false,
|
isLazy: false,
|
||||||
isCompute: false,
|
isCompute: false,
|
||||||
@@ -662,9 +695,13 @@ export class Draw {
|
|||||||
})
|
})
|
||||||
await this.imageObserver.allSettled()
|
await this.imageObserver.allSettled()
|
||||||
const dataUrlList = this.pageList.map(c => c.toDataURL())
|
const dataUrlList = this.pageList.map(c => c.toDataURL())
|
||||||
|
// 还原
|
||||||
if (pixelRatio) {
|
if (pixelRatio) {
|
||||||
this.setPagePixelRatio(null)
|
this.setPagePixelRatio(null)
|
||||||
}
|
}
|
||||||
|
if (isSwitchMode) {
|
||||||
|
this.setMode(currentMode)
|
||||||
|
}
|
||||||
return dataUrlList
|
return dataUrlList
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -869,24 +906,18 @@ export class Draw {
|
|||||||
public setValue(payload: Partial<IEditorData>) {
|
public setValue(payload: Partial<IEditorData>) {
|
||||||
const { header, main, footer } = payload
|
const { header, main, footer } = payload
|
||||||
if (!header && !main && !footer) return
|
if (!header && !main && !footer) return
|
||||||
if (header) {
|
const pageComponentData = [header, main, footer]
|
||||||
formatElementList(header, {
|
pageComponentData.forEach(data => {
|
||||||
|
if (!data) return
|
||||||
|
formatElementList(data, {
|
||||||
editorOptions: this.options
|
editorOptions: this.options
|
||||||
})
|
})
|
||||||
this.header.setElementList(header)
|
})
|
||||||
}
|
this.setEditorData({
|
||||||
if (main) {
|
header,
|
||||||
formatElementList(main, {
|
main,
|
||||||
editorOptions: this.options
|
footer
|
||||||
})
|
})
|
||||||
this.elementList = main
|
|
||||||
}
|
|
||||||
if (footer) {
|
|
||||||
formatElementList(footer, {
|
|
||||||
editorOptions: this.options
|
|
||||||
})
|
|
||||||
this.footer.setElementList(footer)
|
|
||||||
}
|
|
||||||
// 渲染&计算&清空历史记录
|
// 渲染&计算&清空历史记录
|
||||||
this.historyManager.recovery()
|
this.historyManager.recovery()
|
||||||
this.render({
|
this.render({
|
||||||
@@ -894,6 +925,19 @@ export class Draw {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public setEditorData(payload: Partial<IEditorData>) {
|
||||||
|
const { header, main, footer } = payload
|
||||||
|
if (header) {
|
||||||
|
this.header.setElementList(header)
|
||||||
|
}
|
||||||
|
if (main) {
|
||||||
|
this.elementList = main
|
||||||
|
}
|
||||||
|
if (footer) {
|
||||||
|
this.footer.setElementList(footer)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private _wrapContainer(rootContainer: HTMLElement): HTMLDivElement {
|
private _wrapContainer(rootContainer: HTMLElement): HTMLDivElement {
|
||||||
const container = document.createElement('div')
|
const container = document.createElement('div')
|
||||||
rootContainer.append(container)
|
rootContainer.append(container)
|
||||||
@@ -1398,6 +1442,7 @@ export class Draw {
|
|||||||
public drawRow(ctx: CanvasRenderingContext2D, payload: IDrawRowPayload) {
|
public drawRow(ctx: CanvasRenderingContext2D, payload: IDrawRowPayload) {
|
||||||
const { rowList, pageNo, elementList, positionList, startIndex, zone } =
|
const { rowList, pageNo, elementList, positionList, startIndex, zone } =
|
||||||
payload
|
payload
|
||||||
|
const isPrintMode = this.mode === EditorMode.PRINT
|
||||||
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
|
||||||
@@ -1472,7 +1517,7 @@ export class Draw {
|
|||||||
} else if (element.type === ElementType.SEPARATOR) {
|
} else if (element.type === ElementType.SEPARATOR) {
|
||||||
this.separatorParticle.render(ctx, element, x, y)
|
this.separatorParticle.render(ctx, element, x, y)
|
||||||
} else if (element.type === ElementType.PAGE_BREAK) {
|
} else if (element.type === ElementType.PAGE_BREAK) {
|
||||||
if (this.mode !== EditorMode.CLEAN) {
|
if (this.mode !== EditorMode.CLEAN && !isPrintMode) {
|
||||||
this.pageBreakParticle.render(ctx, element, x, y)
|
this.pageBreakParticle.render(ctx, element, x, y)
|
||||||
}
|
}
|
||||||
} else if (
|
} else if (
|
||||||
@@ -1592,21 +1637,23 @@ export class Draw {
|
|||||||
// 绘制富文本及文字
|
// 绘制富文本及文字
|
||||||
this._drawRichText(ctx)
|
this._drawRichText(ctx)
|
||||||
// 绘制选区
|
// 绘制选区
|
||||||
if (rangeRecord.width && rangeRecord.height) {
|
if (!isPrintMode) {
|
||||||
const { x, y, width, height } = rangeRecord
|
if (rangeRecord.width && rangeRecord.height) {
|
||||||
this.range.render(ctx, x, y, width, height)
|
const { x, y, width, height } = rangeRecord
|
||||||
}
|
this.range.render(ctx, x, y, width, height)
|
||||||
if (
|
}
|
||||||
isCrossRowCol &&
|
if (
|
||||||
tableRangeElement &&
|
isCrossRowCol &&
|
||||||
tableRangeElement.id === tableId
|
tableRangeElement &&
|
||||||
) {
|
tableRangeElement.id === tableId
|
||||||
const {
|
) {
|
||||||
coordinate: {
|
const {
|
||||||
leftTop: [x, y]
|
coordinate: {
|
||||||
}
|
leftTop: [x, y]
|
||||||
} = positionList[curRow.startIndex]
|
}
|
||||||
this.tableParticle.drawRange(ctx, tableRangeElement, x, y)
|
} = positionList[curRow.startIndex]
|
||||||
|
this.tableParticle.drawRange(ctx, tableRangeElement, x, y)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import {
|
|||||||
IControlInstance,
|
IControlInstance,
|
||||||
IControlOption
|
IControlOption
|
||||||
} from '../../../interface/Control'
|
} from '../../../interface/Control'
|
||||||
|
import { IEditorData } from '../../../interface/Editor'
|
||||||
import { IElement, IElementPosition } from '../../../interface/Element'
|
import { IElement, IElementPosition } from '../../../interface/Element'
|
||||||
import { EventBusMap } from '../../../interface/EventBus'
|
import { EventBusMap } from '../../../interface/EventBus'
|
||||||
import { IRange } from '../../../interface/Range'
|
import { IRange } from '../../../interface/Range'
|
||||||
@@ -49,6 +50,24 @@ export class Control {
|
|||||||
return this.draw
|
return this.draw
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 过滤控件辅助元素(前后缀、背景提示)
|
||||||
|
public filterAssistElement(
|
||||||
|
payload: Required<IEditorData>
|
||||||
|
): Required<IEditorData> {
|
||||||
|
const editorDataKeys: (keyof IEditorData)[] = ['header', 'main', 'footer']
|
||||||
|
editorDataKeys.forEach(key => {
|
||||||
|
payload[key] = payload[key].filter(element => {
|
||||||
|
if (element.type !== ElementType.CONTROL) return true
|
||||||
|
return (
|
||||||
|
element.controlComponent !== ControlComponent.PREFIX &&
|
||||||
|
element.controlComponent !== ControlComponent.POSTFIX &&
|
||||||
|
element.controlComponent !== ControlComponent.PLACEHOLDER
|
||||||
|
)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
return payload
|
||||||
|
}
|
||||||
|
|
||||||
// 判断选区部分在控件边界外
|
// 判断选区部分在控件边界外
|
||||||
public isPartRangeInControlOutside(): boolean {
|
public isPartRangeInControlOutside(): boolean {
|
||||||
const { startIndex, endIndex } = this.getRange()
|
const { startIndex, endIndex } = this.getRange()
|
||||||
|
|||||||
@@ -14,10 +14,11 @@ export enum EditorContext {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export enum EditorMode {
|
export enum EditorMode {
|
||||||
EDIT = 'edit',
|
EDIT = 'edit', // 编辑模式(文档可编辑、辅助元素均存在)
|
||||||
CLEAN = 'clean',
|
CLEAN = 'clean', // 清洁模式(隐藏辅助元素)
|
||||||
READONLY = 'readonly',
|
READONLY = 'readonly', // 只读模式(文档不可编辑)
|
||||||
FORM = 'form'
|
FORM = 'form', // 表单模式(仅控件内可编辑)
|
||||||
|
PRINT = 'print' // 打印模式(文档不可编辑、隐藏辅助元素、选区、未书写控件及边框)
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum EditorZone {
|
export enum EditorZone {
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { EditorZone } from '../dataset/enum/Editor'
|
import { EditorMode, EditorZone } from '../dataset/enum/Editor'
|
||||||
import { IElement, IElementPosition } from './Element'
|
import { IElement, IElementPosition } from './Element'
|
||||||
import { IRow } from './Row'
|
import { IRow } from './Row'
|
||||||
|
|
||||||
@@ -45,3 +45,8 @@ export interface IGetValueOption {
|
|||||||
export interface IAppendElementListOption {
|
export interface IAppendElementListOption {
|
||||||
isPrepend?: boolean
|
isPrepend?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface IGetImageOption {
|
||||||
|
pixelRatio?: number
|
||||||
|
mode?: EditorMode
|
||||||
|
}
|
||||||
|
|||||||
@@ -1208,6 +1208,10 @@ window.onload = function () {
|
|||||||
{
|
{
|
||||||
mode: EditorMode.FORM,
|
mode: EditorMode.FORM,
|
||||||
name: '表单模式'
|
name: '表单模式'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
mode: EditorMode.PRINT,
|
||||||
|
name: '打印模式'
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
const modeElement = document.querySelector<HTMLDivElement>('.editor-mode')!
|
const modeElement = document.querySelector<HTMLDivElement>('.editor-mode')!
|
||||||
|
|||||||
Reference in New Issue
Block a user