fix: IME position error #675
This commit is contained in:
@@ -51,6 +51,12 @@ body:
|
|||||||
label: What is actually happening?
|
label: What is actually happening?
|
||||||
validations:
|
validations:
|
||||||
required: true
|
required: true
|
||||||
|
- type: textarea
|
||||||
|
id: editor-value
|
||||||
|
attributes:
|
||||||
|
label: Editor Value
|
||||||
|
description: Output of `instance.command.getValue()`
|
||||||
|
render: json
|
||||||
- type: textarea
|
- type: textarea
|
||||||
id: system-info
|
id: system-info
|
||||||
attributes:
|
attributes:
|
||||||
|
|||||||
+104
@@ -1,3 +1,107 @@
|
|||||||
|
## [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)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* three click selection paragraph boundary error #742 ([9dd192f](https://github.com/Hufe921/canvas-editor/commit/9dd192ffd26f9f271efa06c81b6bd5e32557d872)), closes [#742](https://github.com/Hufe921/canvas-editor/issues/742)
|
||||||
|
|
||||||
|
|
||||||
|
### Documentation
|
||||||
|
|
||||||
|
* update plugin markdown ([c2d3e94](https://github.com/Hufe921/canvas-editor/commit/c2d3e941b19a6bc766b0bfa8dac7911578170b6c))
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* add id property to contextMenu context #737 ([997ecc0](https://github.com/Hufe921/canvas-editor/commit/997ecc03e89afeaaf6b903f9f253c5c5090b3f78)), closes [#737](https://github.com/Hufe921/canvas-editor/issues/737)
|
||||||
|
* add line number option #734 ([d89218a](https://github.com/Hufe921/canvas-editor/commit/d89218a916fce5a7b7b6bf27fa4663ecc4d15cf6)), closes [#734](https://github.com/Hufe921/canvas-editor/issues/734)
|
||||||
|
* control related apis support the control id property ([dd1b53e](https://github.com/Hufe921/canvas-editor/commit/dd1b53ee6297bc72b0064c09522b597118919c50))
|
||||||
|
* set range using the shift shortcut key #728 ([8878fd7](https://github.com/Hufe921/canvas-editor/commit/8878fd7734ae0a566f16ca2db14e64ded5a05f38)), closes [#728](https://github.com/Hufe921/canvas-editor/issues/728)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [0.9.88](https://github.com/Hufe921/canvas-editor/compare/v0.9.87...v0.9.88) (2024-08-02)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* float image position boundary error #716 ([f5113f5](https://github.com/Hufe921/canvas-editor/commit/f5113f539c5b224fdb9af8cde8e61f632dc7e49f)), closes [#716](https://github.com/Hufe921/canvas-editor/issues/716)
|
||||||
|
|
||||||
|
|
||||||
|
### Chores
|
||||||
|
|
||||||
|
* add touch support to signature component ([c3ef290](https://github.com/Hufe921/canvas-editor/commit/c3ef2907ae31be21cd3bc61a5600ad381230034f))
|
||||||
|
* update issue template ([eea301e](https://github.com/Hufe921/canvas-editor/commit/eea301eb11fdc3d5870da2408abccf4d96d8532f))
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* add applyPageNumbers attribute to background option #729 ([8d112a8](https://github.com/Hufe921/canvas-editor/commit/8d112a8518656edd14201cb9bd16a417752fcdf9)), closes [#729](https://github.com/Hufe921/canvas-editor/issues/729)
|
||||||
|
* add cursor setting option to executeSetValue api #715 ([3235e5a](https://github.com/Hufe921/canvas-editor/commit/3235e5ae386bd1f48f5f64427e1eb0ed3782838d)), closes [#715](https://github.com/Hufe921/canvas-editor/issues/715)
|
||||||
|
* add title disabled property #680 ([87a8dbe](https://github.com/Hufe921/canvas-editor/commit/87a8dbea1596bcdee28edbb58b02fbe2a36e6c58)), closes [#680](https://github.com/Hufe921/canvas-editor/issues/680)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [0.9.87](https://github.com/Hufe921/canvas-editor/compare/v0.9.86...v0.9.87) (2024-07-26)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* format of checkbox and radio control value ([72686fd](https://github.com/Hufe921/canvas-editor/commit/72686fda1bf12353699fd57273493d8a9b4caee4))
|
||||||
|
* highlight checkbox and radio control #707 ([d939aa3](https://github.com/Hufe921/canvas-editor/commit/d939aa35ba7b19e5d1b5c4121fb873b2c579cc55)), closes [#707](https://github.com/Hufe921/canvas-editor/issues/707)
|
||||||
|
* set control highlight limit component type ([e14fbd6](https://github.com/Hufe921/canvas-editor/commit/e14fbd622d1076cba5f34bd4fa29530af4f70261))
|
||||||
|
* update punctuation width when scaling the page #712 ([83cb479](https://github.com/Hufe921/canvas-editor/commit/83cb47913195c43cde2b3ae344ff1d89a223e6a6)), closes [#712](https://github.com/Hufe921/canvas-editor/issues/712)
|
||||||
|
* word breaking when scaling the page #666 ([2bd1f34](https://github.com/Hufe921/canvas-editor/commit/2bd1f34c15196968f69d4711613f1c81f1dade68)), closes [#666](https://github.com/Hufe921/canvas-editor/issues/666)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* add custom field to getValue api #699 ([67c63f8](https://github.com/Hufe921/canvas-editor/commit/67c63f856f2c0e3e8c0644e39694357639c18d7e)), closes [#699](https://github.com/Hufe921/canvas-editor/issues/699)
|
||||||
|
* delete cell contents when selecting rows and columns #706 ([ccd0627](https://github.com/Hufe921/canvas-editor/commit/ccd0627a6fad975acb43e9f16dda3fa13972c908)), closes [#706](https://github.com/Hufe921/canvas-editor/issues/706)
|
||||||
|
* optimize text selection at the beginning of a line #695 ([97ac2da](https://github.com/Hufe921/canvas-editor/commit/97ac2daaf8f0688b181cb8baea9ba74ae1664361)), closes [#695](https://github.com/Hufe921/canvas-editor/issues/695)
|
||||||
|
* set control properties in read-only mode #679 ([26a3468](https://github.com/Hufe921/canvas-editor/commit/26a3468f66d67bf8249cdc1a679c740d7cf1a9c9)), closes [#679](https://github.com/Hufe921/canvas-editor/issues/679)
|
||||||
|
* set the container scrollbar to automatically scroll #711 ([b226566](https://github.com/Hufe921/canvas-editor/commit/b226566e2bf6f1b4bc3ae11577c7a96ae3cbf2d0)), closes [#711](https://github.com/Hufe921/canvas-editor/issues/711)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## [0.9.86](https://github.com/Hufe921/canvas-editor/compare/v0.9.85...v0.9.86) (2024-07-13)
|
## [0.9.86](https://github.com/Hufe921/canvas-editor/compare/v0.9.85...v0.9.86) (2024-07-13)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -21,6 +21,10 @@ export default defineConfig({
|
|||||||
{
|
{
|
||||||
text: 'Demo',
|
text: 'Demo',
|
||||||
link: 'https://hufe.club/canvas-editor'
|
link: 'https://hufe.club/canvas-editor'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: '官方插件',
|
||||||
|
link: '/guide/plugin-internal.html'
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
sidebar: [
|
sidebar: [
|
||||||
@@ -71,7 +75,10 @@ export default defineConfig({
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
text: '插件',
|
text: '插件',
|
||||||
items: [{ text: '自定义插件', link: '/guide/plugin' }]
|
items: [
|
||||||
|
{ text: '自定义插件', link: '/guide/plugin-custom' },
|
||||||
|
{ text: '官方插件', link: '/guide/plugin-internal' }
|
||||||
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
socialLinks: [
|
socialLinks: [
|
||||||
@@ -104,6 +111,10 @@ export default defineConfig({
|
|||||||
{
|
{
|
||||||
text: 'Demo',
|
text: 'Demo',
|
||||||
link: 'https://hufe.club/canvas-editor'
|
link: 'https://hufe.club/canvas-editor'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: 'Official plugin',
|
||||||
|
link: '/en/guide/plugin-internal.html'
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
sidebar: [
|
sidebar: [
|
||||||
@@ -154,7 +165,10 @@ export default defineConfig({
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
text: 'Plugin',
|
text: 'Plugin',
|
||||||
items: [{ text: 'plugin', link: '/en/guide/plugin' }]
|
items: [
|
||||||
|
{ text: 'custom', link: '/en/guide/plugin-custom' },
|
||||||
|
{ text: 'official', link: '/en/guide/plugin-internal' }
|
||||||
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
@@ -789,7 +789,7 @@ Feature: Set the editor data
|
|||||||
Usage:
|
Usage:
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
instance.command.executeSetValue(payload: Partial<IEditorData>)
|
instance.command.executeSetValue(payload: Partial<IEditorData>, options?: ISetValueOption)
|
||||||
```
|
```
|
||||||
|
|
||||||
## executeRemoveControl
|
## executeRemoveControl
|
||||||
@@ -929,7 +929,7 @@ Feature: Positioning and activating control
|
|||||||
Usage:
|
Usage:
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
instance.command.executeLocationControl(controlId: string)
|
instance.command.executeLocationControl(controlId: string, options?: ILocationControlOption)
|
||||||
```
|
```
|
||||||
|
|
||||||
## executeInsertControl
|
## executeInsertControl
|
||||||
@@ -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)
|
||||||
|
```
|
||||||
|
|||||||
+29
-3
@@ -60,17 +60,19 @@ 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
|
||||||
group?: IGroup // Group option. {opacity?:number; backgroundColor?:string; activeOpacity?:number; activeBackgroundColor?:string; disabled?:boolean}
|
group?: IGroup // Group option. {opacity?:number; backgroundColor?:string; activeOpacity?:number; activeBackgroundColor?:string; disabled?:boolean}
|
||||||
pageBreak?: IPageBreak // PageBreak option。{font?:string; fontSize?:number; lineDash?:number[];}
|
pageBreak?: IPageBreak // PageBreak option。{font?:string; fontSize?:number; lineDash?:number[];}
|
||||||
zone?: IZoneOption // Zone option。{tipDisabled?:boolean;}
|
zone?: IZoneOption // Zone option。{tipDisabled?:boolean;}
|
||||||
background?: IBackgroundOption // Background option. {color?:string; image?:string; size?:BackgroundSize; repeat?:BackgroundRepeat;}。default: {color: '#FFFFFF'}
|
background?: IBackgroundOption // Background option. {color?:string; image?:string; size?:BackgroundSize; repeat?:BackgroundRepeat; applyPageNumbers?:number[]}。default: {color: '#FFFFFF'}
|
||||||
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}
|
||||||
|
pageBorder?: IPageBorderOption // PageBorder option. {color?:string; lineWidth:number; padding?:IPadding; disabled?:boolean;}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -145,3 +147,27 @@ interface IPlaceholder {
|
|||||||
font?: string // font. default: Microsoft YaHei
|
font?: string // font. default: Microsoft YaHei
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## LineNumber Configuration
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
interface ILineNumberOption {
|
||||||
|
size?: number // font size. default: 12
|
||||||
|
font?: string // font. default: Microsoft YaHei
|
||||||
|
color?: string // color. default: #000000
|
||||||
|
disabled?: boolean // Whether to disable. default: false
|
||||||
|
right?: number // Distance from the main text. default: 20
|
||||||
|
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
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|||||||
@@ -1,8 +1,7 @@
|
|||||||
# Custom Plugin
|
# Custom Plugin
|
||||||
|
|
||||||
::: tip
|
::: tip
|
||||||
1. Currently, only methods can be added and modified to the editor instance, and more functions will be extended in the future
|
Official plugin: https://github.com/Hufe921/canvas-editor-plugin
|
||||||
2. Official maintenance plugin: https://github.com/Hufe921/canvas-editor-plugin
|
|
||||||
:::
|
:::
|
||||||
|
|
||||||
## Write a Plugin
|
## Write a Plugin
|
||||||
@@ -14,11 +13,13 @@ export function myPlugin(editor: Editor, options?: Option) {
|
|||||||
|
|
||||||
// 2. add,see more:src/plugins/markdown
|
// 2. add,see more:src/plugins/markdown
|
||||||
editor.command.addFunction = () => {}
|
editor.command.addFunction = () => {}
|
||||||
|
|
||||||
|
// 3. listener, eventbus, shortcut, contextmenu, override...
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
## Use Plugin
|
## Use Plugin
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
instance.add(myPlugin, options?: Option)
|
instance.use(myPlugin, options?: Option)
|
||||||
```
|
```
|
||||||
@@ -0,0 +1,109 @@
|
|||||||
|
# Official plugin
|
||||||
|
|
||||||
|
::: tip
|
||||||
|
Official plugin: https://github.com/Hufe921/canvas-editor-plugin
|
||||||
|
:::
|
||||||
|
|
||||||
|
## Barcode1d
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
import Editor from "@hufe921/canvas-editor"
|
||||||
|
import barcode1DPlugin from "@hufe921/canvas-editor-plugin-barcode1d"
|
||||||
|
|
||||||
|
const instance = new Editor()
|
||||||
|
instance.use(barcode1DPlugin)
|
||||||
|
|
||||||
|
instance.executeInsertBarcode1D(
|
||||||
|
content: string,
|
||||||
|
width: number,
|
||||||
|
height: number,
|
||||||
|
options?: JsBarcode.Options
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
## Barcode2d
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
import Editor from "@hufe921/canvas-editor"
|
||||||
|
import barcode2DPlugin from "@hufe921/canvas-editor-plugin-barcode2d"
|
||||||
|
|
||||||
|
const instance = new Editor()
|
||||||
|
instance.use(barcode2DPlugin, options?: IBarcode2DOption)
|
||||||
|
|
||||||
|
instance.executeInsertBarcode2D(
|
||||||
|
content: string,
|
||||||
|
width: number,
|
||||||
|
height: number,
|
||||||
|
hints?: Map<EncodeHintType, any>
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
## Code block
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
import Editor from "@hufe921/canvas-editor"
|
||||||
|
import codeblockPlugin from "@hufe921/canvas-editor-plugin-codeblock"
|
||||||
|
|
||||||
|
const instance = new Editor()
|
||||||
|
instance.use(codeblockPlugin)
|
||||||
|
|
||||||
|
instance.executeInsertCodeblock(content: string)
|
||||||
|
```
|
||||||
|
|
||||||
|
## Word
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
import Editor from '@hufe921/canvas-editor'
|
||||||
|
import docxPlugin from '@hufe921/canvas-editor-plugin-docx'
|
||||||
|
|
||||||
|
const instance = new Editor()
|
||||||
|
instance.use(docxPlugin)
|
||||||
|
|
||||||
|
command.executeImportDocx({
|
||||||
|
arrayBuffer: buffer
|
||||||
|
})
|
||||||
|
|
||||||
|
instance.executeExportDocx({
|
||||||
|
fileName: string
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
## Excel
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
import Editor from '@hufe921/canvas-editor'
|
||||||
|
import excelPlugin from '@hufe921/canvas-editor-plugin-excel'
|
||||||
|
|
||||||
|
const instance = new Editor()
|
||||||
|
instance.use(excelPlugin)
|
||||||
|
|
||||||
|
command.executeImportExcel({
|
||||||
|
arrayBuffer: buffer
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
## Floating toolbar
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
import Editor from '@hufe921/canvas-editor'
|
||||||
|
import floatingToolbarPlugin from '@hufe921/canvas-editor-plugin-floating-toolbar'
|
||||||
|
|
||||||
|
const instance = new Editor()
|
||||||
|
instance.use(floatingToolbarPlugin)
|
||||||
|
```
|
||||||
|
|
||||||
|
## Diagram
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
import Editor from '@hufe921/canvas-editor'
|
||||||
|
import diagramPlugin from '@hufe921/canvas-editor-plugin-diagram'
|
||||||
|
|
||||||
|
const instance = new Editor()
|
||||||
|
instance.use(diagramPlugin)
|
||||||
|
|
||||||
|
command.executeLoadDiagram({
|
||||||
|
lang?: Lang
|
||||||
|
data?: string
|
||||||
|
onDestroy?: (message?: any) => void
|
||||||
|
})
|
||||||
|
```
|
||||||
@@ -157,6 +157,7 @@ interface IElement {
|
|||||||
title?: {
|
title?: {
|
||||||
conceptId?: string;
|
conceptId?: string;
|
||||||
deletable?: boolean;
|
deletable?: boolean;
|
||||||
|
disabled?: boolean;
|
||||||
};
|
};
|
||||||
// list
|
// list
|
||||||
listType?: ListType;
|
listType?: ListType;
|
||||||
|
|||||||
@@ -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
|
||||||
@@ -789,7 +789,7 @@ instance.command.executeUpdateElementById(payload: IUpdateElementByIdOption)
|
|||||||
用法:
|
用法:
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
instance.command.executeSetValue(payload: Partial<IEditorData>)
|
instance.command.executeSetValue(payload: Partial<IEditorData>, options?: ISetValueOption)
|
||||||
```
|
```
|
||||||
|
|
||||||
## executeRemoveControl
|
## executeRemoveControl
|
||||||
@@ -929,7 +929,7 @@ instance.command.executeSetControlHighlight(payload: ISetControlHighlightOption)
|
|||||||
用法:
|
用法:
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
instance.command.executeLocationControl(controlId: string)
|
instance.command.executeLocationControl(controlId: string, options?: ILocationControlOption)
|
||||||
```
|
```
|
||||||
|
|
||||||
## executeInsertControl
|
## executeInsertControl
|
||||||
@@ -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)
|
||||||
|
```
|
||||||
|
|||||||
+29
-3
@@ -60,17 +60,19 @@ 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 // 编辑器空白占位文本
|
||||||
group?: IGroup // 成组配置。{opacity?:number; backgroundColor?:string; activeOpacity?:number; activeBackgroundColor?:string; disabled?:boolean}
|
group?: IGroup // 成组配置。{opacity?:number; backgroundColor?:string; activeOpacity?:number; activeBackgroundColor?:string; disabled?:boolean}
|
||||||
pageBreak?: IPageBreak // 分页符配置。{font?:string; fontSize?:number; lineDash?:number[];}
|
pageBreak?: IPageBreak // 分页符配置。{font?:string; fontSize?:number; lineDash?:number[];}
|
||||||
zone?: IZoneOption // 编辑器区域配置。{tipDisabled?:boolean;}
|
zone?: IZoneOption // 编辑器区域配置。{tipDisabled?:boolean;}
|
||||||
background?: IBackgroundOption // 背景配置。{color?:string; image?:string; size?:BackgroundSize; repeat?:BackgroundRepeat;}。默认:{color: '#FFFFFF'}
|
background?: IBackgroundOption // 背景配置。{color?:string; image?:string; size?:BackgroundSize; repeat?:BackgroundRepeat; applyPageNumbers?:number[]}。默认:{color: '#FFFFFF'}
|
||||||
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}
|
||||||
|
pageBorder?: IPageBorderOption // 页面边框配置。{color?:string; lineWidth:number; padding?:IPadding; disabled?:boolean;}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -145,3 +147,27 @@ interface IPlaceholder {
|
|||||||
font?: string // 字体。默认:Microsoft YaHei
|
font?: string // 字体。默认:Microsoft YaHei
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## 行号配置
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
interface ILineNumberOption {
|
||||||
|
size?: number // 字体大小。默认:12
|
||||||
|
font?: string // 字体。默认:Microsoft YaHei
|
||||||
|
color?: string // 颜色。默认:#000000
|
||||||
|
disabled?: boolean // 是否禁用。默认:true
|
||||||
|
right?: number // 距离正文距离。默认:20
|
||||||
|
type?: LineNumberType // 编号类型(每页重新编号、连续编号)。默认:连续编号
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## 页面边框配置
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
interface IPageBorderOption {
|
||||||
|
color?: string // 颜色。默认:#000000
|
||||||
|
lineWidth?: number // 宽度。默认:1
|
||||||
|
padding?: IPadding // 距离正文内边距。默认:[0, 5, 0, 5]
|
||||||
|
disabled?: boolean // 是否禁用。默认:true
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|||||||
@@ -1,8 +1,7 @@
|
|||||||
# 自定义插件
|
# 自定义插件
|
||||||
|
|
||||||
::: tip
|
::: tip
|
||||||
1. 目前仅支持对编辑器实例进行方法的增加及修改,后续扩展更多功能
|
官方维护插件仓库:https://github.com/Hufe921/canvas-editor-plugin
|
||||||
2. 官方维护插件:https://github.com/Hufe921/canvas-editor-plugin
|
|
||||||
:::
|
:::
|
||||||
|
|
||||||
## 开发插件
|
## 开发插件
|
||||||
@@ -14,11 +13,13 @@ export function myPlugin(editor: Editor, options?: Option) {
|
|||||||
|
|
||||||
// 2. 增加方法,详见:src/plugins/markdown
|
// 2. 增加方法,详见:src/plugins/markdown
|
||||||
editor.command.addFunction = () => {}
|
editor.command.addFunction = () => {}
|
||||||
|
|
||||||
|
// 3. 事件监听、快捷键、右键菜单、重写方法等组合处理
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
## 使用插件
|
## 使用插件
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
instance.add(myPlugin, options?: Option)
|
instance.use(myPlugin, options?: Option)
|
||||||
```
|
```
|
||||||
@@ -0,0 +1,109 @@
|
|||||||
|
# 官方插件
|
||||||
|
|
||||||
|
::: tip
|
||||||
|
官方维护插件仓库:https://github.com/Hufe921/canvas-editor-plugin
|
||||||
|
:::
|
||||||
|
|
||||||
|
## 条形码
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
import Editor from "@hufe921/canvas-editor"
|
||||||
|
import barcode1DPlugin from "@hufe921/canvas-editor-plugin-barcode1d"
|
||||||
|
|
||||||
|
const instance = new Editor()
|
||||||
|
instance.use(barcode1DPlugin)
|
||||||
|
|
||||||
|
instance.executeInsertBarcode1D(
|
||||||
|
content: string,
|
||||||
|
width: number,
|
||||||
|
height: number,
|
||||||
|
options?: JsBarcode.Options
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
## 二维码
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
import Editor from "@hufe921/canvas-editor"
|
||||||
|
import barcode2DPlugin from "@hufe921/canvas-editor-plugin-barcode2d"
|
||||||
|
|
||||||
|
const instance = new Editor()
|
||||||
|
instance.use(barcode2DPlugin, options?: IBarcode2DOption)
|
||||||
|
|
||||||
|
instance.executeInsertBarcode2D(
|
||||||
|
content: string,
|
||||||
|
width: number,
|
||||||
|
height: number,
|
||||||
|
hints?: Map<EncodeHintType, any>
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
## 代码块
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
import Editor from "@hufe921/canvas-editor"
|
||||||
|
import codeblockPlugin from "@hufe921/canvas-editor-plugin-codeblock"
|
||||||
|
|
||||||
|
const instance = new Editor()
|
||||||
|
instance.use(codeblockPlugin)
|
||||||
|
|
||||||
|
instance.executeInsertCodeblock(content: string)
|
||||||
|
```
|
||||||
|
|
||||||
|
## Word
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
import Editor from '@hufe921/canvas-editor'
|
||||||
|
import docxPlugin from '@hufe921/canvas-editor-plugin-docx'
|
||||||
|
|
||||||
|
const instance = new Editor()
|
||||||
|
instance.use(docxPlugin)
|
||||||
|
|
||||||
|
command.executeImportDocx({
|
||||||
|
arrayBuffer: buffer
|
||||||
|
})
|
||||||
|
|
||||||
|
instance.executeExportDocx({
|
||||||
|
fileName: string
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
## Excel
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
import Editor from '@hufe921/canvas-editor'
|
||||||
|
import excelPlugin from '@hufe921/canvas-editor-plugin-excel'
|
||||||
|
|
||||||
|
const instance = new Editor()
|
||||||
|
instance.use(excelPlugin)
|
||||||
|
|
||||||
|
command.executeImportExcel({
|
||||||
|
arrayBuffer: buffer
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
## 悬浮工具
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
import Editor from '@hufe921/canvas-editor'
|
||||||
|
import floatingToolbarPlugin from '@hufe921/canvas-editor-plugin-floating-toolbar'
|
||||||
|
|
||||||
|
const instance = new Editor()
|
||||||
|
instance.use(floatingToolbarPlugin)
|
||||||
|
```
|
||||||
|
|
||||||
|
## 流程图
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
import Editor from '@hufe921/canvas-editor'
|
||||||
|
import diagramPlugin from '@hufe921/canvas-editor-plugin-diagram'
|
||||||
|
|
||||||
|
const instance = new Editor()
|
||||||
|
instance.use(diagramPlugin)
|
||||||
|
|
||||||
|
command.executeLoadDiagram({
|
||||||
|
lang?: Lang
|
||||||
|
data?: string
|
||||||
|
onDestroy?: (message?: any) => void
|
||||||
|
})
|
||||||
|
```
|
||||||
@@ -157,6 +157,7 @@ interface IElement {
|
|||||||
title?: {
|
title?: {
|
||||||
conceptId?: string;
|
conceptId?: string;
|
||||||
deletable?: boolean;
|
deletable?: boolean;
|
||||||
|
disabled?: boolean;
|
||||||
};
|
};
|
||||||
// 列表
|
// 列表
|
||||||
listType?: ListType;
|
listType?: ListType;
|
||||||
|
|||||||
+1
-1
@@ -2,7 +2,7 @@
|
|||||||
"name": "@hufe921/canvas-editor",
|
"name": "@hufe921/canvas-editor",
|
||||||
"author": "Hufe",
|
"author": "Hufe",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"version": "0.9.86",
|
"version": "0.9.91",
|
||||||
"description": "rich text editor by canvas/svg",
|
"description": "rich text editor by canvas/svg",
|
||||||
"publishConfig": {
|
"publishConfig": {
|
||||||
"registry": "https://registry.npmjs.org/",
|
"registry": "https://registry.npmjs.org/",
|
||||||
|
|||||||
@@ -55,6 +55,10 @@ export class Signature {
|
|||||||
this.ctx.lineCap = 'round'
|
this.ctx.lineCap = 'round'
|
||||||
this._bindEvent()
|
this._bindEvent()
|
||||||
this._clearUndoFn()
|
this._clearUndoFn()
|
||||||
|
// this is necessary so that the screen does not move when moving - it is removed when closing the modal
|
||||||
|
document.documentElement.classList.add('overflow-hidden')
|
||||||
|
document.body.classList.add('overflow-hidden')
|
||||||
|
this.container.classList.add('overflow-hidden')
|
||||||
}
|
}
|
||||||
|
|
||||||
private _render() {
|
private _render() {
|
||||||
@@ -166,6 +170,9 @@ export class Signature {
|
|||||||
this.canvas.onmousedown = this._startDraw.bind(this)
|
this.canvas.onmousedown = this._startDraw.bind(this)
|
||||||
this.canvas.onmousemove = this._draw.bind(this)
|
this.canvas.onmousemove = this._draw.bind(this)
|
||||||
this.container.onmouseup = this._stopDraw.bind(this)
|
this.container.onmouseup = this._stopDraw.bind(this)
|
||||||
|
this.container.ontouchmove = this.registerTouchmove.bind(this)
|
||||||
|
this.container.ontouchstart = this.registerTouchstart.bind(this)
|
||||||
|
this.container.ontouchend = this.registerTouchend.bind(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
private _undo() {
|
private _undo() {
|
||||||
@@ -302,8 +309,32 @@ export class Signature {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private registerTouchmove(evt: TouchEvent) {
|
||||||
|
this.registerTouchEvent(evt, 'mousemove')
|
||||||
|
}
|
||||||
|
|
||||||
|
private registerTouchstart(evt: TouchEvent) {
|
||||||
|
this.registerTouchEvent(evt, 'mousedown')
|
||||||
|
}
|
||||||
|
|
||||||
|
private registerTouchend() {
|
||||||
|
const me = new MouseEvent('mouseup', {})
|
||||||
|
this.canvas.dispatchEvent(me)
|
||||||
|
}
|
||||||
|
|
||||||
|
private registerTouchEvent(evt: TouchEvent, eventName: string) {
|
||||||
|
const touch = evt.touches[0]
|
||||||
|
const me = new MouseEvent(eventName, {
|
||||||
|
clientX: touch.clientX,
|
||||||
|
clientY: touch.clientY
|
||||||
|
})
|
||||||
|
this.canvas.dispatchEvent(me)
|
||||||
|
}
|
||||||
|
|
||||||
private _dispose() {
|
private _dispose() {
|
||||||
this.mask.remove()
|
this.mask.remove()
|
||||||
this.container.remove()
|
this.container.remove()
|
||||||
|
document.documentElement.classList.remove('overflow-hidden')
|
||||||
|
document.body.classList.remove('overflow-hidden')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -126,3 +126,7 @@
|
|||||||
background: #5b9cf3;
|
background: #5b9cf3;
|
||||||
border-color: #5b9cf3;
|
border-color: #5b9cf3;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.overflow-hidden {
|
||||||
|
overflow: hidden !important;
|
||||||
|
}
|
||||||
@@ -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)
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import {
|
|||||||
titleSizeMapping
|
titleSizeMapping
|
||||||
} from '../../dataset/constant/Title'
|
} from '../../dataset/constant/Title'
|
||||||
import { defaultWatermarkOption } from '../../dataset/constant/Watermark'
|
import { defaultWatermarkOption } from '../../dataset/constant/Watermark'
|
||||||
import { ImageDisplay } from '../../dataset/enum/Common'
|
import { ImageDisplay, LocationPosition } from '../../dataset/enum/Common'
|
||||||
import { ControlComponent } from '../../dataset/enum/Control'
|
import { ControlComponent } from '../../dataset/enum/Control'
|
||||||
import {
|
import {
|
||||||
EditorContext,
|
EditorContext,
|
||||||
@@ -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'
|
||||||
@@ -31,6 +32,7 @@ import { DeepRequired } from '../../interface/Common'
|
|||||||
import {
|
import {
|
||||||
IGetControlValueOption,
|
IGetControlValueOption,
|
||||||
IGetControlValueResult,
|
IGetControlValueResult,
|
||||||
|
ILocationControlOption,
|
||||||
ISetControlExtensionOption,
|
ISetControlExtensionOption,
|
||||||
ISetControlHighlightOption,
|
ISetControlHighlightOption,
|
||||||
ISetControlProperties,
|
ISetControlProperties,
|
||||||
@@ -51,6 +53,8 @@ import {
|
|||||||
IEditorOption,
|
IEditorOption,
|
||||||
IEditorResult,
|
IEditorResult,
|
||||||
IEditorText,
|
IEditorText,
|
||||||
|
IFocusOption,
|
||||||
|
ISetValueOption,
|
||||||
IUpdateOption
|
IUpdateOption
|
||||||
} from '../../interface/Editor'
|
} from '../../interface/Editor'
|
||||||
import {
|
import {
|
||||||
@@ -299,15 +303,13 @@ export class CommandAdapt {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public applyPainterStyle() {
|
public applyPainterStyle() {
|
||||||
const isDisabled =
|
const isDisabled = this.draw.isReadonly() || this.draw.isDisabled()
|
||||||
this.draw.isReadonly() || this.control.getIsDisabledControl()
|
|
||||||
if (isDisabled) return
|
if (isDisabled) return
|
||||||
this.canvasEvent.applyPainterStyle()
|
this.canvasEvent.applyPainterStyle()
|
||||||
}
|
}
|
||||||
|
|
||||||
public format() {
|
public format() {
|
||||||
const isDisabled =
|
const isDisabled = this.draw.isReadonly() || this.draw.isDisabled()
|
||||||
this.draw.isReadonly() || this.control.getIsDisabledControl()
|
|
||||||
if (isDisabled) return
|
if (isDisabled) return
|
||||||
const selection = this.range.getSelectionElementList()
|
const selection = this.range.getSelectionElementList()
|
||||||
// 选区设置或设置换行处样式
|
// 选区设置或设置换行处样式
|
||||||
@@ -335,8 +337,7 @@ export class CommandAdapt {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public font(payload: string) {
|
public font(payload: string) {
|
||||||
const isDisabled =
|
const isDisabled = this.draw.isReadonly() || this.draw.isDisabled()
|
||||||
this.draw.isReadonly() || this.control.getIsDisabledControl()
|
|
||||||
if (isDisabled) return
|
if (isDisabled) return
|
||||||
const selection = this.range.getSelectionElementList()
|
const selection = this.range.getSelectionElementList()
|
||||||
if (selection?.length) {
|
if (selection?.length) {
|
||||||
@@ -358,8 +359,7 @@ export class CommandAdapt {
|
|||||||
public size(payload: number) {
|
public size(payload: number) {
|
||||||
const { minSize, maxSize, defaultSize } = this.options
|
const { minSize, maxSize, defaultSize } = this.options
|
||||||
if (payload < minSize || payload > maxSize) return
|
if (payload < minSize || payload > maxSize) return
|
||||||
const isDisabled =
|
const isDisabled = this.draw.isReadonly() || this.draw.isDisabled()
|
||||||
this.draw.isReadonly() || this.control.getIsDisabledControl()
|
|
||||||
if (isDisabled) return
|
if (isDisabled) return
|
||||||
// 选区设置或设置换行处样式
|
// 选区设置或设置换行处样式
|
||||||
let renderOption: IDrawOption = {}
|
let renderOption: IDrawOption = {}
|
||||||
@@ -395,8 +395,7 @@ export class CommandAdapt {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public sizeAdd() {
|
public sizeAdd() {
|
||||||
const isDisabled =
|
const isDisabled = this.draw.isReadonly() || this.draw.isDisabled()
|
||||||
this.draw.isReadonly() || this.control.getIsDisabledControl()
|
|
||||||
if (isDisabled) return
|
if (isDisabled) return
|
||||||
const selection = this.range.getTextLikeSelectionElementList()
|
const selection = this.range.getTextLikeSelectionElementList()
|
||||||
// 选区设置或设置换行处样式
|
// 选区设置或设置换行处样式
|
||||||
@@ -435,8 +434,7 @@ export class CommandAdapt {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public sizeMinus() {
|
public sizeMinus() {
|
||||||
const isDisabled =
|
const isDisabled = this.draw.isReadonly() || this.draw.isDisabled()
|
||||||
this.draw.isReadonly() || this.control.getIsDisabledControl()
|
|
||||||
if (isDisabled) return
|
if (isDisabled) return
|
||||||
const selection = this.range.getTextLikeSelectionElementList()
|
const selection = this.range.getTextLikeSelectionElementList()
|
||||||
// 选区设置或设置换行处样式
|
// 选区设置或设置换行处样式
|
||||||
@@ -475,8 +473,7 @@ export class CommandAdapt {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public bold() {
|
public bold() {
|
||||||
const isDisabled =
|
const isDisabled = this.draw.isReadonly() || this.draw.isDisabled()
|
||||||
this.draw.isReadonly() || this.control.getIsDisabledControl()
|
|
||||||
if (isDisabled) return
|
if (isDisabled) return
|
||||||
const selection = this.range.getSelectionElementList()
|
const selection = this.range.getSelectionElementList()
|
||||||
if (selection?.length) {
|
if (selection?.length) {
|
||||||
@@ -497,8 +494,7 @@ export class CommandAdapt {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public italic() {
|
public italic() {
|
||||||
const isDisabled =
|
const isDisabled = this.draw.isReadonly() || this.draw.isDisabled()
|
||||||
this.draw.isReadonly() || this.control.getIsDisabledControl()
|
|
||||||
if (isDisabled) return
|
if (isDisabled) return
|
||||||
const selection = this.range.getSelectionElementList()
|
const selection = this.range.getSelectionElementList()
|
||||||
if (selection?.length) {
|
if (selection?.length) {
|
||||||
@@ -519,8 +515,7 @@ export class CommandAdapt {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public underline(textDecoration?: ITextDecoration) {
|
public underline(textDecoration?: ITextDecoration) {
|
||||||
const isDisabled =
|
const isDisabled = this.draw.isReadonly() || this.draw.isDisabled()
|
||||||
this.draw.isReadonly() || this.control.getIsDisabledControl()
|
|
||||||
if (isDisabled) return
|
if (isDisabled) return
|
||||||
const selection = this.range.getSelectionElementList()
|
const selection = this.range.getSelectionElementList()
|
||||||
if (selection?.length) {
|
if (selection?.length) {
|
||||||
@@ -558,8 +553,7 @@ export class CommandAdapt {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public strikeout() {
|
public strikeout() {
|
||||||
const isDisabled =
|
const isDisabled = this.draw.isReadonly() || this.draw.isDisabled()
|
||||||
this.draw.isReadonly() || this.control.getIsDisabledControl()
|
|
||||||
if (isDisabled) return
|
if (isDisabled) return
|
||||||
const selection = this.range.getSelectionElementList()
|
const selection = this.range.getSelectionElementList()
|
||||||
if (selection?.length) {
|
if (selection?.length) {
|
||||||
@@ -583,8 +577,7 @@ export class CommandAdapt {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public superscript() {
|
public superscript() {
|
||||||
const isDisabled =
|
const isDisabled = this.draw.isReadonly() || this.draw.isDisabled()
|
||||||
this.draw.isReadonly() || this.control.getIsDisabledControl()
|
|
||||||
if (isDisabled) return
|
if (isDisabled) return
|
||||||
const selection = this.range.getSelectionElementList()
|
const selection = this.range.getSelectionElementList()
|
||||||
if (!selection) return
|
if (!selection) return
|
||||||
@@ -613,8 +606,7 @@ export class CommandAdapt {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public subscript() {
|
public subscript() {
|
||||||
const isDisabled =
|
const isDisabled = this.draw.isReadonly() || this.draw.isDisabled()
|
||||||
this.draw.isReadonly() || this.control.getIsDisabledControl()
|
|
||||||
if (isDisabled) return
|
if (isDisabled) return
|
||||||
const selection = this.range.getSelectionElementList()
|
const selection = this.range.getSelectionElementList()
|
||||||
if (!selection) return
|
if (!selection) return
|
||||||
@@ -643,8 +635,7 @@ export class CommandAdapt {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public color(payload: string | null) {
|
public color(payload: string | null) {
|
||||||
const isDisabled =
|
const isDisabled = this.draw.isReadonly() || this.draw.isDisabled()
|
||||||
this.draw.isReadonly() || this.control.getIsDisabledControl()
|
|
||||||
if (isDisabled) return
|
if (isDisabled) return
|
||||||
const selection = this.range.getSelectionElementList()
|
const selection = this.range.getSelectionElementList()
|
||||||
if (selection?.length) {
|
if (selection?.length) {
|
||||||
@@ -675,8 +666,7 @@ export class CommandAdapt {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public highlight(payload: string | null) {
|
public highlight(payload: string | null) {
|
||||||
const isDisabled =
|
const isDisabled = this.draw.isReadonly() || this.draw.isDisabled()
|
||||||
this.draw.isReadonly() || this.control.getIsDisabledControl()
|
|
||||||
if (isDisabled) return
|
if (isDisabled) return
|
||||||
const selection = this.range.getSelectionElementList()
|
const selection = this.range.getSelectionElementList()
|
||||||
if (selection?.length) {
|
if (selection?.length) {
|
||||||
@@ -801,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
|
||||||
@@ -822,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)
|
||||||
@@ -1801,8 +1791,7 @@ export class CommandAdapt {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public image(payload: IDrawImagePayload) {
|
public image(payload: IDrawImagePayload) {
|
||||||
const isDisabled =
|
const isDisabled = this.draw.isReadonly() || this.draw.isDisabled()
|
||||||
this.draw.isReadonly() || this.control.getIsDisabledControl()
|
|
||||||
if (isDisabled) return
|
if (isDisabled) return
|
||||||
const { startIndex, endIndex } = this.range.getRange()
|
const { startIndex, endIndex } = this.range.getRange()
|
||||||
if (!~startIndex && !~endIndex) return
|
if (!~startIndex && !~endIndex) return
|
||||||
@@ -1962,12 +1951,11 @@ export class CommandAdapt {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public async print() {
|
public async print() {
|
||||||
const { scale, printPixelRatio, paperDirection } = this.options
|
const { scale, printPixelRatio, paperDirection, width, height } =
|
||||||
|
this.options
|
||||||
if (scale !== 1) {
|
if (scale !== 1) {
|
||||||
this.draw.setPageScale(1)
|
this.draw.setPageScale(1)
|
||||||
}
|
}
|
||||||
const width = this.draw.getOriginalWidth()
|
|
||||||
const height = this.draw.getOriginalHeight()
|
|
||||||
const base64List = await this.draw.getDataURL({
|
const base64List = await this.draw.getDataURL({
|
||||||
pixelRatio: printPixelRatio,
|
pixelRatio: printPixelRatio,
|
||||||
mode: EditorMode.PRINT
|
mode: EditorMode.PRINT
|
||||||
@@ -2301,8 +2289,8 @@ export class CommandAdapt {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public setValue(payload: Partial<IEditorData>) {
|
public setValue(payload: Partial<IEditorData>, options?: ISetValueOption) {
|
||||||
this.draw.setValue(payload)
|
this.draw.setValue(payload, options)
|
||||||
}
|
}
|
||||||
|
|
||||||
public removeControl() {
|
public removeControl() {
|
||||||
@@ -2449,19 +2437,19 @@ export class CommandAdapt {
|
|||||||
public getControlValue(
|
public getControlValue(
|
||||||
payload: IGetControlValueOption
|
payload: IGetControlValueOption
|
||||||
): IGetControlValueResult | null {
|
): IGetControlValueResult | null {
|
||||||
return this.draw.getControl().getValueByConceptId(payload)
|
return this.draw.getControl().getValueById(payload)
|
||||||
}
|
}
|
||||||
|
|
||||||
public setControlValue(payload: ISetControlValueOption) {
|
public setControlValue(payload: ISetControlValueOption) {
|
||||||
this.draw.getControl().setValueByConceptId(payload)
|
this.draw.getControl().setValueById(payload)
|
||||||
}
|
}
|
||||||
|
|
||||||
public setControlExtension(payload: ISetControlExtensionOption) {
|
public setControlExtension(payload: ISetControlExtensionOption) {
|
||||||
this.draw.getControl().setExtensionByConceptId(payload)
|
this.draw.getControl().setExtensionById(payload)
|
||||||
}
|
}
|
||||||
|
|
||||||
public setControlProperties(payload: ISetControlProperties) {
|
public setControlProperties(payload: ISetControlProperties) {
|
||||||
this.draw.getControl().setPropertiesByConceptId(payload)
|
this.draw.getControl().setPropertiesById(payload)
|
||||||
}
|
}
|
||||||
|
|
||||||
public setControlHighlight(payload: ISetControlHighlightOption) {
|
public setControlHighlight(payload: ISetControlHighlightOption) {
|
||||||
@@ -2483,7 +2471,8 @@ export class CommandAdapt {
|
|||||||
return this.draw.getControl().getList()
|
return this.draw.getControl().getList()
|
||||||
}
|
}
|
||||||
|
|
||||||
public locationControl(controlId: string) {
|
public locationControl(controlId: string, options?: ILocationControlOption) {
|
||||||
|
const isLocationAfter = options?.position === LocationPosition.AFTER
|
||||||
function location(
|
function location(
|
||||||
elementList: IElement[],
|
elementList: IElement[],
|
||||||
zone: EditorZone
|
zone: EditorZone
|
||||||
@@ -2517,7 +2506,16 @@ export class CommandAdapt {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (element?.controlId !== controlId) continue
|
if (element?.controlId !== controlId) continue
|
||||||
const curIndex = i - 1
|
let curIndex = i - 1
|
||||||
|
if (isLocationAfter) {
|
||||||
|
curIndex -= 1
|
||||||
|
if (
|
||||||
|
element.controlComponent !== ControlComponent.PLACEHOLDER &&
|
||||||
|
element.controlComponent !== ControlComponent.POSTFIX
|
||||||
|
) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
return {
|
return {
|
||||||
zone,
|
zone,
|
||||||
range: {
|
range: {
|
||||||
@@ -2730,4 +2728,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
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -159,7 +159,9 @@ export class ContextMenu {
|
|||||||
const originalElementList = this.draw.getOriginalElementList()
|
const originalElementList = this.draw.getOriginalElementList()
|
||||||
const originTableElement = originalElementList[index!] || null
|
const originTableElement = originalElementList[index!] || null
|
||||||
if (originTableElement) {
|
if (originTableElement) {
|
||||||
tableElement = zipElementList([originTableElement])[0]
|
tableElement = zipElementList([originTableElement], {
|
||||||
|
extraPickAttrs: ['id']
|
||||||
|
})[0]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// 是否存在跨行/列
|
// 是否存在跨行/列
|
||||||
|
|||||||
@@ -15,7 +15,8 @@ import {
|
|||||||
import {
|
import {
|
||||||
IEditorData,
|
IEditorData,
|
||||||
IEditorOption,
|
IEditorOption,
|
||||||
IEditorResult
|
IEditorResult,
|
||||||
|
ISetValueOption
|
||||||
} from '../../interface/Editor'
|
} from '../../interface/Editor'
|
||||||
import {
|
import {
|
||||||
IElement,
|
IElement,
|
||||||
@@ -100,6 +101,8 @@ import { ImageDisplay } from '../../dataset/enum/Common'
|
|||||||
import { PUNCTUATION_REG } from '../../dataset/constant/Regular'
|
import { PUNCTUATION_REG } from '../../dataset/constant/Regular'
|
||||||
import { LineBreakParticle } from './particle/LineBreakParticle'
|
import { LineBreakParticle } from './particle/LineBreakParticle'
|
||||||
import { MouseObserver } from '../observer/MouseObserver'
|
import { MouseObserver } from '../observer/MouseObserver'
|
||||||
|
import { LineNumber } from './frame/LineNumber'
|
||||||
|
import { PageBorder } from './frame/PageBorder'
|
||||||
|
|
||||||
export class Draw {
|
export class Draw {
|
||||||
private container: HTMLDivElement
|
private container: HTMLDivElement
|
||||||
@@ -137,6 +140,7 @@ export class Draw {
|
|||||||
private tableParticle: TableParticle
|
private tableParticle: TableParticle
|
||||||
private tableTool: TableTool
|
private tableTool: TableTool
|
||||||
private pageNumber: PageNumber
|
private pageNumber: PageNumber
|
||||||
|
private lineNumber: LineNumber
|
||||||
private waterMark: Watermark
|
private waterMark: Watermark
|
||||||
private placeholder: Placeholder
|
private placeholder: Placeholder
|
||||||
private header: Header
|
private header: Header
|
||||||
@@ -153,6 +157,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
|
||||||
@@ -212,6 +217,7 @@ export class Draw {
|
|||||||
this.tableParticle = new TableParticle(this)
|
this.tableParticle = new TableParticle(this)
|
||||||
this.tableTool = new TableTool(this)
|
this.tableTool = new TableTool(this)
|
||||||
this.pageNumber = new PageNumber(this)
|
this.pageNumber = new PageNumber(this)
|
||||||
|
this.lineNumber = new LineNumber(this)
|
||||||
this.waterMark = new Watermark(this)
|
this.waterMark = new Watermark(this)
|
||||||
this.placeholder = new Placeholder(this)
|
this.placeholder = new Placeholder(this)
|
||||||
this.header = new Header(this, data.header)
|
this.header = new Header(this, data.header)
|
||||||
@@ -228,6 +234,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)
|
||||||
@@ -298,6 +305,7 @@ export class Draw {
|
|||||||
this.clearSideEffect()
|
this.clearSideEffect()
|
||||||
this.range.clearRange()
|
this.range.clearRange()
|
||||||
this.mode = payload
|
this.mode = payload
|
||||||
|
this.options.mode = payload
|
||||||
this.render({
|
this.render({
|
||||||
isSetCursor: false,
|
isSetCursor: false,
|
||||||
isSubmitHistory: false
|
isSubmitHistory: false
|
||||||
@@ -316,6 +324,23 @@ export class Draw {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public isDisabled() {
|
||||||
|
const { startIndex, endIndex } = this.range.getRange()
|
||||||
|
const elementList = this.getElementList()
|
||||||
|
if (startIndex === endIndex) {
|
||||||
|
const startElement = elementList[startIndex]
|
||||||
|
const nextElement = elementList[startIndex + 1]
|
||||||
|
return !!(
|
||||||
|
(startElement?.title?.disabled && nextElement?.title?.disabled) ||
|
||||||
|
(startElement?.control?.disabled && nextElement?.control?.disabled)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
const selectionElementList = elementList.slice(startIndex + 1, endIndex + 1)
|
||||||
|
return selectionElementList.some(
|
||||||
|
element => element.title?.disabled || element.control?.disabled
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
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
|
||||||
@@ -368,6 +393,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)
|
||||||
}
|
}
|
||||||
@@ -531,6 +568,10 @@ export class Draw {
|
|||||||
return this.lineBreakParticle
|
return this.lineBreakParticle
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public getTextParticle(): TextParticle {
|
||||||
|
return this.textParticle
|
||||||
|
}
|
||||||
|
|
||||||
public getHeaderElementList(): IElement[] {
|
public getHeaderElementList(): IElement[] {
|
||||||
return this.header.getElementList()
|
return this.header.getElementList()
|
||||||
}
|
}
|
||||||
@@ -1034,14 +1075,16 @@ export class Draw {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public setValue(payload: Partial<IEditorData>) {
|
public setValue(payload: Partial<IEditorData>, options?: ISetValueOption) {
|
||||||
const { header, main, footer } = deepClone(payload)
|
const { header, main, footer } = deepClone(payload)
|
||||||
if (!header && !main && !footer) return
|
if (!header && !main && !footer) return
|
||||||
|
const { isSetCursor = false } = options || {}
|
||||||
const pageComponentData = [header, main, footer]
|
const pageComponentData = [header, main, footer]
|
||||||
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({
|
||||||
@@ -1051,8 +1094,17 @@ export class Draw {
|
|||||||
})
|
})
|
||||||
// 渲染&计算&清空历史记录
|
// 渲染&计算&清空历史记录
|
||||||
this.historyManager.recovery()
|
this.historyManager.recovery()
|
||||||
|
const curIndex = isSetCursor
|
||||||
|
? main?.length
|
||||||
|
? main.length - 1
|
||||||
|
: 0
|
||||||
|
: undefined
|
||||||
|
if (curIndex !== undefined) {
|
||||||
|
this.range.setRange(curIndex, curIndex)
|
||||||
|
}
|
||||||
this.render({
|
this.render({
|
||||||
isSetCursor: false,
|
curIndex,
|
||||||
|
isSetCursor,
|
||||||
isFirstRender: true
|
isFirstRender: true
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -1140,7 +1192,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
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1166,6 +1218,7 @@ export class Draw {
|
|||||||
ascent: 0,
|
ascent: 0,
|
||||||
elementList: [],
|
elementList: [],
|
||||||
startIndex: 0,
|
startIndex: 0,
|
||||||
|
rowIndex: 0,
|
||||||
rowFlex: elementList?.[0]?.rowFlex || elementList?.[1]?.rowFlex
|
rowFlex: elementList?.[0]?.rowFlex || elementList?.[1]?.rowFlex
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -1178,7 +1231,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,
|
||||||
@@ -1682,16 +1735,18 @@ export class Draw {
|
|||||||
i
|
i
|
||||||
)
|
)
|
||||||
// 单词宽度大于行可用宽度,无需折行
|
// 单词宽度大于行可用宽度,无需折行
|
||||||
if (width <= availableWidth) {
|
const wordWidth = width * scale
|
||||||
curRowWidth += width
|
if (wordWidth <= availableWidth) {
|
||||||
|
curRowWidth += wordWidth
|
||||||
nextElement = endElement
|
nextElement = endElement
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// 标点符号
|
// 标点符号
|
||||||
curRowWidth += this.textParticle.measurePunctuationWidth(
|
const punctuationWidth = this.textParticle.measurePunctuationWidth(
|
||||||
ctx,
|
ctx,
|
||||||
nextElement
|
nextElement
|
||||||
)
|
)
|
||||||
|
curRowWidth += punctuationWidth * scale
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// 列表信息
|
// 列表信息
|
||||||
@@ -1724,6 +1779,7 @@ export class Draw {
|
|||||||
startIndex: i,
|
startIndex: i,
|
||||||
elementList: [rowElement],
|
elementList: [rowElement],
|
||||||
ascent,
|
ascent,
|
||||||
|
rowIndex: curRow.rowIndex + 1,
|
||||||
rowFlex: elementList[i]?.rowFlex || elementList[i + 1]?.rowFlex,
|
rowFlex: elementList[i]?.rowFlex || elementList[i + 1]?.rowFlex,
|
||||||
isPageBreak: element.type === ElementType.PAGE_BREAK
|
isPageBreak: element.type === ElementType.PAGE_BREAK
|
||||||
}
|
}
|
||||||
@@ -1981,13 +2037,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 (
|
||||||
@@ -2228,6 +2296,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++) {
|
||||||
@@ -2244,8 +2313,8 @@ export class Draw {
|
|||||||
this.imageParticle.render(
|
this.imageParticle.render(
|
||||||
ctx,
|
ctx,
|
||||||
element,
|
element,
|
||||||
imgFloatPosition.x,
|
imgFloatPosition.x * scale,
|
||||||
imgFloatPosition.y
|
imgFloatPosition.y * scale
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2265,7 +2334,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 } = this.options
|
const {
|
||||||
|
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]
|
||||||
// 判断当前激活区域-非正文区域时元素透明度降低
|
// 判断当前激活区域-非正文区域时元素透明度降低
|
||||||
@@ -2326,6 +2403,14 @@ export class Draw {
|
|||||||
if (this.elementList.length <= 1 && !this.elementList[0]?.listId) {
|
if (this.elementList.length <= 1 && !this.elementList[0]?.listId) {
|
||||||
this.placeholder.render(ctx)
|
this.placeholder.render(ctx)
|
||||||
}
|
}
|
||||||
|
// 渲染行数
|
||||||
|
if (!lineNumber.disabled) {
|
||||||
|
this.lineNumber.render(ctx, pageNo)
|
||||||
|
}
|
||||||
|
// 绘制页面边框
|
||||||
|
if (!pageBorder.disabled) {
|
||||||
|
this.pageBorder.render(ctx)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private _disconnectLazyRender() {
|
private _disconnectLazyRender() {
|
||||||
|
|||||||
@@ -207,8 +207,17 @@ export class Control {
|
|||||||
return prefixCount === postfixCount
|
return prefixCount === postfixCount
|
||||||
}
|
}
|
||||||
|
|
||||||
public getIsDisabledControl(): boolean {
|
public getIsDisabledControl(context: IControlContext = {}): boolean {
|
||||||
return !!this.activeControl?.getElement().control?.disabled
|
if (!this.activeControl) return false
|
||||||
|
const { startIndex, endIndex } = context.range || this.range.getRange()
|
||||||
|
if (startIndex === endIndex && ~startIndex && ~endIndex) {
|
||||||
|
const elementList = context.elementList || this.getElementList()
|
||||||
|
const startElement = elementList[startIndex]
|
||||||
|
if (startElement.controlComponent === ControlComponent.POSTFIX) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return !!this.activeControl.getElement()?.control?.disabled
|
||||||
}
|
}
|
||||||
|
|
||||||
public getContainer(): HTMLDivElement {
|
public getContainer(): HTMLDivElement {
|
||||||
@@ -560,11 +569,10 @@ export class Control {
|
|||||||
return this.activeControl.cut()
|
return this.activeControl.cut()
|
||||||
}
|
}
|
||||||
|
|
||||||
public getValueByConceptId(
|
public getValueById(payload: IGetControlValueOption): IGetControlValueResult {
|
||||||
payload: IGetControlValueOption
|
const { id, conceptId } = payload
|
||||||
): IGetControlValueResult {
|
|
||||||
const { conceptId } = payload
|
|
||||||
const result: IGetControlValueResult = []
|
const result: IGetControlValueResult = []
|
||||||
|
if (!id && !conceptId) return result
|
||||||
const getValue = (elementList: IElement[], zone: EditorZone) => {
|
const getValue = (elementList: IElement[], zone: EditorZone) => {
|
||||||
let i = 0
|
let i = 0
|
||||||
while (i < elementList.length) {
|
while (i < elementList.length) {
|
||||||
@@ -581,8 +589,14 @@ export class Control {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (element?.control?.conceptId !== conceptId) continue
|
if (
|
||||||
const { type, code, valueSets } = element.control!
|
!element.control ||
|
||||||
|
(id && element.controlId !== id) ||
|
||||||
|
(conceptId && element.control.conceptId !== conceptId)
|
||||||
|
) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
const { type, code, valueSets } = element.control
|
||||||
let j = i
|
let j = i
|
||||||
let textControlValue = ''
|
let textControlValue = ''
|
||||||
while (j < elementList.length) {
|
while (j < elementList.length) {
|
||||||
@@ -646,9 +660,10 @@ export class Control {
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
public setValueByConceptId(payload: ISetControlValueOption) {
|
public setValueById(payload: ISetControlValueOption) {
|
||||||
let isExistSet = false
|
let isExistSet = false
|
||||||
const { conceptId, value } = payload
|
const { id, conceptId, value } = payload
|
||||||
|
if (!id && !conceptId) return
|
||||||
// 设置值
|
// 设置值
|
||||||
const setValue = (elementList: IElement[]) => {
|
const setValue = (elementList: IElement[]) => {
|
||||||
let i = 0
|
let i = 0
|
||||||
@@ -666,7 +681,13 @@ export class Control {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (element?.control?.conceptId !== conceptId) continue
|
if (
|
||||||
|
!element.control ||
|
||||||
|
(id && element.controlId !== id) ||
|
||||||
|
(conceptId && element.control.conceptId !== conceptId)
|
||||||
|
) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
isExistSet = true
|
isExistSet = true
|
||||||
const { type } = element.control!
|
const { type } = element.control!
|
||||||
// 当前控件结束索引
|
// 当前控件结束索引
|
||||||
@@ -712,7 +733,7 @@ export class Control {
|
|||||||
} else if (type === ControlType.CHECKBOX) {
|
} else if (type === ControlType.CHECKBOX) {
|
||||||
const checkbox = new CheckboxControl(element, this)
|
const checkbox = new CheckboxControl(element, this)
|
||||||
this.activeControl = checkbox
|
this.activeControl = checkbox
|
||||||
const codes = value?.split(',') || []
|
const codes = value ? value.split(',') : []
|
||||||
checkbox.setSelect(codes, controlContext, controlRule)
|
checkbox.setSelect(codes, controlContext, controlRule)
|
||||||
} else if (type === ControlType.RADIO) {
|
} else if (type === ControlType.RADIO) {
|
||||||
const radio = new RadioControl(element, this)
|
const radio = new RadioControl(element, this)
|
||||||
@@ -758,8 +779,9 @@ export class Control {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public setExtensionByConceptId(payload: ISetControlExtensionOption) {
|
public setExtensionById(payload: ISetControlExtensionOption) {
|
||||||
const { conceptId, extension } = payload
|
const { id, conceptId, extension } = payload
|
||||||
|
if (!id && !conceptId) return
|
||||||
const setExtension = (elementList: IElement[]) => {
|
const setExtension = (elementList: IElement[]) => {
|
||||||
let i = 0
|
let i = 0
|
||||||
while (i < elementList.length) {
|
while (i < elementList.length) {
|
||||||
@@ -776,7 +798,13 @@ export class Control {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (element?.control?.conceptId !== conceptId) continue
|
if (
|
||||||
|
!element.control ||
|
||||||
|
(id && element.controlId !== id) ||
|
||||||
|
(conceptId && element.control.conceptId !== conceptId)
|
||||||
|
) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
element.control.extension = extension
|
element.control.extension = extension
|
||||||
// 修改后控件结束索引
|
// 修改后控件结束索引
|
||||||
let newEndIndex = i
|
let newEndIndex = i
|
||||||
@@ -798,8 +826,9 @@ export class Control {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public setPropertiesByConceptId(payload: ISetControlProperties) {
|
public setPropertiesById(payload: ISetControlProperties) {
|
||||||
const { conceptId, properties } = payload
|
const { id, conceptId, properties } = payload
|
||||||
|
if (!id && !conceptId) return
|
||||||
let isExistUpdate = false
|
let isExistUpdate = false
|
||||||
function setProperties(elementList: IElement[]) {
|
function setProperties(elementList: IElement[]) {
|
||||||
let i = 0
|
let i = 0
|
||||||
@@ -816,7 +845,13 @@ export class Control {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (element?.control?.conceptId !== conceptId) continue
|
if (
|
||||||
|
!element.control ||
|
||||||
|
(id && element.controlId !== id) ||
|
||||||
|
(conceptId && element.control.conceptId !== conceptId)
|
||||||
|
) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
isExistUpdate = true
|
isExistUpdate = true
|
||||||
element.control = {
|
element.control = {
|
||||||
...element.control,
|
...element.control,
|
||||||
@@ -857,7 +892,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)
|
||||||
|
|||||||
@@ -77,7 +77,10 @@ export class CheckboxControl implements IControlInstance {
|
|||||||
options: IControlRuleOption = {}
|
options: IControlRuleOption = {}
|
||||||
) {
|
) {
|
||||||
// 校验是否可以设置
|
// 校验是否可以设置
|
||||||
if (!options.isIgnoreDisabledRule && this.control.getIsDisabledControl()) {
|
if (
|
||||||
|
!options.isIgnoreDisabledRule &&
|
||||||
|
this.control.getIsDisabledControl(context)
|
||||||
|
) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
const { control } = this.element
|
const { control } = this.element
|
||||||
|
|||||||
@@ -99,7 +99,10 @@ export class DateControl implements IControlInstance {
|
|||||||
options: IControlRuleOption = {}
|
options: IControlRuleOption = {}
|
||||||
): number {
|
): number {
|
||||||
// 校验是否可以设置
|
// 校验是否可以设置
|
||||||
if (!options.isIgnoreDisabledRule && this.control.getIsDisabledControl()) {
|
if (
|
||||||
|
!options.isIgnoreDisabledRule &&
|
||||||
|
this.control.getIsDisabledControl(context)
|
||||||
|
) {
|
||||||
return -1
|
return -1
|
||||||
}
|
}
|
||||||
const elementList = context.elementList || this.control.getElementList()
|
const elementList = context.elementList || this.control.getElementList()
|
||||||
@@ -147,7 +150,7 @@ export class DateControl implements IControlInstance {
|
|||||||
): number {
|
): number {
|
||||||
const { isIgnoreDisabledRule = false, isAddPlaceholder = true } = options
|
const { isIgnoreDisabledRule = false, isAddPlaceholder = true } = options
|
||||||
// 校验是否可以设置
|
// 校验是否可以设置
|
||||||
if (!isIgnoreDisabledRule && this.control.getIsDisabledControl()) {
|
if (!isIgnoreDisabledRule && this.control.getIsDisabledControl(context)) {
|
||||||
return -1
|
return -1
|
||||||
}
|
}
|
||||||
const range = this.getValueRange(context)
|
const range = this.getValueRange(context)
|
||||||
@@ -171,7 +174,10 @@ export class DateControl implements IControlInstance {
|
|||||||
options: IControlRuleOption = {}
|
options: IControlRuleOption = {}
|
||||||
) {
|
) {
|
||||||
// 校验是否可以设置
|
// 校验是否可以设置
|
||||||
if (!options.isIgnoreDisabledRule && this.control.getIsDisabledControl()) {
|
if (
|
||||||
|
!options.isIgnoreDisabledRule &&
|
||||||
|
this.control.getIsDisabledControl(context)
|
||||||
|
) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
const elementList = context.elementList || this.control.getElementList()
|
const elementList = context.elementList || this.control.getElementList()
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
import { ZERO } from '../../../../dataset/constant/Common'
|
||||||
|
import { ControlComponent } from '../../../../dataset/enum/Control'
|
||||||
import { ElementType } from '../../../../dataset/enum/Element'
|
import { ElementType } from '../../../../dataset/enum/Element'
|
||||||
import { DeepRequired } from '../../../../interface/Common'
|
import { DeepRequired } from '../../../../interface/Common'
|
||||||
import {
|
import {
|
||||||
@@ -69,10 +71,13 @@ export class ControlSearch {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const controlConceptId = element?.control?.conceptId
|
const currentControl = element?.control
|
||||||
if (!controlConceptId) continue
|
if (!currentControl) continue
|
||||||
const highlightIndex = this.highlightList.findIndex(
|
const highlightIndex = this.highlightList.findIndex(
|
||||||
highlight => highlight.conceptId === controlConceptId
|
highlight =>
|
||||||
|
highlight.id === element.controlId ||
|
||||||
|
(currentControl.conceptId &&
|
||||||
|
currentControl.conceptId === highlight.conceptId)
|
||||||
)
|
)
|
||||||
if (!~highlightIndex) continue
|
if (!~highlightIndex) continue
|
||||||
// 搜索后控件结束索引
|
// 搜索后控件结束索引
|
||||||
@@ -85,7 +90,13 @@ export class ControlSearch {
|
|||||||
}
|
}
|
||||||
i = newEndIndex
|
i = newEndIndex
|
||||||
// 高亮信息
|
// 高亮信息
|
||||||
const controlElementList = elementList.slice(startIndex, newEndIndex)
|
const controlElementList = elementList
|
||||||
|
.slice(startIndex, newEndIndex)
|
||||||
|
.map(element =>
|
||||||
|
element.controlComponent === ControlComponent.VALUE
|
||||||
|
? element
|
||||||
|
: { value: ZERO }
|
||||||
|
)
|
||||||
const highlight = this.highlightList[highlightIndex]
|
const highlight = this.highlightList[highlightIndex]
|
||||||
const { ruleList } = highlight
|
const { ruleList } = highlight
|
||||||
for (let r = 0; r < ruleList.length; r++) {
|
for (let r = 0; r < ruleList.length; r++) {
|
||||||
|
|||||||
@@ -12,7 +12,10 @@ export class RadioControl extends CheckboxControl {
|
|||||||
options: IControlRuleOption = {}
|
options: IControlRuleOption = {}
|
||||||
) {
|
) {
|
||||||
// 校验是否可以设置
|
// 校验是否可以设置
|
||||||
if (!options.isIgnoreDisabledRule && this.control.getIsDisabledControl()) {
|
if (
|
||||||
|
!options.isIgnoreDisabledRule &&
|
||||||
|
this.control.getIsDisabledControl(context)
|
||||||
|
) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
const { control } = this.element
|
const { control } = this.element
|
||||||
|
|||||||
@@ -163,7 +163,7 @@ export class SelectControl implements IControlInstance {
|
|||||||
): number {
|
): number {
|
||||||
const { isIgnoreDisabledRule = false, isAddPlaceholder = true } = options
|
const { isIgnoreDisabledRule = false, isAddPlaceholder = true } = options
|
||||||
// 校验是否可以设置
|
// 校验是否可以设置
|
||||||
if (!isIgnoreDisabledRule && this.control.getIsDisabledControl()) {
|
if (!isIgnoreDisabledRule && this.control.getIsDisabledControl(context)) {
|
||||||
return -1
|
return -1
|
||||||
}
|
}
|
||||||
const elementList = context.elementList || this.control.getElementList()
|
const elementList = context.elementList || this.control.getElementList()
|
||||||
@@ -215,7 +215,10 @@ export class SelectControl implements IControlInstance {
|
|||||||
options: IControlRuleOption = {}
|
options: IControlRuleOption = {}
|
||||||
) {
|
) {
|
||||||
// 校验是否可以设置
|
// 校验是否可以设置
|
||||||
if (!options.isIgnoreDisabledRule && this.control.getIsDisabledControl()) {
|
if (
|
||||||
|
!options.isIgnoreDisabledRule &&
|
||||||
|
this.control.getIsDisabledControl(context)
|
||||||
|
) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
const elementList = context.elementList || this.control.getElementList()
|
const elementList = context.elementList || this.control.getElementList()
|
||||||
|
|||||||
@@ -75,7 +75,10 @@ export class TextControl implements IControlInstance {
|
|||||||
options: IControlRuleOption = {}
|
options: IControlRuleOption = {}
|
||||||
): number {
|
): number {
|
||||||
// 校验是否可以设置
|
// 校验是否可以设置
|
||||||
if (!options.isIgnoreDisabledRule && this.control.getIsDisabledControl()) {
|
if (
|
||||||
|
!options.isIgnoreDisabledRule &&
|
||||||
|
this.control.getIsDisabledControl(context)
|
||||||
|
) {
|
||||||
return -1
|
return -1
|
||||||
}
|
}
|
||||||
const elementList = context.elementList || this.control.getElementList()
|
const elementList = context.elementList || this.control.getElementList()
|
||||||
@@ -122,7 +125,10 @@ export class TextControl implements IControlInstance {
|
|||||||
options: IControlRuleOption = {}
|
options: IControlRuleOption = {}
|
||||||
): number {
|
): number {
|
||||||
// 校验是否可以设置
|
// 校验是否可以设置
|
||||||
if (!options.isIgnoreDisabledRule && this.control.getIsDisabledControl()) {
|
if (
|
||||||
|
!options.isIgnoreDisabledRule &&
|
||||||
|
this.control.getIsDisabledControl(context)
|
||||||
|
) {
|
||||||
return -1
|
return -1
|
||||||
}
|
}
|
||||||
const elementList = context.elementList || this.control.getElementList()
|
const elementList = context.elementList || this.control.getElementList()
|
||||||
|
|||||||
@@ -99,14 +99,19 @@ export class Background {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public render(ctx: CanvasRenderingContext2D, pageNo: number) {
|
public render(ctx: CanvasRenderingContext2D, pageNo: number) {
|
||||||
const { background } = this.options
|
const {
|
||||||
if (background.image) {
|
background: { image, color, applyPageNumbers }
|
||||||
|
} = this.options
|
||||||
|
if (
|
||||||
|
image &&
|
||||||
|
(!applyPageNumbers?.length || applyPageNumbers.includes(pageNo))
|
||||||
|
) {
|
||||||
const { width, height } = this.options
|
const { width, height } = this.options
|
||||||
this._renderBackgroundImage(ctx, width, height)
|
this._renderBackgroundImage(ctx, width, height)
|
||||||
} else {
|
} else {
|
||||||
const width = this.draw.getCanvasWidth(pageNo)
|
const width = this.draw.getCanvasWidth(pageNo)
|
||||||
const height = this.draw.getCanvasHeight(pageNo)
|
const height = this.draw.getCanvasHeight(pageNo)
|
||||||
this._renderBackgroundColor(ctx, background.color, width, height)
|
this._renderBackgroundColor(ctx, color, width, height)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,43 @@
|
|||||||
|
import { LineNumberType } from '../../../dataset/enum/LineNumber'
|
||||||
|
import { DeepRequired } from '../../../interface/Common'
|
||||||
|
import { IEditorOption } from '../../../interface/Editor'
|
||||||
|
import { Draw } from '../Draw'
|
||||||
|
|
||||||
|
export class LineNumber {
|
||||||
|
private draw: Draw
|
||||||
|
private options: DeepRequired<IEditorOption>
|
||||||
|
|
||||||
|
constructor(draw: Draw) {
|
||||||
|
this.draw = draw
|
||||||
|
this.options = draw.getOptions()
|
||||||
|
}
|
||||||
|
|
||||||
|
public render(ctx: CanvasRenderingContext2D, pageNo: number) {
|
||||||
|
const {
|
||||||
|
scale,
|
||||||
|
lineNumber: { color, size, font, right, type }
|
||||||
|
} = this.options
|
||||||
|
const textParticle = this.draw.getTextParticle()
|
||||||
|
const margins = this.draw.getMargins()
|
||||||
|
const positionList = this.draw.getPosition().getOriginalMainPositionList()
|
||||||
|
const pageRowList = this.draw.getPageRowList()
|
||||||
|
const rowList = pageRowList[pageNo]
|
||||||
|
ctx.save()
|
||||||
|
ctx.fillStyle = color
|
||||||
|
ctx.font = `${size * scale}px ${font}`
|
||||||
|
for (let i = 0; i < rowList.length; i++) {
|
||||||
|
const row = rowList[i]
|
||||||
|
const {
|
||||||
|
coordinate: { leftBottom }
|
||||||
|
} = positionList[row.startIndex]
|
||||||
|
const seq = type === LineNumberType.PAGE ? i + 1 : row.rowIndex + 1
|
||||||
|
const textMetrics = textParticle.measureText(ctx, {
|
||||||
|
value: `${seq}`
|
||||||
|
})
|
||||||
|
const x = margins[3] - (textMetrics.width + right) * scale
|
||||||
|
const y = leftBottom[1] - textMetrics.actualBoundingBoxAscent * scale
|
||||||
|
ctx.fillText(`${seq}`, x, y)
|
||||||
|
}
|
||||||
|
ctx.restore()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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)
|
||||||
|
|||||||
@@ -106,6 +106,8 @@ export class CanvasEvent {
|
|||||||
public applyPainterStyle() {
|
public applyPainterStyle() {
|
||||||
const painterStyle = this.draw.getPainterStyle()
|
const painterStyle = this.draw.getPainterStyle()
|
||||||
if (!painterStyle) return
|
if (!painterStyle) return
|
||||||
|
const isDisabled = this.draw.isReadonly() || this.draw.isDisabled()
|
||||||
|
if (isDisabled) return
|
||||||
const selection = this.range.getSelection()
|
const selection = this.range.getSelection()
|
||||||
if (!selection) return
|
if (!selection) return
|
||||||
const painterStyleKeys = Object.keys(painterStyle)
|
const painterStyleKeys = Object.keys(painterStyle)
|
||||||
|
|||||||
@@ -195,7 +195,10 @@ function threeClick(host: CanvasEvent) {
|
|||||||
}
|
}
|
||||||
if (newStartIndex < 0) return
|
if (newStartIndex < 0) return
|
||||||
let newEndIndex = index + downCount + 1
|
let newEndIndex = index + downCount + 1
|
||||||
if (elementList[newEndIndex]?.value === ZERO) {
|
if (
|
||||||
|
elementList[newEndIndex]?.value === ZERO ||
|
||||||
|
newEndIndex > elementList.length - 1
|
||||||
|
) {
|
||||||
newEndIndex -= 1
|
newEndIndex -= 1
|
||||||
}
|
}
|
||||||
rangeManager.setRange(newStartIndex, newEndIndex)
|
rangeManager.setRange(newStartIndex, newEndIndex)
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import { CanvasEvent } from '../CanvasEvent'
|
|||||||
|
|
||||||
export function input(data: string, host: CanvasEvent) {
|
export function input(data: string, host: CanvasEvent) {
|
||||||
const draw = host.getDraw()
|
const draw = host.getDraw()
|
||||||
if (draw.isReadonly()) return
|
if (draw.isReadonly() || draw.isDisabled()) return
|
||||||
const position = draw.getPosition()
|
const position = draw.getPosition()
|
||||||
const cursorPosition = position.getCursorPosition()
|
const cursorPosition = position.getCursorPosition()
|
||||||
if (!data || !cursorPosition) return
|
if (!data || !cursorPosition) return
|
||||||
@@ -34,6 +34,7 @@ export function input(data: string, host: CanvasEvent) {
|
|||||||
const newElement: IElement = {
|
const newElement: IElement = {
|
||||||
value
|
value
|
||||||
}
|
}
|
||||||
|
if (!copyElement.title?.disabled && !copyElement.control?.disabled) {
|
||||||
const nextElement = elementList[endIndex + 1]
|
const nextElement = elementList[endIndex + 1]
|
||||||
if (
|
if (
|
||||||
!copyElement.type ||
|
!copyElement.type ||
|
||||||
@@ -55,6 +56,7 @@ export function input(data: string, host: CanvasEvent) {
|
|||||||
if (isComposing) {
|
if (isComposing) {
|
||||||
newElement.underline = true
|
newElement.underline = true
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return newElement
|
return newElement
|
||||||
})
|
})
|
||||||
// 控件-移除placeholder
|
// 控件-移除placeholder
|
||||||
|
|||||||
@@ -7,9 +7,30 @@ export function backspace(evt: KeyboardEvent, host: CanvasEvent) {
|
|||||||
// 可输入性验证
|
// 可输入性验证
|
||||||
const rangeManager = draw.getRange()
|
const rangeManager = draw.getRange()
|
||||||
if (!rangeManager.getIsCanInput()) return
|
if (!rangeManager.getIsCanInput()) return
|
||||||
|
const { startIndex, endIndex, isCrossRowCol } = rangeManager.getRange()
|
||||||
const control = draw.getControl()
|
const control = draw.getControl()
|
||||||
let curIndex: number | null
|
let curIndex: number | null
|
||||||
if (control.getActiveControl() && control.getIsRangeCanCaptureEvent()) {
|
if (isCrossRowCol) {
|
||||||
|
// 表格跨行列选中时清空单元格内容
|
||||||
|
const rowCol = draw.getTableParticle().getRangeRowCol()
|
||||||
|
if (!rowCol) return
|
||||||
|
let isDeleted = false
|
||||||
|
for (let r = 0; r < rowCol.length; r++) {
|
||||||
|
const row = rowCol[r]
|
||||||
|
for (let c = 0; c < row.length; c++) {
|
||||||
|
const col = row[c]
|
||||||
|
if (col.value.length > 1) {
|
||||||
|
draw.spliceElementList(col.value, 1, col.value.length - 1)
|
||||||
|
isDeleted = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 删除成功后定位
|
||||||
|
curIndex = isDeleted ? 0 : null
|
||||||
|
} else if (
|
||||||
|
control.getActiveControl() &&
|
||||||
|
control.getIsRangeCanCaptureEvent()
|
||||||
|
) {
|
||||||
// 光标在控件内
|
// 光标在控件内
|
||||||
curIndex = control.keydown(evt)
|
curIndex = control.keydown(evt)
|
||||||
} else {
|
} else {
|
||||||
@@ -18,7 +39,6 @@ export function backspace(evt: KeyboardEvent, host: CanvasEvent) {
|
|||||||
const cursorPosition = position.getCursorPosition()
|
const cursorPosition = position.getCursorPosition()
|
||||||
if (!cursorPosition) return
|
if (!cursorPosition) return
|
||||||
const { index } = cursorPosition
|
const { index } = cursorPosition
|
||||||
const { startIndex, endIndex } = rangeManager.getRange()
|
|
||||||
const isCollapsed = rangeManager.getIsCollapsed()
|
const isCollapsed = rangeManager.getIsCollapsed()
|
||||||
const elementList = draw.getElementList()
|
const elementList = draw.getElementList()
|
||||||
// 判断是否允许删除
|
// 判断是否允许删除
|
||||||
@@ -33,17 +53,17 @@ export function backspace(evt: KeyboardEvent, host: CanvasEvent) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// 清空当前行对齐方式
|
// 替换当前行对齐方式
|
||||||
const startElement = elementList[startIndex]
|
const startElement = elementList[startIndex]
|
||||||
if (isCollapsed && startElement.rowFlex && startElement.value === ZERO) {
|
if (isCollapsed && startElement.rowFlex && startElement.value === ZERO) {
|
||||||
const rowList = draw.getRowList()
|
const rowFlexElementList = rangeManager.getRangeRowElementList()
|
||||||
const positionList = position.getPositionList()
|
if (rowFlexElementList) {
|
||||||
const rowNo = positionList[startIndex].rowNo
|
const preElement = elementList[startIndex - 1]
|
||||||
const rowFlexElementList = rowList[rowNo].elementList
|
|
||||||
rowFlexElementList.forEach(element => {
|
rowFlexElementList.forEach(element => {
|
||||||
delete element.rowFlex
|
element.rowFlex = preElement?.rowFlex
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (!isCollapsed) {
|
if (!isCollapsed) {
|
||||||
draw.spliceElementList(elementList, startIndex + 1, endIndex - startIndex)
|
draw.spliceElementList(elementList, startIndex + 1, endIndex - startIndex)
|
||||||
} else {
|
} else {
|
||||||
@@ -51,8 +71,17 @@ export function backspace(evt: KeyboardEvent, host: CanvasEvent) {
|
|||||||
}
|
}
|
||||||
curIndex = isCollapsed ? index - 1 : startIndex
|
curIndex = isCollapsed ? index - 1 : startIndex
|
||||||
}
|
}
|
||||||
if (curIndex === null) return
|
|
||||||
draw.getGlobalEvent().setCanvasEventAbility()
|
draw.getGlobalEvent().setCanvasEventAbility()
|
||||||
|
if (curIndex === null) {
|
||||||
|
rangeManager.setRange(startIndex, startIndex)
|
||||||
|
draw.render({
|
||||||
|
curIndex: startIndex,
|
||||||
|
isSubmitHistory: false
|
||||||
|
})
|
||||||
|
} else {
|
||||||
rangeManager.setRange(curIndex, curIndex)
|
rangeManager.setRange(curIndex, curIndex)
|
||||||
draw.render({ curIndex })
|
draw.render({
|
||||||
|
curIndex
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,11 +6,28 @@ export function del(evt: KeyboardEvent, host: CanvasEvent) {
|
|||||||
// 可输入性验证
|
// 可输入性验证
|
||||||
const rangeManager = draw.getRange()
|
const rangeManager = draw.getRange()
|
||||||
if (!rangeManager.getIsCanInput()) return
|
if (!rangeManager.getIsCanInput()) return
|
||||||
const { startIndex, endIndex } = rangeManager.getRange()
|
const { startIndex, endIndex, isCrossRowCol } = rangeManager.getRange()
|
||||||
const elementList = draw.getElementList()
|
const elementList = draw.getElementList()
|
||||||
const control = draw.getControl()
|
const control = draw.getControl()
|
||||||
let curIndex: number | null
|
let curIndex: number | null
|
||||||
if (control.getActiveControl() && control.getIsRangeWithinControl()) {
|
if (isCrossRowCol) {
|
||||||
|
// 表格跨行列选中时清空单元格内容
|
||||||
|
const rowCol = draw.getTableParticle().getRangeRowCol()
|
||||||
|
if (!rowCol) return
|
||||||
|
let isDeleted = false
|
||||||
|
for (let r = 0; r < rowCol.length; r++) {
|
||||||
|
const row = rowCol[r]
|
||||||
|
for (let c = 0; c < row.length; c++) {
|
||||||
|
const col = row[c]
|
||||||
|
if (col.value.length > 1) {
|
||||||
|
draw.spliceElementList(col.value, 1, col.value.length - 1)
|
||||||
|
isDeleted = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 删除成功后定位
|
||||||
|
curIndex = isDeleted ? 0 : null
|
||||||
|
} else if (control.getActiveControl() && control.getIsRangeWithinControl()) {
|
||||||
// 光标在控件内
|
// 光标在控件内
|
||||||
curIndex = control.keydown(evt)
|
curIndex = control.keydown(evt)
|
||||||
} else if (elementList[endIndex + 1]?.controlId) {
|
} else if (elementList[endIndex + 1]?.controlId) {
|
||||||
@@ -42,8 +59,17 @@ export function del(evt: KeyboardEvent, host: CanvasEvent) {
|
|||||||
curIndex = isCollapsed ? index : startIndex
|
curIndex = isCollapsed ? index : startIndex
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (curIndex === null) return
|
|
||||||
draw.getGlobalEvent().setCanvasEventAbility()
|
draw.getGlobalEvent().setCanvasEventAbility()
|
||||||
|
if (curIndex === null) {
|
||||||
|
rangeManager.setRange(startIndex, startIndex)
|
||||||
|
draw.render({
|
||||||
|
curIndex: startIndex,
|
||||||
|
isSubmitHistory: false
|
||||||
|
})
|
||||||
|
} else {
|
||||||
rangeManager.setRange(curIndex, curIndex)
|
rangeManager.setRange(curIndex, curIndex)
|
||||||
draw.render({ curIndex })
|
draw.render({
|
||||||
|
curIndex
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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()
|
||||||
@@ -48,6 +88,8 @@ export function mousedown(evt: MouseEvent, host: CanvasEvent) {
|
|||||||
draw.setPageNo(Number(pageIndex))
|
draw.setPageNo(Number(pageIndex))
|
||||||
}
|
}
|
||||||
host.isAllowSelection = true
|
host.isAllowSelection = true
|
||||||
|
// 缓存旧上下文信息
|
||||||
|
const oldPositionContext = deepClone(position.getPositionContext())
|
||||||
const positionResult = position.adjustPositionContext({
|
const positionResult = position.adjustPositionContext({
|
||||||
x: evt.offsetX,
|
x: evt.offsetX,
|
||||||
y: evt.offsetY
|
y: evt.offsetY
|
||||||
@@ -79,43 +121,46 @@ export function mousedown(evt: MouseEvent, host: CanvasEvent) {
|
|||||||
const isDirectHitCheckbox = !!(isDirectHit && isCheckbox)
|
const isDirectHitCheckbox = !!(isDirectHit && isCheckbox)
|
||||||
const isDirectHitRadio = !!(isDirectHit && isRadio)
|
const isDirectHitRadio = !!(isDirectHit && isRadio)
|
||||||
if (~index) {
|
if (~index) {
|
||||||
rangeManager.setRange(curIndex, curIndex)
|
let startIndex = curIndex
|
||||||
|
let endIndex = curIndex
|
||||||
|
// shift激活时进行选区处理
|
||||||
|
if (evt.shiftKey) {
|
||||||
|
const { startIndex: oldStartIndex } = rangeManager.getRange()
|
||||||
|
if (~oldStartIndex) {
|
||||||
|
const newPositionContext = position.getPositionContext()
|
||||||
|
if (newPositionContext.tdId === oldPositionContext.tdId) {
|
||||||
|
if (curIndex > oldStartIndex) {
|
||||||
|
startIndex = oldStartIndex
|
||||||
|
} else {
|
||||||
|
endIndex = oldStartIndex
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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?.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({
|
||||||
|
|||||||
@@ -48,7 +48,10 @@ export function mouseup(evt: MouseEvent, host: CanvasEvent) {
|
|||||||
// 判断是否允许拖放
|
// 判断是否允许拖放
|
||||||
if (host.isAllowDrop) {
|
if (host.isAllowDrop) {
|
||||||
const draw = host.getDraw()
|
const draw = host.getDraw()
|
||||||
if (draw.isReadonly()) return
|
if (draw.isReadonly() || draw.isDisabled()) {
|
||||||
|
host.mousedown(evt)
|
||||||
|
return
|
||||||
|
}
|
||||||
const position = draw.getPosition()
|
const position = draw.getPosition()
|
||||||
const positionList = position.getPositionList()
|
const positionList = position.getPositionList()
|
||||||
const positionContext = position.getPositionContext()
|
const positionContext = position.getPositionContext()
|
||||||
|
|||||||
@@ -17,8 +17,7 @@ import { IOverrideResult } from '../../override/Override'
|
|||||||
|
|
||||||
export function pasteElement(host: CanvasEvent, elementList: IElement[]) {
|
export function pasteElement(host: CanvasEvent, elementList: IElement[]) {
|
||||||
const draw = host.getDraw()
|
const draw = host.getDraw()
|
||||||
const isReadonly = draw.isReadonly()
|
if (draw.isReadonly() || draw.isDisabled()) return
|
||||||
if (isReadonly) return
|
|
||||||
const rangeManager = draw.getRange()
|
const rangeManager = draw.getRange()
|
||||||
const { startIndex } = rangeManager.getRange()
|
const { startIndex } = rangeManager.getRange()
|
||||||
const originalElementList = draw.getElementList()
|
const originalElementList = draw.getElementList()
|
||||||
@@ -59,8 +58,7 @@ export function pasteElement(host: CanvasEvent, elementList: IElement[]) {
|
|||||||
|
|
||||||
export function pasteHTML(host: CanvasEvent, htmlText: string) {
|
export function pasteHTML(host: CanvasEvent, htmlText: string) {
|
||||||
const draw = host.getDraw()
|
const draw = host.getDraw()
|
||||||
const isReadonly = draw.isReadonly()
|
if (draw.isReadonly() || draw.isDisabled()) return
|
||||||
if (isReadonly) return
|
|
||||||
const elementList = getElementListByHTML(htmlText, {
|
const elementList = getElementListByHTML(htmlText, {
|
||||||
innerWidth: draw.getOriginalInnerWidth()
|
innerWidth: draw.getOriginalInnerWidth()
|
||||||
})
|
})
|
||||||
@@ -69,8 +67,7 @@ export function pasteHTML(host: CanvasEvent, htmlText: string) {
|
|||||||
|
|
||||||
export function pasteImage(host: CanvasEvent, file: File | Blob) {
|
export function pasteImage(host: CanvasEvent, file: File | Blob) {
|
||||||
const draw = host.getDraw()
|
const draw = host.getDraw()
|
||||||
const isReadonly = draw.isReadonly()
|
if (draw.isReadonly() || draw.isDisabled()) return
|
||||||
if (isReadonly) return
|
|
||||||
const rangeManager = draw.getRange()
|
const rangeManager = draw.getRange()
|
||||||
const { startIndex } = rangeManager.getRange()
|
const { startIndex } = rangeManager.getRange()
|
||||||
const elementList = draw.getElementList()
|
const elementList = draw.getElementList()
|
||||||
@@ -99,8 +96,7 @@ export function pasteImage(host: CanvasEvent, file: File | Blob) {
|
|||||||
|
|
||||||
export function pasteByEvent(host: CanvasEvent, evt: ClipboardEvent) {
|
export function pasteByEvent(host: CanvasEvent, evt: ClipboardEvent) {
|
||||||
const draw = host.getDraw()
|
const draw = host.getDraw()
|
||||||
const isReadonly = draw.isReadonly()
|
if (draw.isReadonly() || draw.isDisabled()) return
|
||||||
if (isReadonly) return
|
|
||||||
const clipboardData = evt.clipboardData
|
const clipboardData = evt.clipboardData
|
||||||
if (!clipboardData) return
|
if (!clipboardData) return
|
||||||
// 自定义粘贴事件
|
// 自定义粘贴事件
|
||||||
@@ -157,8 +153,7 @@ export function pasteByEvent(host: CanvasEvent, evt: ClipboardEvent) {
|
|||||||
|
|
||||||
export async function pasteByApi(host: CanvasEvent, options?: IPasteOption) {
|
export async function pasteByApi(host: CanvasEvent, options?: IPasteOption) {
|
||||||
const draw = host.getDraw()
|
const draw = host.getDraw()
|
||||||
const isReadonly = draw.isReadonly()
|
if (draw.isReadonly() || draw.isDisabled()) return
|
||||||
if (isReadonly) return
|
|
||||||
// 自定义粘贴事件
|
// 自定义粘贴事件
|
||||||
const { paste } = draw.getOverride()
|
const { paste } = draw.getOverride()
|
||||||
if (paste) {
|
if (paste) {
|
||||||
|
|||||||
@@ -13,34 +13,65 @@ export class SelectionObserver {
|
|||||||
right: number
|
right: number
|
||||||
] = [70, 40, 10, 20]
|
] = [70, 40, 10, 20]
|
||||||
|
|
||||||
|
private selectionContainer: Element | Document
|
||||||
private rangeManager: RangeManager
|
private rangeManager: RangeManager
|
||||||
private requestAnimationFrameId: number | null
|
private requestAnimationFrameId: number | null
|
||||||
private isMousedown: boolean
|
private isMousedown: boolean
|
||||||
private isMoving: boolean
|
private isMoving: boolean
|
||||||
|
private clientWidth: number
|
||||||
|
private clientHeight: number
|
||||||
|
private containerRect: DOMRect | null
|
||||||
|
|
||||||
constructor(draw: Draw) {
|
constructor(draw: Draw) {
|
||||||
|
this.rangeManager = draw.getRange()
|
||||||
|
// 优先使用配置的滚动容器dom
|
||||||
|
const { scrollContainerSelector } = draw.getOptions()
|
||||||
|
this.selectionContainer = scrollContainerSelector
|
||||||
|
? document.querySelector(scrollContainerSelector) || document
|
||||||
|
: document
|
||||||
this.requestAnimationFrameId = null
|
this.requestAnimationFrameId = null
|
||||||
this.isMousedown = false
|
this.isMousedown = false
|
||||||
this.isMoving = false
|
this.isMoving = false
|
||||||
this.rangeManager = draw.getRange()
|
// 缓存尺寸
|
||||||
|
this.clientWidth = 0
|
||||||
|
this.clientHeight = 0
|
||||||
|
this.containerRect = null
|
||||||
|
// 添加监听
|
||||||
this._addEvent()
|
this._addEvent()
|
||||||
}
|
}
|
||||||
|
|
||||||
private _addEvent() {
|
private _addEvent() {
|
||||||
document.addEventListener('mousedown', this._mousedown)
|
const container = <Document>this.selectionContainer
|
||||||
document.addEventListener('mousemove', this._mousemove)
|
container.addEventListener('mousedown', this._mousedown)
|
||||||
document.addEventListener('mouseup', this._mouseup)
|
container.addEventListener('mousemove', this._mousemove)
|
||||||
|
container.addEventListener('mouseup', this._mouseup)
|
||||||
|
document.addEventListener('mouseleave', this._mouseup)
|
||||||
}
|
}
|
||||||
|
|
||||||
public removeEvent() {
|
public removeEvent() {
|
||||||
document.removeEventListener('mousedown', this._mousedown)
|
const container = <Document>this.selectionContainer
|
||||||
document.removeEventListener('mousemove', this._mousemove)
|
container.removeEventListener('mousedown', this._mousedown)
|
||||||
document.removeEventListener('mouseup', this._mouseup)
|
container.removeEventListener('mousemove', this._mousemove)
|
||||||
|
container.removeEventListener('mouseup', this._mouseup)
|
||||||
|
document.removeEventListener('mouseleave', this._mouseup)
|
||||||
}
|
}
|
||||||
|
|
||||||
private _mousedown = () => {
|
private _mousedown = () => {
|
||||||
this.isMousedown = true
|
this.isMousedown = true
|
||||||
|
// 更新容器宽高
|
||||||
|
this.clientWidth =
|
||||||
|
this.selectionContainer instanceof Document
|
||||||
|
? document.documentElement.clientWidth
|
||||||
|
: this.selectionContainer.clientWidth
|
||||||
|
this.clientHeight =
|
||||||
|
this.selectionContainer instanceof Document
|
||||||
|
? document.documentElement.clientHeight
|
||||||
|
: this.selectionContainer.clientHeight
|
||||||
|
// 更新容器位置信息
|
||||||
|
if (!(this.selectionContainer instanceof Document)) {
|
||||||
|
const rect = this.selectionContainer.getBoundingClientRect()
|
||||||
|
this.containerRect = rect
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private _mouseup = () => {
|
private _mouseup = () => {
|
||||||
@@ -50,16 +81,18 @@ export class SelectionObserver {
|
|||||||
|
|
||||||
private _mousemove = (evt: MouseEvent) => {
|
private _mousemove = (evt: MouseEvent) => {
|
||||||
if (!this.isMousedown || this.rangeManager.getIsCollapsed()) return
|
if (!this.isMousedown || this.rangeManager.getIsCollapsed()) return
|
||||||
const { x, y } = evt
|
let { x, y } = evt
|
||||||
const clientWidth = document.documentElement.clientWidth
|
if (this.containerRect) {
|
||||||
const clientHeight = document.documentElement.clientHeight
|
x = x - this.containerRect.x
|
||||||
|
y = y - this.containerRect.y
|
||||||
|
}
|
||||||
if (y < this.thresholdPoints[0]) {
|
if (y < this.thresholdPoints[0]) {
|
||||||
this._startMove(MoveDirection.UP)
|
this._startMove(MoveDirection.UP)
|
||||||
} else if (clientHeight - y <= this.thresholdPoints[1]) {
|
} else if (this.clientHeight - y <= this.thresholdPoints[1]) {
|
||||||
this._startMove(MoveDirection.DOWN)
|
this._startMove(MoveDirection.DOWN)
|
||||||
} else if (x < this.thresholdPoints[2]) {
|
} else if (x < this.thresholdPoints[2]) {
|
||||||
this._startMove(MoveDirection.LEFT)
|
this._startMove(MoveDirection.LEFT)
|
||||||
} else if (clientWidth - x < this.thresholdPoints[3]) {
|
} else if (this.clientWidth - x < this.thresholdPoints[3]) {
|
||||||
this._startMove(MoveDirection.RIGHT)
|
this._startMove(MoveDirection.RIGHT)
|
||||||
} else {
|
} else {
|
||||||
this._stopMove()
|
this._stopMove()
|
||||||
@@ -67,16 +100,27 @@ export class SelectionObserver {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private _move(direction: MoveDirection) {
|
private _move(direction: MoveDirection) {
|
||||||
const x = window.scrollX
|
// Document使用window
|
||||||
const y = window.scrollY
|
const container =
|
||||||
|
this.selectionContainer instanceof Document
|
||||||
|
? window
|
||||||
|
: this.selectionContainer
|
||||||
|
const x =
|
||||||
|
this.selectionContainer instanceof Document
|
||||||
|
? window.scrollX
|
||||||
|
: (<Element>container).scrollLeft
|
||||||
|
const y =
|
||||||
|
this.selectionContainer instanceof Document
|
||||||
|
? window.scrollY
|
||||||
|
: (<Element>container).scrollTop
|
||||||
if (direction === MoveDirection.DOWN) {
|
if (direction === MoveDirection.DOWN) {
|
||||||
window.scrollTo(x, y + this.step)
|
container.scrollTo(x, y + this.step)
|
||||||
} else if (direction === MoveDirection.UP) {
|
} else if (direction === MoveDirection.UP) {
|
||||||
window.scrollTo(x, y - this.step)
|
container.scrollTo(x, y - this.step)
|
||||||
} else if (direction === MoveDirection.LEFT) {
|
} else if (direction === MoveDirection.LEFT) {
|
||||||
window.scrollTo(x - this.step, y)
|
container.scrollTo(x - this.step, y)
|
||||||
} else {
|
} else {
|
||||||
window.scrollTo(x + this.step, y)
|
container.scrollTo(x + this.step, y)
|
||||||
}
|
}
|
||||||
this.requestAnimationFrameId = window.requestAnimationFrame(
|
this.requestAnimationFrameId = window.requestAnimationFrame(
|
||||||
this._move.bind(this, direction)
|
this._move.bind(this, direction)
|
||||||
|
|||||||
@@ -643,6 +643,7 @@ export class Position {
|
|||||||
payload: IGetFloatPositionByXYPayload
|
payload: IGetFloatPositionByXYPayload
|
||||||
): ICurrentPosition | void {
|
): ICurrentPosition | void {
|
||||||
const { x, y } = payload
|
const { x, y } = payload
|
||||||
|
const currentPageNo = payload.pageNo ?? this.draw.getPageNo()
|
||||||
const currentZone = this.draw.getZone().getZone()
|
const currentZone = this.draw.getZone().getZone()
|
||||||
for (let f = 0; f < this.floatPositionList.length; f++) {
|
for (let f = 0; f < this.floatPositionList.length; f++) {
|
||||||
const {
|
const {
|
||||||
@@ -653,9 +654,11 @@ export class Position {
|
|||||||
trIndex,
|
trIndex,
|
||||||
tdIndex,
|
tdIndex,
|
||||||
tdValueIndex,
|
tdValueIndex,
|
||||||
zone: floatElementZone
|
zone: floatElementZone,
|
||||||
|
pageNo
|
||||||
} = this.floatPositionList[f]
|
} = this.floatPositionList[f]
|
||||||
if (
|
if (
|
||||||
|
currentPageNo === pageNo &&
|
||||||
element.type === ElementType.IMAGE &&
|
element.type === ElementType.IMAGE &&
|
||||||
element.imgDisplay === payload.imgDisplay &&
|
element.imgDisplay === payload.imgDisplay &&
|
||||||
(!floatElementZone || floatElementZone === currentZone)
|
(!floatElementZone || floatElementZone === currentZone)
|
||||||
|
|||||||
@@ -171,8 +171,9 @@ export class RangeManager {
|
|||||||
}
|
}
|
||||||
start--
|
start--
|
||||||
}
|
}
|
||||||
|
const isCollapsed = startIndex === endIndex
|
||||||
// 中间选择
|
// 中间选择
|
||||||
if (startIndex !== endIndex) {
|
if (!isCollapsed) {
|
||||||
let middle = startIndex + 1
|
let middle = startIndex + 1
|
||||||
while (middle < endIndex) {
|
while (middle < endIndex) {
|
||||||
const { pageNo, rowNo } = positionList[middle]
|
const { pageNo, rowNo } = positionList[middle]
|
||||||
@@ -189,6 +190,10 @@ export class RangeManager {
|
|||||||
}
|
}
|
||||||
// 向下查找
|
// 向下查找
|
||||||
let end = endIndex
|
let end = endIndex
|
||||||
|
// 闭合选区&&首字符为换行符时继续向下查找
|
||||||
|
if (isCollapsed && elementList[startIndex].value === ZERO) {
|
||||||
|
end += 1
|
||||||
|
}
|
||||||
while (end < positionList.length) {
|
while (end < positionList.length) {
|
||||||
const element = elementList[end]
|
const element = elementList[end]
|
||||||
const nextElement = elementList[end + 1]
|
const nextElement = elementList[end + 1]
|
||||||
@@ -425,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
|
||||||
|
|||||||
@@ -5,5 +5,6 @@ export const defaultBackground: Readonly<Required<IBackgroundOption>> = {
|
|||||||
color: '#FFFFFF',
|
color: '#FFFFFF',
|
||||||
image: '',
|
image: '',
|
||||||
size: BackgroundSize.COVER,
|
size: BackgroundSize.COVER,
|
||||||
repeat: BackgroundRepeat.NO_REPEAT
|
repeat: BackgroundRepeat.NO_REPEAT,
|
||||||
|
applyPageNumbers: []
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -120,8 +120,7 @@ export const CONTROL_STYLE_ATTR: Array<keyof IControlStyle> = [
|
|||||||
export const EDITOR_ELEMENT_CONTEXT_ATTR: Array<keyof IElement> = [
|
export const EDITOR_ELEMENT_CONTEXT_ATTR: Array<keyof IElement> = [
|
||||||
...TABLE_CONTEXT_ATTR,
|
...TABLE_CONTEXT_ATTR,
|
||||||
...TITLE_CONTEXT_ATTR,
|
...TITLE_CONTEXT_ATTR,
|
||||||
...LIST_CONTEXT_ATTR,
|
...LIST_CONTEXT_ATTR
|
||||||
...EDITOR_ROW_ATTR
|
|
||||||
]
|
]
|
||||||
|
|
||||||
export const TEXTLIKE_ELEMENT_TYPE: ElementType[] = [
|
export const TEXTLIKE_ELEMENT_TYPE: ElementType[] = [
|
||||||
|
|||||||
@@ -0,0 +1,11 @@
|
|||||||
|
import { ILineNumberOption } from '../../interface/LineNumber'
|
||||||
|
import { LineNumberType } from '../enum/LineNumber'
|
||||||
|
|
||||||
|
export const defaultLineNumberOption: Readonly<Required<ILineNumberOption>> = {
|
||||||
|
size: 12,
|
||||||
|
font: 'Microsoft YaHei',
|
||||||
|
color: '#000000',
|
||||||
|
disabled: true,
|
||||||
|
right: 20,
|
||||||
|
type: LineNumberType.CONTINUITY
|
||||||
|
}
|
||||||
@@ -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
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,3 +15,8 @@ export enum ImageDisplay {
|
|||||||
FLOAT_TOP = 'float-top',
|
FLOAT_TOP = 'float-top',
|
||||||
FLOAT_BOTTOM = 'float-bottom'
|
FLOAT_BOTTOM = 'float-bottom'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export enum LocationPosition {
|
||||||
|
BEFORE = 'before',
|
||||||
|
AFTER = 'after'
|
||||||
|
}
|
||||||
|
|||||||
@@ -0,0 +1,4 @@
|
|||||||
|
export enum LineNumberType {
|
||||||
|
PAGE = 'page',
|
||||||
|
CONTINUITY = 'continuity'
|
||||||
|
}
|
||||||
+7
-3
@@ -6,7 +6,7 @@ import { Command } from './core/command/Command'
|
|||||||
import { CommandAdapt } from './core/command/CommandAdapt'
|
import { CommandAdapt } from './core/command/CommandAdapt'
|
||||||
import { Listener } from './core/listener/Listener'
|
import { Listener } from './core/listener/Listener'
|
||||||
import { RowFlex } from './dataset/enum/Row'
|
import { RowFlex } from './dataset/enum/Row'
|
||||||
import { ImageDisplay } from './dataset/enum/Common'
|
import { ImageDisplay, LocationPosition } from './dataset/enum/Common'
|
||||||
import { ElementType } from './dataset/enum/Element'
|
import { ElementType } from './dataset/enum/Element'
|
||||||
import { formatElementList } from './utils/element'
|
import { formatElementList } from './utils/element'
|
||||||
import { Register } from './core/register/Register'
|
import { Register } from './core/register/Register'
|
||||||
@@ -52,6 +52,7 @@ import { deepClone, splitText } from './utils'
|
|||||||
import { BackgroundRepeat, BackgroundSize } from './dataset/enum/Background'
|
import { BackgroundRepeat, BackgroundSize } from './dataset/enum/Background'
|
||||||
import { TextDecorationStyle } from './dataset/enum/Text'
|
import { TextDecorationStyle } from './dataset/enum/Text'
|
||||||
import { mergeOption } from './utils/option'
|
import { mergeOption } from './utils/option'
|
||||||
|
import { LineNumberType } from './dataset/enum/LineNumber'
|
||||||
|
|
||||||
export default class Editor {
|
export default class Editor {
|
||||||
public command: Command
|
public command: Command
|
||||||
@@ -88,7 +89,8 @@ export default class Editor {
|
|||||||
]
|
]
|
||||||
pageComponentData.forEach(elementList => {
|
pageComponentData.forEach(elementList => {
|
||||||
formatElementList(elementList, {
|
formatElementList(elementList, {
|
||||||
editorOptions
|
editorOptions,
|
||||||
|
isForceCompensation: true
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
// 监听
|
// 监听
|
||||||
@@ -169,7 +171,9 @@ export {
|
|||||||
ControlIndentation,
|
ControlIndentation,
|
||||||
BackgroundRepeat,
|
BackgroundRepeat,
|
||||||
BackgroundSize,
|
BackgroundSize,
|
||||||
TextDecorationStyle
|
TextDecorationStyle,
|
||||||
|
LineNumberType,
|
||||||
|
LocationPosition
|
||||||
}
|
}
|
||||||
|
|
||||||
// 对外类型
|
// 对外类型
|
||||||
|
|||||||
@@ -5,4 +5,5 @@ export interface IBackgroundOption {
|
|||||||
image?: string
|
image?: string
|
||||||
size?: BackgroundSize
|
size?: BackgroundSize
|
||||||
repeat?: BackgroundRepeat
|
repeat?: BackgroundRepeat
|
||||||
|
applyPageNumbers?: number[]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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,3 +1,4 @@
|
|||||||
|
import { LocationPosition } from '../dataset/enum/Common'
|
||||||
import { ControlType, ControlIndentation } from '../dataset/enum/Control'
|
import { ControlType, ControlIndentation } from '../dataset/enum/Control'
|
||||||
import { EditorZone } from '../dataset/enum/Editor'
|
import { EditorZone } from '../dataset/enum/Editor'
|
||||||
import { MoveDirection } from '../dataset/enum/Observer'
|
import { MoveDirection } from '../dataset/enum/Observer'
|
||||||
@@ -40,7 +41,8 @@ export interface IControlHighlightRule {
|
|||||||
|
|
||||||
export interface IControlHighlight {
|
export interface IControlHighlight {
|
||||||
ruleList: IControlHighlightRule[]
|
ruleList: IControlHighlightRule[]
|
||||||
conceptId: string
|
id?: string
|
||||||
|
conceptId?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IControlRule {
|
export interface IControlRule {
|
||||||
@@ -124,7 +126,8 @@ export interface IControlRuleOption {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface IGetControlValueOption {
|
export interface IGetControlValueOption {
|
||||||
conceptId: string
|
id?: string
|
||||||
|
conceptId?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
export type IGetControlValueResult = (Omit<IControl, 'value'> & {
|
export type IGetControlValueResult = (Omit<IControl, 'value'> & {
|
||||||
@@ -134,19 +137,22 @@ export type IGetControlValueResult = (Omit<IControl, 'value'> & {
|
|||||||
})[]
|
})[]
|
||||||
|
|
||||||
export interface ISetControlValueOption {
|
export interface ISetControlValueOption {
|
||||||
conceptId: string
|
id?: string
|
||||||
|
conceptId?: string
|
||||||
value: string
|
value: string
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ISetControlExtensionOption {
|
export interface ISetControlExtensionOption {
|
||||||
conceptId: string
|
id?: string
|
||||||
|
conceptId?: string
|
||||||
extension: unknown
|
extension: unknown
|
||||||
}
|
}
|
||||||
|
|
||||||
export type ISetControlHighlightOption = IControlHighlight[]
|
export type ISetControlHighlightOption = IControlHighlight[]
|
||||||
|
|
||||||
export type ISetControlProperties = {
|
export type ISetControlProperties = {
|
||||||
conceptId: string
|
id?: string
|
||||||
|
conceptId?: string
|
||||||
properties: Partial<Omit<IControl, 'value'>>
|
properties: Partial<Omit<IControl, 'value'>>
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -163,3 +169,7 @@ export interface INextControlContext {
|
|||||||
export interface IInitNextControlOption {
|
export interface IInitNextControlOption {
|
||||||
direction?: MoveDirection
|
direction?: MoveDirection
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface ILocationControlOption {
|
||||||
|
position: LocationPosition
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { IElement } from '..'
|
import { IElement, LocationPosition } from '..'
|
||||||
import {
|
import {
|
||||||
EditorMode,
|
EditorMode,
|
||||||
PageMode,
|
PageMode,
|
||||||
@@ -24,6 +24,8 @@ import { IWatermark } from './Watermark'
|
|||||||
import { IZoneOption } from './Zone'
|
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 { IPageBorderOption } from './PageBorder'
|
||||||
|
|
||||||
export interface IEditorData {
|
export interface IEditorData {
|
||||||
header?: IElement[]
|
header?: IElement[]
|
||||||
@@ -89,6 +91,8 @@ export interface IEditorOption {
|
|||||||
background?: IBackgroundOption
|
background?: IBackgroundOption
|
||||||
lineBreak?: ILineBreakOption
|
lineBreak?: ILineBreakOption
|
||||||
separator?: ISeparatorOption
|
separator?: ISeparatorOption
|
||||||
|
lineNumber?: ILineNumberOption
|
||||||
|
pageBorder?: IPageBorderOption
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IEditorResult {
|
export interface IEditorResult {
|
||||||
@@ -117,3 +121,11 @@ export type IUpdateOption = Omit<
|
|||||||
| 'historyMaxRecordCount'
|
| 'historyMaxRecordCount'
|
||||||
| 'scrollContainerSelector'
|
| 'scrollContainerSelector'
|
||||||
>
|
>
|
||||||
|
|
||||||
|
export interface ISetValueOption {
|
||||||
|
isSetCursor?: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IFocusOption {
|
||||||
|
position?: LocationPosition
|
||||||
|
}
|
||||||
|
|||||||
@@ -177,5 +177,5 @@ export interface IElementFillRect {
|
|||||||
|
|
||||||
export interface IUpdateElementByIdOption {
|
export interface IUpdateElementByIdOption {
|
||||||
id: string
|
id: string
|
||||||
properties: Omit<IElement, 'id'>
|
properties: Omit<Partial<IElement>, 'id'>
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,10 @@
|
|||||||
|
import { LineNumberType } from '../dataset/enum/LineNumber'
|
||||||
|
|
||||||
|
export interface ILineNumberOption {
|
||||||
|
size?: number
|
||||||
|
font?: string
|
||||||
|
color?: string
|
||||||
|
disabled?: boolean
|
||||||
|
right?: number
|
||||||
|
type?: LineNumberType
|
||||||
|
}
|
||||||
@@ -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
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,4 +19,5 @@ export interface IRow {
|
|||||||
offsetX?: number
|
offsetX?: number
|
||||||
elementList: IRowElement[]
|
elementList: IRowElement[]
|
||||||
isWidthNotEnough?: boolean
|
isWidthNotEnough?: boolean
|
||||||
|
rowIndex: number
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ export type ITitleOption = ITitleSizeOption & {}
|
|||||||
|
|
||||||
export interface ITitleRule {
|
export interface ITitleRule {
|
||||||
deletable?: boolean
|
deletable?: boolean
|
||||||
|
disabled?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
export type ITitle = ITitleRule & {
|
export type ITitle = ITitleRule & {
|
||||||
|
|||||||
+41
-22
@@ -4,6 +4,7 @@ import {
|
|||||||
deepCloneOmitKeys,
|
deepCloneOmitKeys,
|
||||||
getUUID,
|
getUUID,
|
||||||
isArrayEqual,
|
isArrayEqual,
|
||||||
|
omitObject,
|
||||||
pickObject,
|
pickObject,
|
||||||
splitText
|
splitText
|
||||||
} from '.'
|
} from '.'
|
||||||
@@ -29,7 +30,8 @@ import {
|
|||||||
INLINE_NODE_NAME,
|
INLINE_NODE_NAME,
|
||||||
TABLE_CONTEXT_ATTR,
|
TABLE_CONTEXT_ATTR,
|
||||||
TABLE_TD_ZIP_ATTR,
|
TABLE_TD_ZIP_ATTR,
|
||||||
TEXTLIKE_ELEMENT_TYPE
|
TEXTLIKE_ELEMENT_TYPE,
|
||||||
|
TITLE_CONTEXT_ATTR
|
||||||
} from '../dataset/constant/Element'
|
} from '../dataset/constant/Element'
|
||||||
import {
|
import {
|
||||||
listStyleCSSMapping,
|
listStyleCSSMapping,
|
||||||
@@ -63,7 +65,8 @@ export function unzipElementList(elementList: IElement[]): IElement[] {
|
|||||||
}
|
}
|
||||||
|
|
||||||
interface IFormatElementListOption {
|
interface IFormatElementListOption {
|
||||||
isHandleFirstElement?: boolean
|
isHandleFirstElement?: boolean // 根据上下文确定首字符处理逻辑(处理首字符补偿)
|
||||||
|
isForceCompensation?: boolean // 强制补偿字符
|
||||||
editorOptions: DeepRequired<IEditorOption>
|
editorOptions: DeepRequired<IEditorOption>
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -71,17 +74,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 ||
|
||||||
|
(isHandleFirstElement &&
|
||||||
startElement?.type !== ElementType.LIST &&
|
startElement?.type !== ElementType.LIST &&
|
||||||
((startElement?.type && startElement.type !== ElementType.TEXT) ||
|
((startElement?.type && startElement.type !== ElementType.TEXT) ||
|
||||||
!START_LINE_BREAK_REG.test(startElement?.value))
|
!START_LINE_BREAK_REG.test(startElement?.value)))
|
||||||
) {
|
) {
|
||||||
elementList.unshift({
|
elementList.unshift({
|
||||||
value: ZERO
|
value: ZERO
|
||||||
@@ -98,7 +103,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) {
|
||||||
@@ -132,7 +138,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) {
|
||||||
@@ -168,7 +175,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]
|
||||||
@@ -234,7 +242,10 @@ export function formatElementList(
|
|||||||
// 移除父节点
|
// 移除父节点
|
||||||
elementList.splice(i, 1)
|
elementList.splice(i, 1)
|
||||||
// 控件上下文提取(压缩后的控件上下文无法提取)
|
// 控件上下文提取(压缩后的控件上下文无法提取)
|
||||||
const controlContext = pickObject(el, EDITOR_ELEMENT_CONTEXT_ATTR)
|
const controlContext = pickObject(el, [
|
||||||
|
...EDITOR_ELEMENT_CONTEXT_ATTR,
|
||||||
|
...EDITOR_ROW_ATTR
|
||||||
|
])
|
||||||
// 控件设置的默认样式(以前缀为基准)
|
// 控件设置的默认样式(以前缀为基准)
|
||||||
const controlDefaultStyle = pickObject(
|
const controlDefaultStyle = pickObject(
|
||||||
<IElement>(<unknown>el.control),
|
<IElement>(<unknown>el.control),
|
||||||
@@ -285,6 +296,7 @@ export function formatElementList(
|
|||||||
// checkbox组件
|
// checkbox组件
|
||||||
elementList.splice(i, 0, {
|
elementList.splice(i, 0, {
|
||||||
...controlContext,
|
...controlContext,
|
||||||
|
...controlDefaultStyle,
|
||||||
controlId,
|
controlId,
|
||||||
value: '',
|
value: '',
|
||||||
type: el.type,
|
type: el.type,
|
||||||
@@ -332,6 +344,7 @@ export function formatElementList(
|
|||||||
// radio组件
|
// radio组件
|
||||||
elementList.splice(i, 0, {
|
elementList.splice(i, 0, {
|
||||||
...controlContext,
|
...controlContext,
|
||||||
|
...controlDefaultStyle,
|
||||||
controlId,
|
controlId,
|
||||||
value: '',
|
value: '',
|
||||||
type: el.type,
|
type: el.type,
|
||||||
@@ -378,7 +391,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]
|
||||||
@@ -444,7 +458,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) {
|
||||||
@@ -816,8 +830,12 @@ export function formatElementContext(
|
|||||||
anchorIndex: number,
|
anchorIndex: number,
|
||||||
options?: IFormatElementContextOption
|
options?: IFormatElementContextOption
|
||||||
) {
|
) {
|
||||||
const copyElement = getAnchorElement(sourceElementList, anchorIndex)
|
let copyElement = getAnchorElement(sourceElementList, anchorIndex)
|
||||||
if (!copyElement) return
|
if (!copyElement) return
|
||||||
|
// 标题元素禁用时不复制标题属性
|
||||||
|
if (copyElement.title?.disabled) {
|
||||||
|
copyElement = omitObject(copyElement, TITLE_CONTEXT_ATTR)
|
||||||
|
}
|
||||||
const { isBreakWhenWrap = false } = options || {}
|
const { isBreakWhenWrap = false } = options || {}
|
||||||
// 是否已经换行
|
// 是否已经换行
|
||||||
let isBreakWarped = false
|
let isBreakWarped = false
|
||||||
@@ -837,9 +855,9 @@ export function formatElementContext(
|
|||||||
(!copyElement.listId && targetElement.type === ElementType.LIST)
|
(!copyElement.listId && targetElement.type === ElementType.LIST)
|
||||||
) {
|
) {
|
||||||
const cloneAttr = [...TABLE_CONTEXT_ATTR, ...EDITOR_ROW_ATTR]
|
const cloneAttr = [...TABLE_CONTEXT_ATTR, ...EDITOR_ROW_ATTR]
|
||||||
cloneProperty<IElement>(cloneAttr, copyElement, targetElement)
|
cloneProperty<IElement>(cloneAttr, copyElement!, targetElement)
|
||||||
targetElement.valueList?.forEach(valueItem => {
|
targetElement.valueList?.forEach(valueItem => {
|
||||||
cloneProperty<IElement>(cloneAttr, copyElement, valueItem)
|
cloneProperty<IElement>(cloneAttr, copyElement!, valueItem)
|
||||||
})
|
})
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@@ -850,11 +868,12 @@ export function formatElementContext(
|
|||||||
anchorIndex
|
anchorIndex
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
cloneProperty<IElement>(
|
// 非块类元素,需处理行属性
|
||||||
EDITOR_ELEMENT_CONTEXT_ATTR,
|
const cloneAttr = [...EDITOR_ELEMENT_CONTEXT_ATTR]
|
||||||
copyElement,
|
if (!getIsBlockElement(targetElement)) {
|
||||||
targetElement
|
cloneAttr.push(...EDITOR_ROW_ATTR)
|
||||||
)
|
}
|
||||||
|
cloneProperty<IElement>(cloneAttr, copyElement, targetElement)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ import { defaultTableOption } from '../dataset/constant/Table'
|
|||||||
import { defaultTitleOption } from '../dataset/constant/Title'
|
import { defaultTitleOption } from '../dataset/constant/Title'
|
||||||
import { defaultWatermarkOption } from '../dataset/constant/Watermark'
|
import { defaultWatermarkOption } from '../dataset/constant/Watermark'
|
||||||
import { defaultZoneOption } from '../dataset/constant/Zone'
|
import { defaultZoneOption } from '../dataset/constant/Zone'
|
||||||
|
import { defaultLineNumberOption } from '../dataset/constant/LineNumber'
|
||||||
import { IBackgroundOption } from '../interface/Background'
|
import { IBackgroundOption } from '../interface/Background'
|
||||||
import { ICheckboxOption } from '../interface/Checkbox'
|
import { ICheckboxOption } from '../interface/Checkbox'
|
||||||
import { DeepRequired } from '../interface/Common'
|
import { DeepRequired } from '../interface/Common'
|
||||||
@@ -35,6 +36,9 @@ import { ITableOption } from '../interface/table/Table'
|
|||||||
import { ITitleOption } from '../interface/Title'
|
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 { IPageBorderOption } from '../interface/PageBorder'
|
||||||
|
import { defaultPageBorderOption } from '../dataset/constant/PageBorder'
|
||||||
import {
|
import {
|
||||||
EditorMode,
|
EditorMode,
|
||||||
PageMode,
|
PageMode,
|
||||||
@@ -114,6 +118,14 @@ export function mergeOption(
|
|||||||
...defaultSeparatorOption,
|
...defaultSeparatorOption,
|
||||||
...options.separator
|
...options.separator
|
||||||
}
|
}
|
||||||
|
const lineNumberOptions: Required<ILineNumberOption> = {
|
||||||
|
...defaultLineNumberOption,
|
||||||
|
...options.lineNumber
|
||||||
|
}
|
||||||
|
const pageBorderOptions: Required<IPageBorderOption> = {
|
||||||
|
...defaultPageBorderOption,
|
||||||
|
...options.pageBorder
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
mode: EditorMode.EDIT,
|
mode: EditorMode.EDIT,
|
||||||
@@ -173,6 +185,8 @@ export function mergeOption(
|
|||||||
zone: zoneOptions,
|
zone: zoneOptions,
|
||||||
background: backgroundOptions,
|
background: backgroundOptions,
|
||||||
lineBreak: lineBreakOptions,
|
lineBreak: lineBreakOptions,
|
||||||
separator: separatorOptions
|
separator: separatorOptions,
|
||||||
|
lineNumber: lineNumberOptions,
|
||||||
|
pageBorder: pageBorderOptions
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,35 @@
|
|||||||
import { PaperDirection } from '../dataset/enum/Editor'
|
import { PaperDirection } from '../dataset/enum/Editor'
|
||||||
|
|
||||||
|
function convertPxToPaperSize(width: number, height: number) {
|
||||||
|
if (width === 1125 && height === 1593) {
|
||||||
|
return {
|
||||||
|
size: 'a3',
|
||||||
|
width: '297mm',
|
||||||
|
height: '420mm'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (width === 794 && height === 1123) {
|
||||||
|
return {
|
||||||
|
size: 'a4',
|
||||||
|
width: '210mm',
|
||||||
|
height: '297mm'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (width === 565 && height === 796) {
|
||||||
|
return {
|
||||||
|
size: 'a5',
|
||||||
|
width: '148mm',
|
||||||
|
height: '210mm'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 其他默认不转换
|
||||||
|
return {
|
||||||
|
size: '',
|
||||||
|
width: `${width}px`,
|
||||||
|
height: `${height}px`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export interface IPrintImageBase64Option {
|
export interface IPrintImageBase64Option {
|
||||||
width: number
|
width: number
|
||||||
height: number
|
height: number
|
||||||
@@ -24,10 +54,17 @@ export function printImageBase64(
|
|||||||
const doc = contentWindow.document
|
const doc = contentWindow.document
|
||||||
doc.open()
|
doc.open()
|
||||||
const container = document.createElement('div')
|
const container = document.createElement('div')
|
||||||
|
const paperSize = convertPxToPaperSize(width, height)
|
||||||
base64List.forEach(base64 => {
|
base64List.forEach(base64 => {
|
||||||
const image = document.createElement('img')
|
const image = document.createElement('img')
|
||||||
image.style.width = `${width}px`
|
image.style.width =
|
||||||
image.style.height = `${height}px`
|
direction === PaperDirection.HORIZONTAL
|
||||||
|
? paperSize.height
|
||||||
|
: paperSize.width
|
||||||
|
image.style.height =
|
||||||
|
direction === PaperDirection.HORIZONTAL
|
||||||
|
? paperSize.width
|
||||||
|
: paperSize.height
|
||||||
image.src = base64
|
image.src = base64
|
||||||
container.append(image)
|
container.append(image)
|
||||||
})
|
})
|
||||||
@@ -39,7 +76,9 @@ export function printImageBase64(
|
|||||||
}
|
}
|
||||||
@page {
|
@page {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
size: ${direction === PaperDirection.HORIZONTAL ? `landscape` : `portrait`};
|
size: ${paperSize.size} ${
|
||||||
|
direction === PaperDirection.HORIZONTAL ? `landscape` : `portrait`
|
||||||
|
};
|
||||||
}`
|
}`
|
||||||
style.append(document.createTextNode(stylesheet))
|
style.append(document.createTextNode(stylesheet))
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
|
|||||||
Reference in New Issue
Block a user