feat: 发布0.9.89版本
This commit is contained in:
@@ -1,3 +1,41 @@
|
|||||||
|
## [0.9.91](https://github.com/Hufe921/canvas-editor/compare/v0.9.90...v0.9.91) (2024-08-25)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* format different types of line breaks #769 ([f65ff87](https://github.com/Hufe921/canvas-editor/commit/f65ff87e44728322417d235d2347ceca25cc6667)), closes [#769](https://github.com/Hufe921/canvas-editor/issues/769)
|
||||||
|
* format initial data boundary error #771 #784 ([f62a315](https://github.com/Hufe921/canvas-editor/commit/f62a315a7bd04e49e9e17bc7737ccd1f0e751d69)), closes [#771](https://github.com/Hufe921/canvas-editor/issues/771) [#784](https://github.com/Hufe921/canvas-editor/issues/784)
|
||||||
|
* set row margin boundary error ([5285170](https://github.com/Hufe921/canvas-editor/commit/528517094373b5fa9ca2145bb259889db865a588))
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* add page border ([3f6bdf6](https://github.com/Hufe921/canvas-editor/commit/3f6bdf6fcb583ab370cb5abe3eafebf6100f415e))
|
||||||
|
* hit checkbox/radio control when click on label #651 ([31b76b6](https://github.com/Hufe921/canvas-editor/commit/31b76b6fb6640ea75383569cb16ad1b5a2ccf25f)), closes [#651](https://github.com/Hufe921/canvas-editor/issues/651)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [0.9.90](https://github.com/Hufe921/canvas-editor/compare/v0.9.89...v0.9.90) (2024-08-18)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* float image position when scaling the page #766 ([c249b9e](https://github.com/Hufe921/canvas-editor/commit/c249b9eec215fe573b325d1430212f5f01c32099)), closes [#766](https://github.com/Hufe921/canvas-editor/issues/766)
|
||||||
|
* get range paragraph info boundary error #758 ([4653fe7](https://github.com/Hufe921/canvas-editor/commit/4653fe7427f4a9ec40700f6a86ff284d1d46088a)), closes [#758](https://github.com/Hufe921/canvas-editor/issues/758)
|
||||||
|
* insert block element row flex error #754 ([136b1ff](https://github.com/Hufe921/canvas-editor/commit/136b1ffa55b7b0b78bf3d114400489e1bbab4f17)), closes [#754](https://github.com/Hufe921/canvas-editor/issues/754)
|
||||||
|
* paper printing size setting #760 ([7a6dd75](https://github.com/Hufe921/canvas-editor/commit/7a6dd753e59bde4cb581ac215b038dd1cd08c96f)), closes [#760](https://github.com/Hufe921/canvas-editor/issues/760)
|
||||||
|
* set editor mode option error #755 ([500cec3](https://github.com/Hufe921/canvas-editor/commit/500cec3e0b63e012f6572dcedb071befa114956e)), closes [#755](https://github.com/Hufe921/canvas-editor/issues/755)
|
||||||
|
* set row flex boundary error when deleting element ([2f272de](https://github.com/Hufe921/canvas-editor/commit/2f272dee58169607783e4cfd1347534f49db0834))
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* add location property to executeLocationControl api #753 ([d1a1aaa](https://github.com/Hufe921/canvas-editor/commit/d1a1aaa6ae08d8395df1df664d47bfe4fe821869)), closes [#753](https://github.com/Hufe921/canvas-editor/issues/753)
|
||||||
|
* add radio and checkbox vertical align setting ([c375466](https://github.com/Hufe921/canvas-editor/commit/c3754663cee25003a7021a6079dd46e2a3a0abd8))
|
||||||
|
* get context content width ([187498e](https://github.com/Hufe921/canvas-editor/commit/187498ed3dfba4386375d812d41b31c057ac3af8))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## [0.9.89](https://github.com/Hufe921/canvas-editor/compare/v0.9.88...v0.9.89) (2024-08-09)
|
## [0.9.89](https://github.com/Hufe921/canvas-editor/compare/v0.9.88...v0.9.89) (2024-08-09)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -679,7 +679,7 @@ Feature: Change how image rows are displayed
|
|||||||
Usage:
|
Usage:
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
instance.command.executeSaveAsImageElement(element: IElement, display: ImageDisplay)
|
instance.command.executeChangeImageDisplay(element: IElement, display: ImageDisplay)
|
||||||
```
|
```
|
||||||
|
|
||||||
## executePageMode
|
## executePageMode
|
||||||
@@ -961,3 +961,13 @@ Usage:
|
|||||||
```javascript
|
```javascript
|
||||||
instance.command.executeInsertTitle(payload: IElement)
|
instance.command.executeInsertTitle(payload: IElement)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## executeFocus
|
||||||
|
|
||||||
|
Feature: focus
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
instance.command.executeFocus(payload?: IFocusOption)
|
||||||
|
```
|
||||||
|
|||||||
+15
-3
@@ -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), Print (Visual aids are not displayed, Unwritten content 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), Design (Do not handle configurations such as non deletable and read-only). default: Edit
|
||||||
defaultType?: string // Default element type. default: TEXT
|
defaultType?: string // Default element type. default: TEXT
|
||||||
defaultColor?: string // Default color. default: #000000
|
defaultColor?: string // Default color. default: #000000
|
||||||
defaultFont?: string // Default font. default: Microsoft YaHei
|
defaultFont?: string // Default font. default: Microsoft YaHei
|
||||||
@@ -60,8 +60,8 @@ interface IEditorOption {
|
|||||||
wordBreak?: WordBreak // Word and punctuation breaks: No punctuation in the first line of the BREAK_WORD &The word is not split, and the line is folded after BREAK_ALL full according to the width of the character. default: BREAK_WORD
|
wordBreak?: WordBreak // Word and punctuation breaks: No punctuation in the first line of the BREAK_WORD &The word is not split, and the line is folded after BREAK_ALL full according to the width of the character. default: BREAK_WORD
|
||||||
watermark?: IWatermark // Watermark{data:string; color?:string; opacity?:number; size?:number; font?:string;}
|
watermark?: IWatermark // Watermark{data:string; color?:string; opacity?:number; size?:number; font?:string;}
|
||||||
control?: IControlOption // Control {placeholderColor?:string; bracketColor?:string; prefix?:string; postfix?:string; borderWidth?: number; borderColor?: string;}
|
control?: IControlOption // Control {placeholderColor?:string; bracketColor?:string; prefix?:string; postfix?:string; borderWidth?: number; borderColor?: string;}
|
||||||
checkbox?: ICheckboxOption // Checkbox {width?:number; height?:number; gap?:number; lineWidth?:number; fillStyle?:string; strokeStyle?: string;}
|
checkbox?: ICheckboxOption // Checkbox {width?:number; height?:number; gap?:number; lineWidth?:number; fillStyle?:string; strokeStyle?: string; verticalAlign?: VerticalAlign;}
|
||||||
radio?: IRadioOption // Radio {width?:number; height?:number; gap?:number; lineWidth?:number; fillStyle?:string; strokeStyle?: string;}
|
radio?: IRadioOption // Radio {width?:number; height?:number; gap?:number; lineWidth?:number; fillStyle?:string; strokeStyle?: string; verticalAlign?: VerticalAlign;}
|
||||||
cursor?: ICursorOption // Cursor style. {width?: number; color?: string; dragWidth?: number; dragColor?: string;}
|
cursor?: ICursorOption // Cursor style. {width?: number; color?: string; dragWidth?: number; dragColor?: string;}
|
||||||
title?: ITitleOption // Title configuration.{ defaultFirstSize?: number; defaultSecondSize?: number; defaultThirdSize?: number defaultFourthSize?: number; defaultFifthSize?: number; defaultSixthSize?: number;}
|
title?: ITitleOption // Title configuration.{ defaultFirstSize?: number; defaultSecondSize?: number; defaultThirdSize?: number defaultFourthSize?: number; defaultFifthSize?: number; defaultSixthSize?: number;}
|
||||||
placeholder?: IPlaceholder // Placeholder text
|
placeholder?: IPlaceholder // Placeholder text
|
||||||
@@ -72,6 +72,7 @@ interface IEditorOption {
|
|||||||
lineBreak?: ILineBreakOption // LineBreak option. {disabled?:boolean; color?:string; lineWidth?:number;}
|
lineBreak?: ILineBreakOption // LineBreak option. {disabled?:boolean; color?:string; lineWidth?:number;}
|
||||||
separator?: ISeparatorOption // Separator option. {lineWidth?:number; strokeStyle?:string;}
|
separator?: ISeparatorOption // Separator option. {lineWidth?:number; strokeStyle?:string;}
|
||||||
lineNumber?: ILineNumberOption // LineNumber option. {size?:number; font?:string; color?:string; disabled?:boolean; right?:number}
|
lineNumber?: ILineNumberOption // LineNumber option. {size?:number; font?:string; color?:string; disabled?:boolean; right?:number}
|
||||||
|
pageBorder?: IPageBorderOption // PageBorder option. {color?:string; lineWidth:number; padding?:IPadding; disabled?:boolean;}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -159,3 +160,14 @@ interface ILineNumberOption {
|
|||||||
type?: LineNumberType // Number type (renumber each page, consecutive numbering). default: continuity
|
type?: LineNumberType // Number type (renumber each page, consecutive numbering). default: continuity
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## PageBorder Configuration
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
interface IPageBorderOption {
|
||||||
|
color?: string // color. default: #000000
|
||||||
|
lineWidth?: number // line width. default: 1
|
||||||
|
padding?: IPadding // padding. default: [0, 0, 0, 0]
|
||||||
|
disabled?: boolean // Whether to disable. default: true
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|||||||
@@ -21,5 +21,5 @@ export function myPlugin(editor: Editor, options?: Option) {
|
|||||||
## Use Plugin
|
## Use Plugin
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
instance.add(myPlugin, options?: Option)
|
instance.use(myPlugin, options?: Option)
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -679,7 +679,7 @@ instance.command.executeSaveAsImageElement()
|
|||||||
用法:
|
用法:
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
instance.command.executeSaveAsImageElement(element: IElement, display: ImageDisplay)
|
instance.command.executeChangeImageDisplay(element: IElement, display: ImageDisplay)
|
||||||
```
|
```
|
||||||
|
|
||||||
## executePageMode
|
## executePageMode
|
||||||
@@ -961,3 +961,13 @@ instance.command.executeUpdateOptions(payload: IUpdateOption)
|
|||||||
```javascript
|
```javascript
|
||||||
instance.command.executeInsertTitle(payload: IElement)
|
instance.command.executeInsertTitle(payload: IElement)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## executeFocus
|
||||||
|
|
||||||
|
功能:光标聚焦
|
||||||
|
|
||||||
|
用法:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
instance.command.executeFocus(payload?: IFocusOption)
|
||||||
|
```
|
||||||
|
|||||||
+15
-3
@@ -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
|
||||||
defaultColor?: string // 默认字体颜色。默认:#000000
|
defaultColor?: string // 默认字体颜色。默认:#000000
|
||||||
defaultFont?: string // 默认字体。默认:Microsoft YaHei
|
defaultFont?: string // 默认字体。默认:Microsoft YaHei
|
||||||
@@ -60,8 +60,8 @@ interface IEditorOption {
|
|||||||
wordBreak?: WordBreak // 单词与标点断行:BREAK_WORD首行不出现标点&单词不拆分、BREAK_ALL按字符宽度撑满后折行。默认:BREAK_WORD
|
wordBreak?: WordBreak // 单词与标点断行:BREAK_WORD首行不出现标点&单词不拆分、BREAK_ALL按字符宽度撑满后折行。默认:BREAK_WORD
|
||||||
watermark?: IWatermark // 水印信息。{data:string; color?:string; opacity?:number; size?:number; font?:string;}
|
watermark?: IWatermark // 水印信息。{data:string; color?:string; opacity?:number; size?:number; font?:string;}
|
||||||
control?: IControlOption // 控件信息。 {placeholderColor?:string; bracketColor?:string; prefix?:string; postfix?:string; borderWidth?: number; borderColor?: string;}
|
control?: IControlOption // 控件信息。 {placeholderColor?:string; bracketColor?:string; prefix?:string; postfix?:string; borderWidth?: number; borderColor?: string;}
|
||||||
checkbox?: ICheckboxOption // 复选框信息。{width?:number; height?:number; gap?:number; lineWidth?:number; fillStyle?:string; strokeStyle?: string;}
|
checkbox?: ICheckboxOption // 复选框信息。{width?:number; height?:number; gap?:number; lineWidth?:number; fillStyle?:string; strokeStyle?: string; verticalAlign?: VerticalAlign;}
|
||||||
radio?: IRadioOption // 单选框信息。{width?:number; height?:number; gap?:number; lineWidth?:number; fillStyle?:string; strokeStyle?: string;}
|
radio?: IRadioOption // 单选框信息。{width?:number; height?:number; gap?:number; lineWidth?:number; fillStyle?:string; strokeStyle?: string; verticalAlign?: VerticalAlign;}
|
||||||
cursor?: ICursorOption // 光标样式。{width?: number; color?: string; dragWidth?: number; dragColor?: string;}
|
cursor?: ICursorOption // 光标样式。{width?: number; color?: string; dragWidth?: number; dragColor?: string;}
|
||||||
title?: ITitleOption // 标题配置。{ defaultFirstSize?: number; defaultSecondSize?: number; defaultThirdSize?: number defaultFourthSize?: number; defaultFifthSize?: number; defaultSixthSize?: number;}
|
title?: ITitleOption // 标题配置。{ defaultFirstSize?: number; defaultSecondSize?: number; defaultThirdSize?: number defaultFourthSize?: number; defaultFifthSize?: number; defaultSixthSize?: number;}
|
||||||
placeholder?: IPlaceholder // 编辑器空白占位文本
|
placeholder?: IPlaceholder // 编辑器空白占位文本
|
||||||
@@ -72,6 +72,7 @@ interface IEditorOption {
|
|||||||
lineBreak?: ILineBreakOption // 换行符配置。{disabled?:boolean; color?:string; lineWidth?:number;}
|
lineBreak?: ILineBreakOption // 换行符配置。{disabled?:boolean; color?:string; lineWidth?:number;}
|
||||||
separator?: ISeparatorOption // 分隔符配置。{lineWidth?:number; strokeStyle?:string;}
|
separator?: ISeparatorOption // 分隔符配置。{lineWidth?:number; strokeStyle?:string;}
|
||||||
lineNumber?: ILineNumberOption // 行号配置。{size?:number; font?:string; color?:string; disabled?:boolean; right?:number}
|
lineNumber?: ILineNumberOption // 行号配置。{size?:number; font?:string; color?:string; disabled?:boolean; right?:number}
|
||||||
|
pageBorder?: IPageBorderOption // 页面边框配置。{color?:string; lineWidth:number; padding?:IPadding; disabled?:boolean;}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -159,3 +160,14 @@ interface ILineNumberOption {
|
|||||||
type?: LineNumberType // 编号类型(每页重新编号、连续编号)。默认:连续编号
|
type?: LineNumberType // 编号类型(每页重新编号、连续编号)。默认:连续编号
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## 页面边框配置
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
interface IPageBorderOption {
|
||||||
|
color?: string // 颜色。默认:#000000
|
||||||
|
lineWidth?: number // 宽度。默认:1
|
||||||
|
padding?: IPadding // 距离正文内边距。默认:[0, 5, 0, 5]
|
||||||
|
disabled?: boolean // 是否禁用。默认:true
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|||||||
@@ -21,5 +21,5 @@ export function myPlugin(editor: Editor, options?: Option) {
|
|||||||
## 使用插件
|
## 使用插件
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
instance.add(myPlugin, options?: Option)
|
instance.use(myPlugin, options?: Option)
|
||||||
```
|
```
|
||||||
|
|||||||
+1
-1
@@ -365,7 +365,7 @@
|
|||||||
<span>页面:<span class="page-no">1</span>/<span class="page-size">1</span></span>
|
<span>页面:<span class="page-no">1</span>/<span class="page-size">1</span></span>
|
||||||
<span>字数:<span class="word-count">0</span></span>
|
<span>字数:<span class="word-count">0</span></span>
|
||||||
</div>
|
</div>
|
||||||
<div class="editor-mode" title="编辑模式(编辑、清洁、只读、表单)">编辑模式</div>
|
<div class="editor-mode" title="编辑模式(编辑、清洁、只读、表单、设计)">编辑模式</div>
|
||||||
<div>
|
<div>
|
||||||
<div class="page-scale-minus" title="缩小(Ctrl+-)">
|
<div class="page-scale-minus" title="缩小(Ctrl+-)">
|
||||||
<i></i>
|
<i></i>
|
||||||
|
|||||||
+2
-2
@@ -1,11 +1,11 @@
|
|||||||
{
|
{
|
||||||
"name": "@hufe921/canvas-editor",
|
"name": "@liushuai05/canvas-editor",
|
||||||
"author": "Hufe",
|
"author": "Hufe",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"version": "0.9.89",
|
"version": "0.9.89",
|
||||||
"description": "rich text editor by canvas/svg",
|
"description": "rich text editor by canvas/svg",
|
||||||
"publishConfig": {
|
"publishConfig": {
|
||||||
"registry": "https://registry.npmjs.org/",
|
"registry": "https://registry.yarnpkg.com/",
|
||||||
"access": "public"
|
"access": "public"
|
||||||
},
|
},
|
||||||
"files": [
|
"files": [
|
||||||
|
|||||||
@@ -95,6 +95,7 @@ export class Command {
|
|||||||
public executeInsertControl: CommandAdapt['insertControl']
|
public executeInsertControl: CommandAdapt['insertControl']
|
||||||
public executeUpdateOptions: CommandAdapt['updateOptions']
|
public executeUpdateOptions: CommandAdapt['updateOptions']
|
||||||
public executeInsertTitle: CommandAdapt['insertTitle']
|
public executeInsertTitle: CommandAdapt['insertTitle']
|
||||||
|
public executeFocus: CommandAdapt['focus']
|
||||||
public getCatalog: CommandAdapt['getCatalog']
|
public getCatalog: CommandAdapt['getCatalog']
|
||||||
public getImage: CommandAdapt['getImage']
|
public getImage: CommandAdapt['getImage']
|
||||||
public getOptions: CommandAdapt['getOptions']
|
public getOptions: CommandAdapt['getOptions']
|
||||||
@@ -214,6 +215,7 @@ export class Command {
|
|||||||
this.executeSetZone = adapt.setZone.bind(adapt)
|
this.executeSetZone = adapt.setZone.bind(adapt)
|
||||||
this.executeUpdateOptions = adapt.updateOptions.bind(adapt)
|
this.executeUpdateOptions = adapt.updateOptions.bind(adapt)
|
||||||
this.executeInsertTitle = adapt.insertTitle.bind(adapt)
|
this.executeInsertTitle = adapt.insertTitle.bind(adapt)
|
||||||
|
this.executeFocus = adapt.focus.bind(adapt)
|
||||||
// 获取
|
// 获取
|
||||||
this.getImage = adapt.getImage.bind(adapt)
|
this.getImage = adapt.getImage.bind(adapt)
|
||||||
this.getOptions = adapt.getOptions.bind(adapt)
|
this.getOptions = adapt.getOptions.bind(adapt)
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ import {
|
|||||||
import { ElementType } from '../../dataset/enum/Element'
|
import { ElementType } from '../../dataset/enum/Element'
|
||||||
import { ElementStyleKey } from '../../dataset/enum/ElementStyle'
|
import { ElementStyleKey } from '../../dataset/enum/ElementStyle'
|
||||||
import { ListStyle, ListType } from '../../dataset/enum/List'
|
import { ListStyle, ListType } from '../../dataset/enum/List'
|
||||||
|
import { MoveDirection } from '../../dataset/enum/Observer'
|
||||||
import { RowFlex } from '../../dataset/enum/Row'
|
import { RowFlex } from '../../dataset/enum/Row'
|
||||||
import { TableBorder, TdBorder, TdSlash } from '../../dataset/enum/table/Table'
|
import { TableBorder, TdBorder, TdSlash } from '../../dataset/enum/table/Table'
|
||||||
import { TitleLevel } from '../../dataset/enum/Title'
|
import { TitleLevel } from '../../dataset/enum/Title'
|
||||||
@@ -52,6 +53,7 @@ import {
|
|||||||
IEditorOption,
|
IEditorOption,
|
||||||
IEditorResult,
|
IEditorResult,
|
||||||
IEditorText,
|
IEditorText,
|
||||||
|
IFocusOption,
|
||||||
ISetValueOption,
|
ISetValueOption,
|
||||||
IUpdateOption
|
IUpdateOption
|
||||||
} from '../../interface/Editor'
|
} from '../../interface/Editor'
|
||||||
@@ -789,7 +791,7 @@ export class CommandAdapt {
|
|||||||
const row = rowList[rowIndex]
|
const row = rowList[rowIndex]
|
||||||
offsetX = row?.offsetX || 0
|
offsetX = row?.offsetX || 0
|
||||||
}
|
}
|
||||||
const innerWidth = this.draw.getOriginalInnerWidth() - offsetX
|
const innerWidth = this.draw.getContextInnerWidth() - offsetX
|
||||||
// colgroup
|
// colgroup
|
||||||
const colgroup: IColgroup[] = []
|
const colgroup: IColgroup[] = []
|
||||||
const colWidth = innerWidth / col
|
const colWidth = innerWidth / col
|
||||||
@@ -810,7 +812,7 @@ export class CommandAdapt {
|
|||||||
tdList.push({
|
tdList.push({
|
||||||
colspan: 1,
|
colspan: 1,
|
||||||
rowspan: 1,
|
rowspan: 1,
|
||||||
value: [{ value: ZERO, size: 16 }]
|
value: []
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
trList.push(tr)
|
trList.push(tr)
|
||||||
@@ -825,7 +827,9 @@ export class CommandAdapt {
|
|||||||
formatElementList([element], {
|
formatElementList([element], {
|
||||||
editorOptions: this.options
|
editorOptions: this.options
|
||||||
})
|
})
|
||||||
formatElementContext(elementList, [element], startIndex)
|
formatElementContext(elementList, [element], startIndex, {
|
||||||
|
editorOptions: this.options
|
||||||
|
})
|
||||||
const curIndex = startIndex + 1
|
const curIndex = startIndex + 1
|
||||||
this.draw.spliceElementList(
|
this.draw.spliceElementList(
|
||||||
elementList,
|
elementList,
|
||||||
@@ -1586,7 +1590,9 @@ export class CommandAdapt {
|
|||||||
}))
|
}))
|
||||||
if (!newElementList) return
|
if (!newElementList) return
|
||||||
const start = startIndex + 1
|
const start = startIndex + 1
|
||||||
formatElementContext(elementList, newElementList, startIndex)
|
formatElementContext(elementList, newElementList, startIndex, {
|
||||||
|
editorOptions: this.options
|
||||||
|
})
|
||||||
this.draw.spliceElementList(
|
this.draw.spliceElementList(
|
||||||
elementList,
|
elementList,
|
||||||
start,
|
start,
|
||||||
@@ -1731,7 +1737,9 @@ export class CommandAdapt {
|
|||||||
dashArray: payload
|
dashArray: payload
|
||||||
}
|
}
|
||||||
// 从行头增加分割线
|
// 从行头增加分割线
|
||||||
formatElementContext(elementList, [newElement], startIndex)
|
formatElementContext(elementList, [newElement], startIndex, {
|
||||||
|
editorOptions: this.options
|
||||||
|
})
|
||||||
if (startIndex !== 0 && elementList[startIndex].value === ZERO) {
|
if (startIndex !== 0 && elementList[startIndex].value === ZERO) {
|
||||||
this.draw.spliceElementList(elementList, startIndex, 1, newElement)
|
this.draw.spliceElementList(elementList, startIndex, 1, newElement)
|
||||||
curIndex = startIndex - 1
|
curIndex = startIndex - 1
|
||||||
@@ -2236,7 +2244,8 @@ export class CommandAdapt {
|
|||||||
const { startIndex } = this.range.getRange()
|
const { startIndex } = this.range.getRange()
|
||||||
const elementList = this.draw.getElementList()
|
const elementList = this.draw.getElementList()
|
||||||
formatElementContext(elementList, cloneElementList, startIndex, {
|
formatElementContext(elementList, cloneElementList, startIndex, {
|
||||||
isBreakWhenWrap: true
|
isBreakWhenWrap: true,
|
||||||
|
editorOptions: this.options
|
||||||
})
|
})
|
||||||
this.draw.insertElementList(cloneElementList)
|
this.draw.insertElementList(cloneElementList)
|
||||||
}
|
}
|
||||||
@@ -2726,4 +2735,23 @@ export class CommandAdapt {
|
|||||||
// 插入标题
|
// 插入标题
|
||||||
this.draw.insertElementList([cloneElement])
|
this.draw.insertElementList([cloneElement])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public focus(payload?: IFocusOption) {
|
||||||
|
const { position = LocationPosition.AFTER } = payload || {}
|
||||||
|
const curIndex =
|
||||||
|
position === LocationPosition.BEFORE
|
||||||
|
? 0
|
||||||
|
: this.draw.getOriginalMainElementList().length - 1
|
||||||
|
this.range.setRange(curIndex, curIndex)
|
||||||
|
this.draw.render({
|
||||||
|
curIndex,
|
||||||
|
isCompute: false,
|
||||||
|
isSubmitHistory: false
|
||||||
|
})
|
||||||
|
const positionList = this.draw.getPosition().getPositionList()
|
||||||
|
this.draw.getCursor().moveCursorToVisible({
|
||||||
|
cursorPosition: positionList[curIndex],
|
||||||
|
direction: MoveDirection.DOWN
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -103,6 +103,7 @@ import { LineBreakParticle } from './particle/LineBreakParticle'
|
|||||||
import { MouseObserver } from '../observer/MouseObserver'
|
import { MouseObserver } from '../observer/MouseObserver'
|
||||||
import { LineNumber } from './frame/LineNumber'
|
import { LineNumber } from './frame/LineNumber'
|
||||||
import { ITd } from '../../interface/table/Td'
|
import { ITd } from '../../interface/table/Td'
|
||||||
|
import { PageBorder } from './frame/PageBorder'
|
||||||
|
|
||||||
export class Draw {
|
export class Draw {
|
||||||
private container: HTMLDivElement
|
private container: HTMLDivElement
|
||||||
@@ -157,6 +158,7 @@ export class Draw {
|
|||||||
private listParticle: ListParticle
|
private listParticle: ListParticle
|
||||||
private lineBreakParticle: LineBreakParticle
|
private lineBreakParticle: LineBreakParticle
|
||||||
private control: Control
|
private control: Control
|
||||||
|
private pageBorder: PageBorder
|
||||||
private workerManager: WorkerManager
|
private workerManager: WorkerManager
|
||||||
private scrollObserver: ScrollObserver
|
private scrollObserver: ScrollObserver
|
||||||
private selectionObserver: SelectionObserver
|
private selectionObserver: SelectionObserver
|
||||||
@@ -233,6 +235,7 @@ export class Draw {
|
|||||||
this.listParticle = new ListParticle(this)
|
this.listParticle = new ListParticle(this)
|
||||||
this.lineBreakParticle = new LineBreakParticle(this)
|
this.lineBreakParticle = new LineBreakParticle(this)
|
||||||
this.control = new Control(this)
|
this.control = new Control(this)
|
||||||
|
this.pageBorder = new PageBorder(this)
|
||||||
|
|
||||||
this.scrollObserver = new ScrollObserver(this)
|
this.scrollObserver = new ScrollObserver(this)
|
||||||
this.selectionObserver = new SelectionObserver(this)
|
this.selectionObserver = new SelectionObserver(this)
|
||||||
@@ -312,6 +315,8 @@ export class Draw {
|
|||||||
|
|
||||||
public isReadonly() {
|
public isReadonly() {
|
||||||
switch (this.mode) {
|
switch (this.mode) {
|
||||||
|
case EditorMode.DESIGN:
|
||||||
|
return false
|
||||||
case EditorMode.READONLY:
|
case EditorMode.READONLY:
|
||||||
case EditorMode.PRINT:
|
case EditorMode.PRINT:
|
||||||
return true
|
return true
|
||||||
@@ -323,6 +328,7 @@ export class Draw {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public isDisabled() {
|
public isDisabled() {
|
||||||
|
if (this.mode === EditorMode.DESIGN) return false
|
||||||
const { startIndex, endIndex } = this.range.getRange()
|
const { startIndex, endIndex } = this.range.getRange()
|
||||||
const elementList = this.getElementList()
|
const elementList = this.getElementList()
|
||||||
if (startIndex === endIndex) {
|
if (startIndex === endIndex) {
|
||||||
@@ -339,6 +345,10 @@ export class Draw {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public isDesignMode() {
|
||||||
|
return this.mode === EditorMode.DESIGN
|
||||||
|
}
|
||||||
|
|
||||||
public getOriginalWidth(): number {
|
public getOriginalWidth(): number {
|
||||||
const { paperDirection, width, height } = this.options
|
const { paperDirection, width, height } = this.options
|
||||||
return paperDirection === PaperDirection.VERTICAL ? width : height
|
return paperDirection === PaperDirection.VERTICAL ? width : height
|
||||||
@@ -391,6 +401,18 @@ export class Draw {
|
|||||||
return width - margins[1] - margins[3]
|
return width - margins[1] - margins[3]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public getContextInnerWidth(): number {
|
||||||
|
const positionContext = this.position.getPositionContext()
|
||||||
|
if (positionContext.isTable) {
|
||||||
|
const { index, trIndex, tdIndex } = positionContext
|
||||||
|
const elementList = this.getOriginalElementList()
|
||||||
|
const td = elementList[index!].trList![trIndex!].tdList[tdIndex!]
|
||||||
|
const tdPadding = this.getTdPadding()
|
||||||
|
return td!.width! - tdPadding[1] - tdPadding[3]
|
||||||
|
}
|
||||||
|
return this.getOriginalInnerWidth()
|
||||||
|
}
|
||||||
|
|
||||||
public getMargins(): IMargin {
|
public getMargins(): IMargin {
|
||||||
return <IMargin>this.getOriginalMargins().map(m => m * this.options.scale)
|
return <IMargin>this.getOriginalMargins().map(m => m * this.options.scale)
|
||||||
}
|
}
|
||||||
@@ -684,6 +706,7 @@ export class Draw {
|
|||||||
deleteCount: number,
|
deleteCount: number,
|
||||||
...items: IElement[]
|
...items: IElement[]
|
||||||
) {
|
) {
|
||||||
|
const isDesignMode = this.isDesignMode()
|
||||||
if (deleteCount > 0) {
|
if (deleteCount > 0) {
|
||||||
// 当最后元素与开始元素列表信息不一致时:清除当前列表信息
|
// 当最后元素与开始元素列表信息不一致时:清除当前列表信息
|
||||||
const endIndex = start + deleteCount
|
const endIndex = start + deleteCount
|
||||||
@@ -714,8 +737,9 @@ export class Draw {
|
|||||||
while (deleteIndex >= start) {
|
while (deleteIndex >= start) {
|
||||||
const deleteElement = elementList[deleteIndex]
|
const deleteElement = elementList[deleteIndex]
|
||||||
if (
|
if (
|
||||||
deleteElement?.control?.deletable !== false &&
|
isDesignMode ||
|
||||||
deleteElement?.title?.deletable !== false
|
(deleteElement?.control?.deletable !== false &&
|
||||||
|
deleteElement?.title?.deletable !== false)
|
||||||
) {
|
) {
|
||||||
elementList.splice(deleteIndex, 1)
|
elementList.splice(deleteIndex, 1)
|
||||||
}
|
}
|
||||||
@@ -1069,7 +1093,8 @@ export class Draw {
|
|||||||
pageComponentData.forEach(data => {
|
pageComponentData.forEach(data => {
|
||||||
if (!data) return
|
if (!data) return
|
||||||
formatElementList(data, {
|
formatElementList(data, {
|
||||||
editorOptions: this.options
|
editorOptions: this.options,
|
||||||
|
isForceCompensation: true
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
this.setEditorData({
|
this.setEditorData({
|
||||||
@@ -1177,7 +1202,7 @@ export class Draw {
|
|||||||
const { defaultBasicRowMarginHeight, defaultRowMargin, scale } =
|
const { defaultBasicRowMarginHeight, defaultRowMargin, scale } =
|
||||||
this.options
|
this.options
|
||||||
return (
|
return (
|
||||||
defaultBasicRowMarginHeight * (el.rowMargin || defaultRowMargin) * scale
|
defaultBasicRowMarginHeight * (el.rowMargin ?? defaultRowMargin) * scale
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1217,7 +1242,7 @@ export class Draw {
|
|||||||
const curRow: IRow = rowList[rowList.length - 1]
|
const curRow: IRow = rowList[rowList.length - 1]
|
||||||
const element = elementList[i]
|
const element = elementList[i]
|
||||||
const rowMargin =
|
const rowMargin =
|
||||||
defaultBasicRowMarginHeight * (element.rowMargin || defaultRowMargin)
|
defaultBasicRowMarginHeight * (element.rowMargin ?? defaultRowMargin)
|
||||||
const metrics: IElementMetrics = {
|
const metrics: IElementMetrics = {
|
||||||
width: 0,
|
width: 0,
|
||||||
height: 0,
|
height: 0,
|
||||||
@@ -2223,13 +2248,25 @@ export class Draw {
|
|||||||
element.controlComponent === ControlComponent.CHECKBOX
|
element.controlComponent === ControlComponent.CHECKBOX
|
||||||
) {
|
) {
|
||||||
this.textParticle.complete()
|
this.textParticle.complete()
|
||||||
this.checkboxParticle.render(ctx, element, x, y + offsetY)
|
this.checkboxParticle.render({
|
||||||
|
ctx,
|
||||||
|
x,
|
||||||
|
y: y + offsetY,
|
||||||
|
index: j,
|
||||||
|
row: curRow
|
||||||
|
})
|
||||||
} else if (
|
} else if (
|
||||||
element.type === ElementType.RADIO ||
|
element.type === ElementType.RADIO ||
|
||||||
element.controlComponent === ControlComponent.RADIO
|
element.controlComponent === ControlComponent.RADIO
|
||||||
) {
|
) {
|
||||||
this.textParticle.complete()
|
this.textParticle.complete()
|
||||||
this.radioParticle.render(ctx, element, x, y + offsetY)
|
this.radioParticle.render({
|
||||||
|
ctx,
|
||||||
|
x,
|
||||||
|
y: y + offsetY,
|
||||||
|
index: j,
|
||||||
|
row: curRow
|
||||||
|
})
|
||||||
} else if (element.type === ElementType.TAB) {
|
} else if (element.type === ElementType.TAB) {
|
||||||
this.textParticle.complete()
|
this.textParticle.complete()
|
||||||
} else if (
|
} else if (
|
||||||
@@ -2470,6 +2507,7 @@ export class Draw {
|
|||||||
ctx: CanvasRenderingContext2D,
|
ctx: CanvasRenderingContext2D,
|
||||||
payload: IDrawFloatPayload
|
payload: IDrawFloatPayload
|
||||||
) {
|
) {
|
||||||
|
const { scale } = this.options
|
||||||
const floatPositionList = this.position.getFloatPositionList()
|
const floatPositionList = this.position.getFloatPositionList()
|
||||||
const { imgDisplay, pageNo } = payload
|
const { imgDisplay, pageNo } = payload
|
||||||
for (let e = 0; e < floatPositionList.length; e++) {
|
for (let e = 0; e < floatPositionList.length; e++) {
|
||||||
@@ -2486,8 +2524,8 @@ export class Draw {
|
|||||||
this.imageParticle.render(
|
this.imageParticle.render(
|
||||||
ctx,
|
ctx,
|
||||||
element,
|
element,
|
||||||
imgFloatPosition.x,
|
imgFloatPosition.x * scale,
|
||||||
imgFloatPosition.y
|
imgFloatPosition.y * scale
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2507,8 +2545,15 @@ export class Draw {
|
|||||||
|
|
||||||
private _drawPage(payload: IDrawPagePayload) {
|
private _drawPage(payload: IDrawPagePayload) {
|
||||||
const { elementList, positionList, rowList, pageNo } = payload
|
const { elementList, positionList, rowList, pageNo } = payload
|
||||||
const { inactiveAlpha, pageMode, header, footer, pageNumber, lineNumber } =
|
const {
|
||||||
this.options
|
inactiveAlpha,
|
||||||
|
pageMode,
|
||||||
|
header,
|
||||||
|
footer,
|
||||||
|
pageNumber,
|
||||||
|
lineNumber,
|
||||||
|
pageBorder
|
||||||
|
} = this.options
|
||||||
const innerWidth = this.getInnerWidth()
|
const innerWidth = this.getInnerWidth()
|
||||||
const ctx = this.ctxList[pageNo]
|
const ctx = this.ctxList[pageNo]
|
||||||
// 判断当前激活区域-非正文区域时元素透明度降低
|
// 判断当前激活区域-非正文区域时元素透明度降低
|
||||||
@@ -2573,6 +2618,10 @@ export class Draw {
|
|||||||
if (!lineNumber.disabled) {
|
if (!lineNumber.disabled) {
|
||||||
this.lineNumber.render(ctx, pageNo)
|
this.lineNumber.render(ctx, pageNo)
|
||||||
}
|
}
|
||||||
|
// 绘制页面边框
|
||||||
|
if (!pageBorder.disabled) {
|
||||||
|
this.pageBorder.render(ctx)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private _disconnectLazyRender() {
|
private _disconnectLazyRender() {
|
||||||
|
|||||||
@@ -208,7 +208,7 @@ export class Control {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public getIsDisabledControl(context: IControlContext = {}): boolean {
|
public getIsDisabledControl(context: IControlContext = {}): boolean {
|
||||||
if (!this.activeControl) return false
|
if (this.draw.isDesignMode() || !this.activeControl) return false
|
||||||
const { startIndex, endIndex } = context.range || this.range.getRange()
|
const { startIndex, endIndex } = context.range || this.range.getRange()
|
||||||
if (startIndex === endIndex && ~startIndex && ~endIndex) {
|
if (startIndex === endIndex && ~startIndex && ~endIndex) {
|
||||||
const elementList = context.elementList || this.getElementList()
|
const elementList = context.elementList || this.getElementList()
|
||||||
@@ -452,8 +452,11 @@ export class Control {
|
|||||||
): number | null {
|
): number | null {
|
||||||
const elementList = context.elementList || this.getElementList()
|
const elementList = context.elementList || this.getElementList()
|
||||||
const startElement = elementList[startIndex]
|
const startElement = elementList[startIndex]
|
||||||
const { deletable = true } = startElement.control!
|
// 设计模式不验证删除权限
|
||||||
if (!deletable) return null
|
if (!this.draw.isDesignMode()) {
|
||||||
|
const { deletable = true } = startElement.control!
|
||||||
|
if (!deletable) return null
|
||||||
|
}
|
||||||
let leftIndex = -1
|
let leftIndex = -1
|
||||||
let rightIndex = -1
|
let rightIndex = -1
|
||||||
// 向左查找
|
// 向左查找
|
||||||
@@ -538,7 +541,9 @@ export class Control {
|
|||||||
controlComponent: ControlComponent.PLACEHOLDER,
|
controlComponent: ControlComponent.PLACEHOLDER,
|
||||||
color: this.controlOptions.placeholderColor
|
color: this.controlOptions.placeholderColor
|
||||||
}
|
}
|
||||||
formatElementContext(elementList, [newElement], startIndex)
|
formatElementContext(elementList, [newElement], startIndex, {
|
||||||
|
editorOptions: this.options
|
||||||
|
})
|
||||||
this.draw.spliceElementList(
|
this.draw.spliceElementList(
|
||||||
elementList,
|
elementList,
|
||||||
startIndex + p + 1,
|
startIndex + p + 1,
|
||||||
@@ -892,7 +897,8 @@ export class Control {
|
|||||||
const elementList = zipElementList(pageComponentData[pageComponentKey]!)
|
const elementList = zipElementList(pageComponentData[pageComponentKey]!)
|
||||||
pageComponentData[pageComponentKey] = elementList
|
pageComponentData[pageComponentKey] = elementList
|
||||||
formatElementList(elementList, {
|
formatElementList(elementList, {
|
||||||
editorOptions: this.options
|
editorOptions: this.options,
|
||||||
|
isForceCompensation: true
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
this.draw.setEditorData(pageComponentData)
|
this.draw.setEditorData(pageComponentData)
|
||||||
|
|||||||
@@ -6,11 +6,13 @@ import {
|
|||||||
import { ControlComponent } from '../../../../dataset/enum/Control'
|
import { ControlComponent } from '../../../../dataset/enum/Control'
|
||||||
import { ElementType } from '../../../../dataset/enum/Element'
|
import { ElementType } from '../../../../dataset/enum/Element'
|
||||||
import { KeyMap } from '../../../../dataset/enum/KeyMap'
|
import { KeyMap } from '../../../../dataset/enum/KeyMap'
|
||||||
|
import { DeepRequired } from '../../../../interface/Common'
|
||||||
import {
|
import {
|
||||||
IControlContext,
|
IControlContext,
|
||||||
IControlInstance,
|
IControlInstance,
|
||||||
IControlRuleOption
|
IControlRuleOption
|
||||||
} from '../../../../interface/Control'
|
} from '../../../../interface/Control'
|
||||||
|
import { IEditorOption } from '../../../../interface/Editor'
|
||||||
import { IElement } from '../../../../interface/Element'
|
import { IElement } from '../../../../interface/Element'
|
||||||
import { omitObject, pickObject } from '../../../../utils'
|
import { omitObject, pickObject } from '../../../../utils'
|
||||||
import { formatElementContext } from '../../../../utils/element'
|
import { formatElementContext } from '../../../../utils/element'
|
||||||
@@ -24,10 +26,12 @@ export class DateControl implements IControlInstance {
|
|||||||
private control: Control
|
private control: Control
|
||||||
private isPopup: boolean
|
private isPopup: boolean
|
||||||
private datePicker: DatePicker | null
|
private datePicker: DatePicker | null
|
||||||
|
private options: DeepRequired<IEditorOption>
|
||||||
|
|
||||||
constructor(element: IElement, control: Control) {
|
constructor(element: IElement, control: Control) {
|
||||||
const draw = control.getDraw()
|
const draw = control.getDraw()
|
||||||
this.draw = draw
|
this.draw = draw
|
||||||
|
this.options = draw.getOptions()
|
||||||
this.element = element
|
this.element = element
|
||||||
this.control = control
|
this.control = control
|
||||||
this.isPopup = false
|
this.isPopup = false
|
||||||
@@ -138,7 +142,9 @@ export class DateControl implements IControlInstance {
|
|||||||
...data[i],
|
...data[i],
|
||||||
controlComponent: ControlComponent.VALUE
|
controlComponent: ControlComponent.VALUE
|
||||||
}
|
}
|
||||||
formatElementContext(elementList, [newElement], startIndex)
|
formatElementContext(elementList, [newElement], startIndex, {
|
||||||
|
editorOptions: this.options
|
||||||
|
})
|
||||||
draw.spliceElementList(elementList, start + i, 0, newElement)
|
draw.spliceElementList(elementList, start + i, 0, newElement)
|
||||||
}
|
}
|
||||||
return start + data.length - 1
|
return start + data.length - 1
|
||||||
@@ -207,7 +213,9 @@ export class DateControl implements IControlInstance {
|
|||||||
value: date[i],
|
value: date[i],
|
||||||
controlComponent: ControlComponent.VALUE
|
controlComponent: ControlComponent.VALUE
|
||||||
}
|
}
|
||||||
formatElementContext(elementList, [newElement], prefixIndex)
|
formatElementContext(elementList, [newElement], prefixIndex, {
|
||||||
|
editorOptions: this.options
|
||||||
|
})
|
||||||
draw.spliceElementList(elementList, start + i, 0, newElement)
|
draw.spliceElementList(elementList, start + i, 0, newElement)
|
||||||
}
|
}
|
||||||
// 重新渲染控件
|
// 重新渲染控件
|
||||||
|
|||||||
@@ -10,11 +10,13 @@ import { ControlComponent } from '../../../../dataset/enum/Control'
|
|||||||
import { EditorComponent } from '../../../../dataset/enum/Editor'
|
import { EditorComponent } from '../../../../dataset/enum/Editor'
|
||||||
import { ElementType } from '../../../../dataset/enum/Element'
|
import { ElementType } from '../../../../dataset/enum/Element'
|
||||||
import { KeyMap } from '../../../../dataset/enum/KeyMap'
|
import { KeyMap } from '../../../../dataset/enum/KeyMap'
|
||||||
|
import { DeepRequired } from '../../../../interface/Common'
|
||||||
import {
|
import {
|
||||||
IControlContext,
|
IControlContext,
|
||||||
IControlInstance,
|
IControlInstance,
|
||||||
IControlRuleOption
|
IControlRuleOption
|
||||||
} from '../../../../interface/Control'
|
} from '../../../../interface/Control'
|
||||||
|
import { IEditorOption } from '../../../../interface/Editor'
|
||||||
import { IElement } from '../../../../interface/Element'
|
import { IElement } from '../../../../interface/Element'
|
||||||
import { omitObject, pickObject, splitText } from '../../../../utils'
|
import { omitObject, pickObject, splitText } from '../../../../utils'
|
||||||
import { formatElementContext } from '../../../../utils/element'
|
import { formatElementContext } from '../../../../utils/element'
|
||||||
@@ -25,8 +27,10 @@ export class SelectControl implements IControlInstance {
|
|||||||
private control: Control
|
private control: Control
|
||||||
private isPopup: boolean
|
private isPopup: boolean
|
||||||
private selectDom: HTMLDivElement | null
|
private selectDom: HTMLDivElement | null
|
||||||
|
private options: DeepRequired<IEditorOption>
|
||||||
|
|
||||||
constructor(element: IElement, control: Control) {
|
constructor(element: IElement, control: Control) {
|
||||||
|
this.options = control.getDraw().getOptions()
|
||||||
this.element = element
|
this.element = element
|
||||||
this.control = control
|
this.control = control
|
||||||
this.isPopup = false
|
this.isPopup = false
|
||||||
@@ -270,7 +274,9 @@ export class SelectControl implements IControlInstance {
|
|||||||
value: data[i],
|
value: data[i],
|
||||||
controlComponent: ControlComponent.VALUE
|
controlComponent: ControlComponent.VALUE
|
||||||
}
|
}
|
||||||
formatElementContext(elementList, [newElement], prefixIndex)
|
formatElementContext(elementList, [newElement], prefixIndex, {
|
||||||
|
editorOptions: this.options
|
||||||
|
})
|
||||||
draw.spliceElementList(elementList, start + i, 0, newElement)
|
draw.spliceElementList(elementList, start + i, 0, newElement)
|
||||||
}
|
}
|
||||||
// 设置状态
|
// 设置状态
|
||||||
|
|||||||
@@ -4,11 +4,13 @@ import {
|
|||||||
} from '../../../../dataset/constant/Element'
|
} from '../../../../dataset/constant/Element'
|
||||||
import { ControlComponent } from '../../../../dataset/enum/Control'
|
import { ControlComponent } from '../../../../dataset/enum/Control'
|
||||||
import { KeyMap } from '../../../../dataset/enum/KeyMap'
|
import { KeyMap } from '../../../../dataset/enum/KeyMap'
|
||||||
|
import { DeepRequired } from '../../../../interface/Common'
|
||||||
import {
|
import {
|
||||||
IControlContext,
|
IControlContext,
|
||||||
IControlInstance,
|
IControlInstance,
|
||||||
IControlRuleOption
|
IControlRuleOption
|
||||||
} from '../../../../interface/Control'
|
} from '../../../../interface/Control'
|
||||||
|
import { IEditorOption } from '../../../../interface/Editor'
|
||||||
import { IElement } from '../../../../interface/Element'
|
import { IElement } from '../../../../interface/Element'
|
||||||
import { omitObject, pickObject } from '../../../../utils'
|
import { omitObject, pickObject } from '../../../../utils'
|
||||||
import { formatElementContext } from '../../../../utils/element'
|
import { formatElementContext } from '../../../../utils/element'
|
||||||
@@ -17,8 +19,10 @@ import { Control } from '../Control'
|
|||||||
export class TextControl implements IControlInstance {
|
export class TextControl implements IControlInstance {
|
||||||
private element: IElement
|
private element: IElement
|
||||||
private control: Control
|
private control: Control
|
||||||
|
private options: DeepRequired<IEditorOption>
|
||||||
|
|
||||||
constructor(element: IElement, control: Control) {
|
constructor(element: IElement, control: Control) {
|
||||||
|
this.options = control.getDraw().getOptions()
|
||||||
this.element = element
|
this.element = element
|
||||||
this.control = control
|
this.control = control
|
||||||
}
|
}
|
||||||
@@ -114,7 +118,9 @@ export class TextControl implements IControlInstance {
|
|||||||
...data[i],
|
...data[i],
|
||||||
controlComponent: ControlComponent.VALUE
|
controlComponent: ControlComponent.VALUE
|
||||||
}
|
}
|
||||||
formatElementContext(elementList, [newElement], startIndex)
|
formatElementContext(elementList, [newElement], startIndex, {
|
||||||
|
editorOptions: this.options
|
||||||
|
})
|
||||||
draw.spliceElementList(elementList, start + i, 0, newElement)
|
draw.spliceElementList(elementList, start + i, 0, newElement)
|
||||||
}
|
}
|
||||||
return start + data.length - 1
|
return start + data.length - 1
|
||||||
|
|||||||
@@ -0,0 +1,47 @@
|
|||||||
|
import { DeepRequired } from '../../../interface/Common'
|
||||||
|
import { IEditorOption } from '../../../interface/Editor'
|
||||||
|
import { Draw } from '../Draw'
|
||||||
|
import { Footer } from './Footer'
|
||||||
|
import { Header } from './Header'
|
||||||
|
|
||||||
|
export class PageBorder {
|
||||||
|
private draw: Draw
|
||||||
|
private header: Header
|
||||||
|
private footer: Footer
|
||||||
|
private options: DeepRequired<IEditorOption>
|
||||||
|
|
||||||
|
constructor(draw: Draw) {
|
||||||
|
this.draw = draw
|
||||||
|
this.header = draw.getHeader()
|
||||||
|
this.footer = draw.getFooter()
|
||||||
|
this.options = draw.getOptions()
|
||||||
|
}
|
||||||
|
|
||||||
|
public render(ctx: CanvasRenderingContext2D) {
|
||||||
|
const {
|
||||||
|
scale,
|
||||||
|
pageBorder: { color, lineWidth, padding }
|
||||||
|
} = this.options
|
||||||
|
ctx.save()
|
||||||
|
ctx.translate(0.5, 0.5)
|
||||||
|
ctx.strokeStyle = color
|
||||||
|
ctx.lineWidth = lineWidth * scale
|
||||||
|
const margins = this.draw.getMargins()
|
||||||
|
// x:左边距 - 左距离正文距离
|
||||||
|
const x = margins[3] - padding[3] * scale
|
||||||
|
// y:页眉上边距 + 页眉高度 - 上距离正文距离
|
||||||
|
const y = margins[0] + this.header.getExtraHeight() - padding[0] * scale
|
||||||
|
// width:页面宽度 + 左右距离正文距离
|
||||||
|
const width = this.draw.getInnerWidth() + (padding[1] + padding[3]) * scale
|
||||||
|
// height:页面高度 - 正文起始位置 - 页脚高度 - 下边距 - 下距离正文距离
|
||||||
|
const height =
|
||||||
|
this.draw.getHeight() -
|
||||||
|
y -
|
||||||
|
this.footer.getExtraHeight() -
|
||||||
|
margins[2] +
|
||||||
|
padding[2] * scale
|
||||||
|
ctx.rect(x, y, width, height)
|
||||||
|
ctx.stroke()
|
||||||
|
ctx.restore()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -84,7 +84,8 @@ export class Placeholder {
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
formatElementList(this.elementList, {
|
formatElementList(this.elementList, {
|
||||||
editorOptions: this.options
|
editorOptions: this.options,
|
||||||
|
isForceCompensation: true
|
||||||
})
|
})
|
||||||
// 计算
|
// 计算
|
||||||
this._compute()
|
this._compute()
|
||||||
|
|||||||
@@ -1,9 +1,19 @@
|
|||||||
|
import { NBSP, ZERO } from '../../../dataset/constant/Common'
|
||||||
|
import { VerticalAlign } from '../../../dataset/enum/VerticalAlign'
|
||||||
import { DeepRequired } from '../../../interface/Common'
|
import { DeepRequired } from '../../../interface/Common'
|
||||||
import { IEditorOption } from '../../../interface/Editor'
|
import { IEditorOption } from '../../../interface/Editor'
|
||||||
import { IElement } from '../../../interface/Element'
|
import { IElement } from '../../../interface/Element'
|
||||||
import { IRowElement } from '../../../interface/Row'
|
import { IRow, IRowElement } from '../../../interface/Row'
|
||||||
import { Draw } from '../Draw'
|
import { Draw } from '../Draw'
|
||||||
|
|
||||||
|
interface ICheckboxRenderOption {
|
||||||
|
ctx: CanvasRenderingContext2D
|
||||||
|
x: number
|
||||||
|
y: number
|
||||||
|
row: IRow
|
||||||
|
index: number
|
||||||
|
}
|
||||||
|
|
||||||
export class CheckboxParticle {
|
export class CheckboxParticle {
|
||||||
private draw: Draw
|
private draw: Draw
|
||||||
private options: DeepRequired<IEditorOption>
|
private options: DeepRequired<IEditorOption>
|
||||||
@@ -28,17 +38,41 @@ export class CheckboxParticle {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
public render(
|
public render(payload: ICheckboxRenderOption) {
|
||||||
ctx: CanvasRenderingContext2D,
|
const { ctx, x, index, row } = payload
|
||||||
element: IRowElement,
|
let { y } = payload
|
||||||
x: number,
|
|
||||||
y: number
|
|
||||||
) {
|
|
||||||
const {
|
const {
|
||||||
checkbox: { gap, lineWidth, fillStyle, strokeStyle },
|
checkbox: { gap, lineWidth, fillStyle, strokeStyle, verticalAlign },
|
||||||
scale
|
scale
|
||||||
} = this.options
|
} = this.options
|
||||||
const { metrics, checkbox } = element
|
const { metrics, checkbox } = row.elementList[index]
|
||||||
|
// 垂直布局设置
|
||||||
|
if (
|
||||||
|
verticalAlign === VerticalAlign.TOP ||
|
||||||
|
verticalAlign === VerticalAlign.MIDDLE
|
||||||
|
) {
|
||||||
|
let nextIndex = index + 1
|
||||||
|
let nextElement: IRowElement | null = null
|
||||||
|
while (nextIndex < row.elementList.length) {
|
||||||
|
nextElement = row.elementList[nextIndex]
|
||||||
|
if (nextElement.value !== ZERO && nextElement.value !== NBSP) break
|
||||||
|
nextIndex++
|
||||||
|
}
|
||||||
|
// 以后一个非空格元素为基准
|
||||||
|
if (nextElement) {
|
||||||
|
const {
|
||||||
|
metrics: { boundingBoxAscent, boundingBoxDescent }
|
||||||
|
} = nextElement
|
||||||
|
const textHeight = boundingBoxAscent + boundingBoxDescent
|
||||||
|
if (textHeight > metrics.height) {
|
||||||
|
if (verticalAlign === VerticalAlign.TOP) {
|
||||||
|
y -= boundingBoxAscent - metrics.height
|
||||||
|
} else if (verticalAlign === VerticalAlign.MIDDLE) {
|
||||||
|
y -= (textHeight - metrics.height) / 2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
// left top 四舍五入避免1像素问题
|
// left top 四舍五入避免1像素问题
|
||||||
const left = Math.round(x + gap * scale)
|
const left = Math.round(x + gap * scale)
|
||||||
const top = Math.round(y - metrics.height + lineWidth)
|
const top = Math.round(y - metrics.height + lineWidth)
|
||||||
|
|||||||
@@ -199,9 +199,16 @@ export class ListParticle {
|
|||||||
height: height * scale
|
height: height * scale
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.draw
|
this.draw.getCheckboxParticle().render({
|
||||||
.getCheckboxParticle()
|
ctx,
|
||||||
.render(ctx, checkboxRowElement, x - gap * scale, y)
|
x: x - gap * scale,
|
||||||
|
y,
|
||||||
|
index: 0,
|
||||||
|
row: {
|
||||||
|
...row,
|
||||||
|
elementList: [checkboxRowElement, ...row.elementList]
|
||||||
|
}
|
||||||
|
})
|
||||||
} else {
|
} else {
|
||||||
let text = ''
|
let text = ''
|
||||||
if (startElement.listType === ListType.UL) {
|
if (startElement.listType === ListType.UL) {
|
||||||
|
|||||||
@@ -1,9 +1,19 @@
|
|||||||
|
import { NBSP, ZERO } from '../../../dataset/constant/Common'
|
||||||
|
import { VerticalAlign } from '../../../dataset/enum/VerticalAlign'
|
||||||
import { DeepRequired } from '../../../interface/Common'
|
import { DeepRequired } from '../../../interface/Common'
|
||||||
import { IEditorOption } from '../../../interface/Editor'
|
import { IEditorOption } from '../../../interface/Editor'
|
||||||
import { IElement } from '../../../interface/Element'
|
import { IElement } from '../../../interface/Element'
|
||||||
import { IRowElement } from '../../../interface/Row'
|
import { IRow, IRowElement } from '../../../interface/Row'
|
||||||
import { Draw } from '../Draw'
|
import { Draw } from '../Draw'
|
||||||
|
|
||||||
|
interface IRadioRenderOption {
|
||||||
|
ctx: CanvasRenderingContext2D
|
||||||
|
x: number
|
||||||
|
y: number
|
||||||
|
row: IRow
|
||||||
|
index: number
|
||||||
|
}
|
||||||
|
|
||||||
export class RadioParticle {
|
export class RadioParticle {
|
||||||
private draw: Draw
|
private draw: Draw
|
||||||
private options: DeepRequired<IEditorOption>
|
private options: DeepRequired<IEditorOption>
|
||||||
@@ -28,17 +38,41 @@ export class RadioParticle {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
public render(
|
public render(payload: IRadioRenderOption) {
|
||||||
ctx: CanvasRenderingContext2D,
|
const { ctx, x, index, row } = payload
|
||||||
element: IRowElement,
|
let { y } = payload
|
||||||
x: number,
|
|
||||||
y: number
|
|
||||||
) {
|
|
||||||
const {
|
const {
|
||||||
radio: { gap, lineWidth, fillStyle, strokeStyle },
|
radio: { gap, lineWidth, fillStyle, strokeStyle, verticalAlign },
|
||||||
scale
|
scale
|
||||||
} = this.options
|
} = this.options
|
||||||
const { metrics, radio } = element
|
const { metrics, radio } = row.elementList[index]
|
||||||
|
// 垂直布局设置
|
||||||
|
if (
|
||||||
|
verticalAlign === VerticalAlign.TOP ||
|
||||||
|
verticalAlign === VerticalAlign.MIDDLE
|
||||||
|
) {
|
||||||
|
let nextIndex = index + 1
|
||||||
|
let nextElement: IRowElement | null = null
|
||||||
|
while (nextIndex < row.elementList.length) {
|
||||||
|
nextElement = row.elementList[nextIndex]
|
||||||
|
if (nextElement.value !== ZERO && nextElement.value !== NBSP) break
|
||||||
|
nextIndex++
|
||||||
|
}
|
||||||
|
// 以后一个非空格元素为基准
|
||||||
|
if (nextElement) {
|
||||||
|
const {
|
||||||
|
metrics: { boundingBoxAscent, boundingBoxDescent }
|
||||||
|
} = nextElement
|
||||||
|
const textHeight = boundingBoxAscent + boundingBoxDescent
|
||||||
|
if (textHeight > metrics.height) {
|
||||||
|
if (verticalAlign === VerticalAlign.TOP) {
|
||||||
|
y -= boundingBoxAscent - metrics.height
|
||||||
|
} else if (verticalAlign === VerticalAlign.MIDDLE) {
|
||||||
|
y -= (textHeight - metrics.height) / 2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
// left top 四舍五入避免1像素问题
|
// left top 四舍五入避免1像素问题
|
||||||
const left = Math.round(x + gap * scale)
|
const left = Math.round(x + gap * scale)
|
||||||
const top = Math.round(y - metrics.height + lineWidth)
|
const top = Math.round(y - metrics.height + lineWidth)
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
import { ElementType } from '../../../../dataset/enum/Element'
|
import { ElementType } from '../../../../dataset/enum/Element'
|
||||||
|
import { DeepRequired } from '../../../../interface/Common'
|
||||||
|
import { IEditorOption } from '../../../../interface/Editor'
|
||||||
import { IElement, IElementPosition } from '../../../../interface/Element'
|
import { IElement, IElementPosition } from '../../../../interface/Element'
|
||||||
import { formatElementContext } from '../../../../utils/element'
|
import { formatElementContext } from '../../../../utils/element'
|
||||||
import { RangeManager } from '../../../range/RangeManager'
|
import { RangeManager } from '../../../range/RangeManager'
|
||||||
@@ -9,9 +11,11 @@ export class DateParticle {
|
|||||||
private draw: Draw
|
private draw: Draw
|
||||||
private range: RangeManager
|
private range: RangeManager
|
||||||
private datePicker: DatePicker
|
private datePicker: DatePicker
|
||||||
|
private options: DeepRequired<IEditorOption>
|
||||||
|
|
||||||
constructor(draw: Draw) {
|
constructor(draw: Draw) {
|
||||||
this.draw = draw
|
this.draw = draw
|
||||||
|
this.options = draw.getOptions()
|
||||||
this.range = draw.getRange()
|
this.range = draw.getRange()
|
||||||
this.datePicker = new DatePicker(draw, {
|
this.datePicker = new DatePicker(draw, {
|
||||||
onSubmit: this._setValue.bind(this)
|
onSubmit: this._setValue.bind(this)
|
||||||
@@ -43,7 +47,9 @@ export class DateParticle {
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
formatElementContext(elementList, [dateElement], leftIndex)
|
formatElementContext(elementList, [dateElement], leftIndex, {
|
||||||
|
editorOptions: this.options
|
||||||
|
})
|
||||||
this.draw.insertElementList([dateElement])
|
this.draw.insertElementList([dateElement])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -30,11 +30,15 @@ export function input(data: string, host: CanvasEvent) {
|
|||||||
const elementList = draw.getElementList()
|
const elementList = draw.getElementList()
|
||||||
const copyElement = getAnchorElement(elementList, endIndex)
|
const copyElement = getAnchorElement(elementList, endIndex)
|
||||||
if (!copyElement) return
|
if (!copyElement) return
|
||||||
|
const isDesignMode = draw.isDesignMode()
|
||||||
const inputData: IElement[] = splitText(text).map(value => {
|
const inputData: IElement[] = splitText(text).map(value => {
|
||||||
const newElement: IElement = {
|
const newElement: IElement = {
|
||||||
value
|
value
|
||||||
}
|
}
|
||||||
if (!copyElement.title?.disabled && !copyElement.control?.disabled) {
|
if (
|
||||||
|
isDesignMode ||
|
||||||
|
(!copyElement.title?.disabled && !copyElement.control?.disabled)
|
||||||
|
) {
|
||||||
const nextElement = elementList[endIndex + 1]
|
const nextElement = elementList[endIndex + 1]
|
||||||
if (
|
if (
|
||||||
!copyElement.type ||
|
!copyElement.type ||
|
||||||
@@ -69,7 +73,9 @@ export function input(data: string, host: CanvasEvent) {
|
|||||||
if (startIndex !== endIndex) {
|
if (startIndex !== endIndex) {
|
||||||
draw.spliceElementList(elementList, start, endIndex - startIndex)
|
draw.spliceElementList(elementList, start, endIndex - startIndex)
|
||||||
}
|
}
|
||||||
formatElementContext(elementList, inputData, startIndex)
|
formatElementContext(elementList, inputData, startIndex, {
|
||||||
|
editorOptions: draw.getOptions()
|
||||||
|
})
|
||||||
draw.spliceElementList(elementList, start, 0, ...inputData)
|
draw.spliceElementList(elementList, start, 0, ...inputData)
|
||||||
curIndex = startIndex + inputData.length
|
curIndex = startIndex + inputData.length
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,7 +40,8 @@ export function enter(evt: KeyboardEvent, host: CanvasEvent) {
|
|||||||
}
|
}
|
||||||
// 格式化上下文
|
// 格式化上下文
|
||||||
formatElementContext(elementList, [enterText], startIndex, {
|
formatElementContext(elementList, [enterText], startIndex, {
|
||||||
isBreakWhenWrap: true
|
isBreakWhenWrap: true,
|
||||||
|
editorOptions: draw.getOptions()
|
||||||
})
|
})
|
||||||
// 标题结尾处回车无需格式化及样式复制
|
// 标题结尾处回车无需格式化及样式复制
|
||||||
if (
|
if (
|
||||||
|
|||||||
@@ -25,7 +25,9 @@ export function tab(evt: KeyboardEvent, host: CanvasEvent) {
|
|||||||
const rangeManager = draw.getRange()
|
const rangeManager = draw.getRange()
|
||||||
const { startIndex } = rangeManager.getRange()
|
const { startIndex } = rangeManager.getRange()
|
||||||
const elementList = draw.getElementList()
|
const elementList = draw.getElementList()
|
||||||
formatElementContext(elementList, [tabElement], startIndex)
|
formatElementContext(elementList, [tabElement], startIndex, {
|
||||||
|
editorOptions: draw.getOptions()
|
||||||
|
})
|
||||||
draw.insertElementList([tabElement])
|
draw.insertElementList([tabElement])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,12 +2,16 @@ import { ImageDisplay } from '../../../dataset/enum/Common'
|
|||||||
import { EditorMode } from '../../../dataset/enum/Editor'
|
import { EditorMode } from '../../../dataset/enum/Editor'
|
||||||
import { ElementType } from '../../../dataset/enum/Element'
|
import { ElementType } from '../../../dataset/enum/Element'
|
||||||
import { MouseEventButton } from '../../../dataset/enum/Event'
|
import { MouseEventButton } from '../../../dataset/enum/Event'
|
||||||
|
import { ControlComponent } from '../../../dataset/enum/Control'
|
||||||
|
import { ControlType } from '../../../dataset/enum/Control'
|
||||||
import { IPreviewerDrawOption } from '../../../interface/Previewer'
|
import { IPreviewerDrawOption } from '../../../interface/Previewer'
|
||||||
import { deepClone } from '../../../utils'
|
import { deepClone } from '../../../utils'
|
||||||
import { isMod } from '../../../utils/hotkey'
|
import { isMod } from '../../../utils/hotkey'
|
||||||
import { CheckboxControl } from '../../draw/control/checkbox/CheckboxControl'
|
import { CheckboxControl } from '../../draw/control/checkbox/CheckboxControl'
|
||||||
import { RadioControl } from '../../draw/control/radio/RadioControl'
|
import { RadioControl } from '../../draw/control/radio/RadioControl'
|
||||||
import { CanvasEvent } from '../CanvasEvent'
|
import { CanvasEvent } from '../CanvasEvent'
|
||||||
|
import { IElement } from '../../../interface/Element'
|
||||||
|
import { Draw } from '../../draw/Draw'
|
||||||
|
|
||||||
export function setRangeCache(host: CanvasEvent) {
|
export function setRangeCache(host: CanvasEvent) {
|
||||||
const draw = host.getDraw()
|
const draw = host.getDraw()
|
||||||
@@ -21,6 +25,42 @@ export function setRangeCache(host: CanvasEvent) {
|
|||||||
host.cachePositionContext = position.getPositionContext()
|
host.cachePositionContext = position.getPositionContext()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function hitCheckbox(element: IElement, draw: Draw) {
|
||||||
|
const { checkbox, control } = element
|
||||||
|
// 复选框不在控件内独立控制
|
||||||
|
if (!control) {
|
||||||
|
draw.getCheckboxParticle().setSelect(element)
|
||||||
|
} else {
|
||||||
|
const codes = control?.code ? control.code.split(',') : []
|
||||||
|
if (checkbox?.value) {
|
||||||
|
const codeIndex = codes.findIndex(c => c === checkbox.code)
|
||||||
|
codes.splice(codeIndex, 1)
|
||||||
|
} else {
|
||||||
|
if (checkbox?.code) {
|
||||||
|
codes.push(checkbox.code)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const activeControl = draw.getControl().getActiveControl()
|
||||||
|
if (activeControl instanceof CheckboxControl) {
|
||||||
|
activeControl.setSelect(codes)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function hitRadio(element: IElement, draw: Draw) {
|
||||||
|
const { radio, control } = element
|
||||||
|
// 单选框不在控件内独立控制
|
||||||
|
if (!control) {
|
||||||
|
draw.getRadioParticle().setSelect(element)
|
||||||
|
} else {
|
||||||
|
const codes = radio?.code ? [radio.code] : []
|
||||||
|
const activeControl = draw.getControl().getActiveControl()
|
||||||
|
if (activeControl instanceof RadioControl) {
|
||||||
|
activeControl.setSelect(codes)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export function mousedown(evt: MouseEvent, host: CanvasEvent) {
|
export function mousedown(evt: MouseEvent, host: CanvasEvent) {
|
||||||
if (evt.button === MouseEventButton.RIGHT) return
|
if (evt.button === MouseEventButton.RIGHT) return
|
||||||
const draw = host.getDraw()
|
const draw = host.getDraw()
|
||||||
@@ -100,40 +140,27 @@ export function mousedown(evt: MouseEvent, host: CanvasEvent) {
|
|||||||
rangeManager.setRange(startIndex, endIndex)
|
rangeManager.setRange(startIndex, endIndex)
|
||||||
position.setCursorPosition(positionList[curIndex])
|
position.setCursorPosition(positionList[curIndex])
|
||||||
// 复选框
|
// 复选框
|
||||||
const isSetCheckbox = isDirectHitCheckbox && !isReadonly
|
if (isDirectHitCheckbox && !isReadonly) {
|
||||||
// 单选框
|
hitCheckbox(curElement, draw)
|
||||||
const isSetRadio = isDirectHitRadio && !isReadonly
|
} else if (isDirectHitRadio && !isReadonly) {
|
||||||
if (isSetCheckbox) {
|
hitRadio(curElement, draw)
|
||||||
const { checkbox, control } = curElement
|
} else if (
|
||||||
// 复选框不在控件内独立控制
|
curElement.controlComponent === ControlComponent.VALUE &&
|
||||||
if (!control) {
|
(curElement.control?.type === ControlType.CHECKBOX ||
|
||||||
draw.getCheckboxParticle().setSelect(curElement)
|
curElement.control?.type === ControlType.RADIO)
|
||||||
} else {
|
) {
|
||||||
const codes = control?.code ? control.code.split(',') : []
|
// 向左查找
|
||||||
if (checkbox?.value) {
|
let preIndex = curIndex
|
||||||
const codeIndex = codes.findIndex(c => c === checkbox.code)
|
while (preIndex > 0) {
|
||||||
codes.splice(codeIndex, 1)
|
const preElement = elementList[preIndex]
|
||||||
} else {
|
if (preElement.controlComponent === ControlComponent.CHECKBOX) {
|
||||||
if (checkbox?.code) {
|
hitCheckbox(preElement, draw)
|
||||||
codes.push(checkbox.code)
|
break
|
||||||
}
|
} else if (preElement.controlComponent === ControlComponent.RADIO) {
|
||||||
}
|
hitRadio(preElement, draw)
|
||||||
const activeControl = draw.getControl().getActiveControl()
|
break
|
||||||
if (activeControl instanceof CheckboxControl) {
|
|
||||||
activeControl.setSelect(codes)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (isSetRadio) {
|
|
||||||
const { control, radio } = curElement
|
|
||||||
// 单选框不在控件内独立控制
|
|
||||||
if (!control) {
|
|
||||||
draw.getRadioParticle().setSelect(curElement)
|
|
||||||
} else {
|
|
||||||
const codes = radio?.code ? [radio.code] : []
|
|
||||||
const activeControl = draw.getControl().getActiveControl()
|
|
||||||
if (activeControl instanceof RadioControl) {
|
|
||||||
activeControl.setSelect(codes)
|
|
||||||
}
|
}
|
||||||
|
preIndex--
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
draw.render({
|
draw.render({
|
||||||
|
|||||||
@@ -176,7 +176,9 @@ export function mouseup(evt: MouseEvent, host: CanvasEvent) {
|
|||||||
return newElement
|
return newElement
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
formatElementContext(elementList, replaceElementList, range.startIndex)
|
formatElementContext(elementList, replaceElementList, range.startIndex, {
|
||||||
|
editorOptions: draw.getOptions()
|
||||||
|
})
|
||||||
// 缓存拖拽选区开始元素、位置、开始结束id
|
// 缓存拖拽选区开始元素、位置、开始结束id
|
||||||
const cacheStartElement = cacheElementList[cacheStartIndex]
|
const cacheStartElement = cacheElementList[cacheStartIndex]
|
||||||
const cacheStartPosition = cachePositionList[cacheStartIndex]
|
const cacheStartPosition = cachePositionList[cacheStartIndex]
|
||||||
|
|||||||
@@ -50,7 +50,8 @@ export function pasteElement(host: CanvasEvent, elementList: IElement[]) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
formatElementContext(originalElementList, elementList, startIndex, {
|
formatElementContext(originalElementList, elementList, startIndex, {
|
||||||
isBreakWhenWrap: true
|
isBreakWhenWrap: true,
|
||||||
|
editorOptions: draw.getOptions()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
draw.insertElementList(elementList)
|
draw.insertElementList(elementList)
|
||||||
@@ -87,7 +88,9 @@ export function pasteImage(host: CanvasEvent, file: File | Blob) {
|
|||||||
height: image.height
|
height: image.height
|
||||||
}
|
}
|
||||||
if (~startIndex) {
|
if (~startIndex) {
|
||||||
formatElementContext(elementList, [imageElement], startIndex)
|
formatElementContext(elementList, [imageElement], startIndex, {
|
||||||
|
editorOptions: draw.getOptions()
|
||||||
|
})
|
||||||
}
|
}
|
||||||
draw.insertElementList([imageElement])
|
draw.insertElementList([imageElement])
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -430,7 +430,7 @@ export class RangeManager {
|
|||||||
const color = curElement.color || null
|
const color = curElement.color || null
|
||||||
const highlight = curElement.highlight || null
|
const highlight = curElement.highlight || null
|
||||||
const rowFlex = curElement.rowFlex || null
|
const rowFlex = curElement.rowFlex || null
|
||||||
const rowMargin = curElement.rowMargin || this.options.defaultRowMargin
|
const rowMargin = curElement.rowMargin ?? this.options.defaultRowMargin
|
||||||
const dashArray = curElement.dashArray || []
|
const dashArray = curElement.dashArray || []
|
||||||
const level = curElement.level || null
|
const level = curElement.level || null
|
||||||
const listType = curElement.listType || null
|
const listType = curElement.listType || null
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { ICheckboxOption } from '../../interface/Checkbox'
|
import { ICheckboxOption } from '../../interface/Checkbox'
|
||||||
|
import { VerticalAlign } from '../enum/VerticalAlign'
|
||||||
|
|
||||||
export const defaultCheckboxOption: Readonly<Required<ICheckboxOption>> = {
|
export const defaultCheckboxOption: Readonly<Required<ICheckboxOption>> = {
|
||||||
width: 14,
|
width: 14,
|
||||||
@@ -6,5 +7,6 @@ export const defaultCheckboxOption: Readonly<Required<ICheckboxOption>> = {
|
|||||||
gap: 5,
|
gap: 5,
|
||||||
lineWidth: 1,
|
lineWidth: 1,
|
||||||
fillStyle: '#5175f4',
|
fillStyle: '#5175f4',
|
||||||
strokeStyle: '#ffffff'
|
strokeStyle: '#ffffff',
|
||||||
|
verticalAlign: VerticalAlign.BOTTOM
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,8 @@
|
|||||||
|
import { IPageBorderOption } from '../../interface/PageBorder'
|
||||||
|
|
||||||
|
export const defaultPageBorderOption: Readonly<Required<IPageBorderOption>> = {
|
||||||
|
color: '#000000',
|
||||||
|
lineWidth: 1,
|
||||||
|
padding: [0, 5, 0, 5],
|
||||||
|
disabled: true
|
||||||
|
}
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
import { IRadioOption } from '../../interface/Radio'
|
import { IRadioOption } from '../../interface/Radio'
|
||||||
|
import { VerticalAlign } from '../enum/VerticalAlign'
|
||||||
|
|
||||||
export const defaultRadioOption: Readonly<Required<IRadioOption>> = {
|
export const defaultRadioOption: Readonly<Required<IRadioOption>> = {
|
||||||
width: 14,
|
width: 14,
|
||||||
@@ -6,5 +7,6 @@ export const defaultRadioOption: Readonly<Required<IRadioOption>> = {
|
|||||||
gap: 5,
|
gap: 5,
|
||||||
lineWidth: 1,
|
lineWidth: 1,
|
||||||
fillStyle: '#5175f4',
|
fillStyle: '#5175f4',
|
||||||
strokeStyle: '#000000'
|
strokeStyle: '#000000',
|
||||||
|
verticalAlign: VerticalAlign.BOTTOM
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,7 +19,8 @@ export enum EditorMode {
|
|||||||
CLEAN = 'clean', // 清洁模式(隐藏辅助元素)
|
CLEAN = 'clean', // 清洁模式(隐藏辅助元素)
|
||||||
READONLY = 'readonly', // 只读模式(文档不可编辑)
|
READONLY = 'readonly', // 只读模式(文档不可编辑)
|
||||||
FORM = 'form', // 表单模式(仅控件内可编辑)
|
FORM = 'form', // 表单模式(仅控件内可编辑)
|
||||||
PRINT = 'print' // 打印模式(文档不可编辑、隐藏辅助元素、选区、未书写控件及边框)
|
PRINT = 'print', // 打印模式(文档不可编辑、隐藏辅助元素、选区、未书写控件及边框)
|
||||||
|
DESIGN = 'design' // 设计模式(不可删除、只读等配置不控制)
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum EditorZone {
|
export enum EditorZone {
|
||||||
|
|||||||
+2
-1
@@ -89,7 +89,8 @@ export default class Editor {
|
|||||||
]
|
]
|
||||||
pageComponentData.forEach(elementList => {
|
pageComponentData.forEach(elementList => {
|
||||||
formatElementList(elementList, {
|
formatElementList(elementList, {
|
||||||
editorOptions
|
editorOptions,
|
||||||
|
isForceCompensation: true
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
// 监听
|
// 监听
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
import { VerticalAlign } from '../dataset/enum/VerticalAlign'
|
||||||
|
|
||||||
export interface ICheckbox {
|
export interface ICheckbox {
|
||||||
value: boolean | null
|
value: boolean | null
|
||||||
code?: string
|
code?: string
|
||||||
@@ -11,4 +13,5 @@ export interface ICheckboxOption {
|
|||||||
lineWidth?: number
|
lineWidth?: number
|
||||||
fillStyle?: string
|
fillStyle?: string
|
||||||
strokeStyle?: string
|
strokeStyle?: string
|
||||||
|
verticalAlign?: VerticalAlign
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { IElement } from '..'
|
import { IElement, LocationPosition } from '..'
|
||||||
import {
|
import {
|
||||||
EditorMode,
|
EditorMode,
|
||||||
PageMode,
|
PageMode,
|
||||||
@@ -25,6 +25,7 @@ import { IZoneOption } from './Zone'
|
|||||||
import { ISeparatorOption } from './Separator'
|
import { ISeparatorOption } from './Separator'
|
||||||
import { ITableOption } from './table/Table'
|
import { ITableOption } from './table/Table'
|
||||||
import { ILineNumberOption } from './LineNumber'
|
import { ILineNumberOption } from './LineNumber'
|
||||||
|
import { IPageBorderOption } from './PageBorder'
|
||||||
|
|
||||||
export interface IEditorData {
|
export interface IEditorData {
|
||||||
header?: IElement[]
|
header?: IElement[]
|
||||||
@@ -91,6 +92,7 @@ export interface IEditorOption {
|
|||||||
lineBreak?: ILineBreakOption
|
lineBreak?: ILineBreakOption
|
||||||
separator?: ISeparatorOption
|
separator?: ISeparatorOption
|
||||||
lineNumber?: ILineNumberOption
|
lineNumber?: ILineNumberOption
|
||||||
|
pageBorder?: IPageBorderOption
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IEditorResult {
|
export interface IEditorResult {
|
||||||
@@ -123,3 +125,7 @@ export type IUpdateOption = Omit<
|
|||||||
export interface ISetValueOption {
|
export interface ISetValueOption {
|
||||||
isSetCursor?: boolean
|
isSetCursor?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface IFocusOption {
|
||||||
|
position?: LocationPosition
|
||||||
|
}
|
||||||
|
|||||||
@@ -0,0 +1,8 @@
|
|||||||
|
import { IPadding } from './Common'
|
||||||
|
|
||||||
|
export interface IPageBorderOption {
|
||||||
|
color?: string
|
||||||
|
lineWidth?: number
|
||||||
|
padding?: IPadding
|
||||||
|
disabled?: boolean
|
||||||
|
}
|
||||||
@@ -1,3 +1,5 @@
|
|||||||
|
import { VerticalAlign } from '../dataset/enum/VerticalAlign'
|
||||||
|
|
||||||
export interface IRadio {
|
export interface IRadio {
|
||||||
value: boolean | null
|
value: boolean | null
|
||||||
code?: string
|
code?: string
|
||||||
@@ -11,4 +13,5 @@ export interface IRadioOption {
|
|||||||
lineWidth?: number
|
lineWidth?: number
|
||||||
fillStyle?: string
|
fillStyle?: string
|
||||||
strokeStyle?: string
|
strokeStyle?: string
|
||||||
|
verticalAlign?: VerticalAlign
|
||||||
}
|
}
|
||||||
|
|||||||
+30
-19
@@ -9,6 +9,7 @@ import {
|
|||||||
splitText
|
splitText
|
||||||
} from '.'
|
} from '.'
|
||||||
import {
|
import {
|
||||||
|
EditorMode,
|
||||||
ElementType,
|
ElementType,
|
||||||
IEditorOption,
|
IEditorOption,
|
||||||
IElement,
|
IElement,
|
||||||
@@ -65,7 +66,8 @@ export function unzipElementList(elementList: IElement[]): IElement[] {
|
|||||||
}
|
}
|
||||||
|
|
||||||
interface IFormatElementListOption {
|
interface IFormatElementListOption {
|
||||||
isHandleFirstElement?: boolean
|
isHandleFirstElement?: boolean // 根据上下文确定首字符处理逻辑(处理首字符补偿)
|
||||||
|
isForceCompensation?: boolean // 强制补偿字符
|
||||||
editorOptions: DeepRequired<IEditorOption>
|
editorOptions: DeepRequired<IEditorOption>
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -73,17 +75,19 @@ export function formatElementList(
|
|||||||
elementList: IElement[],
|
elementList: IElement[],
|
||||||
options: IFormatElementListOption
|
options: IFormatElementListOption
|
||||||
) {
|
) {
|
||||||
const { isHandleFirstElement, editorOptions } = <IFormatElementListOption>{
|
const {
|
||||||
isHandleFirstElement: true,
|
isHandleFirstElement = true,
|
||||||
...options
|
isForceCompensation = false,
|
||||||
}
|
editorOptions
|
||||||
|
} = options
|
||||||
const startElement = elementList[0]
|
const startElement = elementList[0]
|
||||||
// 非首字符零宽节点文本元素则补偿-列表元素内部会补偿此处忽略
|
// 非首字符零宽节点文本元素则补偿-列表元素内部会补偿此处忽略
|
||||||
if (
|
if (
|
||||||
isHandleFirstElement &&
|
isForceCompensation ||
|
||||||
startElement?.type !== ElementType.LIST &&
|
(isHandleFirstElement &&
|
||||||
((startElement?.type && startElement.type !== ElementType.TEXT) ||
|
startElement?.type !== ElementType.LIST &&
|
||||||
!START_LINE_BREAK_REG.test(startElement?.value))
|
((startElement?.type && startElement.type !== ElementType.TEXT) ||
|
||||||
|
!START_LINE_BREAK_REG.test(startElement?.value)))
|
||||||
) {
|
) {
|
||||||
elementList.unshift({
|
elementList.unshift({
|
||||||
value: ZERO
|
value: ZERO
|
||||||
@@ -100,7 +104,8 @@ export function formatElementList(
|
|||||||
const valueList = el.valueList || []
|
const valueList = el.valueList || []
|
||||||
formatElementList(valueList, {
|
formatElementList(valueList, {
|
||||||
...options,
|
...options,
|
||||||
isHandleFirstElement: false
|
isHandleFirstElement: false,
|
||||||
|
isForceCompensation: false
|
||||||
})
|
})
|
||||||
// 追加节点
|
// 追加节点
|
||||||
if (valueList.length) {
|
if (valueList.length) {
|
||||||
@@ -134,7 +139,8 @@ export function formatElementList(
|
|||||||
const valueList = el.valueList || []
|
const valueList = el.valueList || []
|
||||||
formatElementList(valueList, {
|
formatElementList(valueList, {
|
||||||
...options,
|
...options,
|
||||||
isHandleFirstElement: true
|
isHandleFirstElement: true,
|
||||||
|
isForceCompensation: false
|
||||||
})
|
})
|
||||||
// 追加节点
|
// 追加节点
|
||||||
if (valueList.length) {
|
if (valueList.length) {
|
||||||
@@ -170,7 +176,8 @@ export function formatElementList(
|
|||||||
td.id = tdId
|
td.id = tdId
|
||||||
formatElementList(td.value, {
|
formatElementList(td.value, {
|
||||||
...options,
|
...options,
|
||||||
isHandleFirstElement: true
|
isHandleFirstElement: true,
|
||||||
|
isForceCompensation: true
|
||||||
})
|
})
|
||||||
for (let v = 0; v < td.value.length; v++) {
|
for (let v = 0; v < td.value.length; v++) {
|
||||||
const value = td.value[v]
|
const value = td.value[v]
|
||||||
@@ -385,7 +392,8 @@ export function formatElementList(
|
|||||||
}
|
}
|
||||||
formatElementList(valueList, {
|
formatElementList(valueList, {
|
||||||
...options,
|
...options,
|
||||||
isHandleFirstElement: false
|
isHandleFirstElement: false,
|
||||||
|
isForceCompensation: false
|
||||||
})
|
})
|
||||||
for (let v = 0; v < valueList.length; v++) {
|
for (let v = 0; v < valueList.length; v++) {
|
||||||
const element = valueList[v]
|
const element = valueList[v]
|
||||||
@@ -451,7 +459,7 @@ export function formatElementList(
|
|||||||
}
|
}
|
||||||
el = elementList[i]
|
el = elementList[i]
|
||||||
}
|
}
|
||||||
if (el.value === '\n') {
|
if (el.value === '\n' || el.value == '\r\n') {
|
||||||
el.value = ZERO
|
el.value = ZERO
|
||||||
}
|
}
|
||||||
if (el.type === ElementType.IMAGE || el.type === ElementType.BLOCK) {
|
if (el.type === ElementType.IMAGE || el.type === ElementType.BLOCK) {
|
||||||
@@ -886,7 +894,8 @@ export function getAnchorElement(
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface IFormatElementContextOption {
|
export interface IFormatElementContextOption {
|
||||||
isBreakWhenWrap: boolean
|
isBreakWhenWrap?: boolean
|
||||||
|
editorOptions?: DeepRequired<IEditorOption>
|
||||||
}
|
}
|
||||||
|
|
||||||
export function formatElementContext(
|
export function formatElementContext(
|
||||||
@@ -897,11 +906,12 @@ export function formatElementContext(
|
|||||||
) {
|
) {
|
||||||
let copyElement = getAnchorElement(sourceElementList, anchorIndex)
|
let copyElement = getAnchorElement(sourceElementList, anchorIndex)
|
||||||
if (!copyElement) return
|
if (!copyElement) return
|
||||||
// 标题元素禁用时不复制标题属性
|
const { isBreakWhenWrap = false, editorOptions } = options || {}
|
||||||
if (copyElement.title?.disabled) {
|
const { mode } = editorOptions || {}
|
||||||
|
// 非设计模式时:标题元素禁用时不复制标题属性
|
||||||
|
if (mode !== EditorMode.DESIGN && copyElement.title?.disabled) {
|
||||||
copyElement = omitObject(copyElement, TITLE_CONTEXT_ATTR)
|
copyElement = omitObject(copyElement, TITLE_CONTEXT_ATTR)
|
||||||
}
|
}
|
||||||
const { isBreakWhenWrap = false } = options || {}
|
|
||||||
// 是否已经换行
|
// 是否已经换行
|
||||||
let isBreakWarped = false
|
let isBreakWarped = false
|
||||||
for (let e = 0; e < formatElementList.length; e++) {
|
for (let e = 0; e < formatElementList.length; e++) {
|
||||||
@@ -930,7 +940,8 @@ export function formatElementContext(
|
|||||||
formatElementContext(
|
formatElementContext(
|
||||||
sourceElementList,
|
sourceElementList,
|
||||||
targetElement.valueList,
|
targetElement.valueList,
|
||||||
anchorIndex
|
anchorIndex,
|
||||||
|
options
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
// 非块类元素,需处理行属性
|
// 非块类元素,需处理行属性
|
||||||
|
|||||||
@@ -37,6 +37,8 @@ import { ITitleOption } from '../interface/Title'
|
|||||||
import { IWatermark } from '../interface/Watermark'
|
import { IWatermark } from '../interface/Watermark'
|
||||||
import { IZoneOption } from '../interface/Zone'
|
import { IZoneOption } from '../interface/Zone'
|
||||||
import { ILineNumberOption } from '../interface/LineNumber'
|
import { ILineNumberOption } from '../interface/LineNumber'
|
||||||
|
import { IPageBorderOption } from '../interface/PageBorder'
|
||||||
|
import { defaultPageBorderOption } from '../dataset/constant/PageBorder'
|
||||||
import {
|
import {
|
||||||
EditorMode,
|
EditorMode,
|
||||||
PageMode,
|
PageMode,
|
||||||
@@ -120,6 +122,10 @@ export function mergeOption(
|
|||||||
...defaultLineNumberOption,
|
...defaultLineNumberOption,
|
||||||
...options.lineNumber
|
...options.lineNumber
|
||||||
}
|
}
|
||||||
|
const pageBorderOptions: Required<IPageBorderOption> = {
|
||||||
|
...defaultPageBorderOption,
|
||||||
|
...options.pageBorder
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
mode: EditorMode.EDIT,
|
mode: EditorMode.EDIT,
|
||||||
@@ -180,6 +186,7 @@ export function mergeOption(
|
|||||||
background: backgroundOptions,
|
background: backgroundOptions,
|
||||||
lineBreak: lineBreakOptions,
|
lineBreak: lineBreakOptions,
|
||||||
separator: separatorOptions,
|
separator: separatorOptions,
|
||||||
lineNumber: lineNumberOptions
|
lineNumber: lineNumberOptions,
|
||||||
|
pageBorder: pageBorderOptions
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1412,6 +1412,10 @@ window.onload = function () {
|
|||||||
{
|
{
|
||||||
mode: EditorMode.PRINT,
|
mode: EditorMode.PRINT,
|
||||||
name: '打印模式'
|
name: '打印模式'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
mode: EditorMode.DESIGN,
|
||||||
|
name: '设计模式'
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
const modeElement = document.querySelector<HTMLDivElement>('.editor-mode')!
|
const modeElement = document.querySelector<HTMLDivElement>('.editor-mode')!
|
||||||
|
|||||||
Reference in New Issue
Block a user