Skip to content

Commit

Permalink
feat: set control highlight rule #332
Browse files Browse the repository at this point in the history
  • Loading branch information
Hufe921 committed Dec 16, 2023
1 parent 285aeec commit b6fe212
Show file tree
Hide file tree
Showing 10 changed files with 231 additions and 8 deletions.
10 changes: 10 additions & 0 deletions docs/en/guide/command-execute.md
Original file line number Diff line number Diff line change
Expand Up @@ -891,3 +891,13 @@ Usage:
```javascript
instance.command.executeSetControlExtension(payload: ISetControlExtensionOption)
```

## executeSetControlHighlight

Feature: Set control highlight (by keyword)

Usage:

```javascript
instance.command.executeSetControlHighlight(payload: ISetControlHighlightOption)
```
10 changes: 10 additions & 0 deletions docs/guide/command-execute.md
Original file line number Diff line number Diff line change
Expand Up @@ -891,3 +891,13 @@ instance.command.executeSetControlValue(payload: ISetControlValueOption)
```javascript
instance.command.executeSetControlExtension(payload: ISetControlExtensionOption)
```

## executeSetControlHighlight

功能:设置控件高亮(根据关键词)

用法:

```javascript
instance.command.executeSetControlHighlight(payload: ISetControlHighlightOption)
```
2 changes: 2 additions & 0 deletions src/editor/core/command/Command.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ export class Command {
public executeSetZone: CommandAdapt['setZone']
public executeSetControlValue: CommandAdapt['setControlValue']
public executeSetControlExtension: CommandAdapt['setControlExtension']
public executeSetControlHighlight: CommandAdapt['setControlHighlight']
public getCatalog: CommandAdapt['getCatalog']
public getImage: CommandAdapt['getImage']
public getOptions: CommandAdapt['getOptions']
Expand Down Expand Up @@ -221,6 +222,7 @@ export class Command {
// 控件
this.executeSetControlValue = adapt.setControlValue.bind(adapt)
this.executeSetControlExtension = adapt.setControlExtension.bind(adapt)
this.executeSetControlHighlight = adapt.setControlHighlight.bind(adapt)
this.getControlValue = adapt.getControlValue.bind(adapt)
}
}
5 changes: 5 additions & 0 deletions src/editor/core/command/CommandAdapt.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import {
IGetControlValueOption,
IGetControlValueResult,
ISetControlExtensionOption,
ISetControlHighlightOption,
ISetControlValueOption
} from '../../interface/Control'
import {
Expand Down Expand Up @@ -2197,6 +2198,10 @@ export class CommandAdapt {
this.draw.getControl().setExtensionByConceptId(payload)
}

public setControlHighlight(payload: ISetControlHighlightOption) {
this.draw.getControl().setHighlightList(payload)
}

public getContainer(): HTMLDivElement {
return this.draw.getContainer()
}
Expand Down
4 changes: 4 additions & 0 deletions src/editor/core/draw/Draw.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1821,6 +1821,8 @@ export class Draw {
if (this.mode !== EditorMode.PRINT) {
this.margin.render(ctx, pageNo)
}
// 控件高亮
this.control.renderHighlightList(ctx, pageNo)
// 渲染元素
const index = rowList[0].startIndex
this.drawRow(ctx, {
Expand Down Expand Up @@ -1935,6 +1937,8 @@ export class Draw {
if (searchKeyword) {
this.search.compute(searchKeyword)
}
// 控件关键词高亮
this.control.computeHighlightList()
}
// 清除光标等副作用
this.imageObserver.clearAll()
Expand Down
35 changes: 31 additions & 4 deletions src/editor/core/draw/control/Control.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import { ControlComponent, ControlType } from '../../../dataset/enum/Control'
import { EditorZone } from '../../../dataset/enum/Editor'
import { ElementType } from '../../../dataset/enum/Element'
import { DeepRequired } from '../../../interface/Common'
import {
IControl,
IControlContext,
IControlHighlight,
IControlInitOption,
IControlInstance,
IControlOption,
Expand All @@ -13,6 +15,7 @@ import {
ISetControlExtensionOption,
ISetControlValueOption
} from '../../../interface/Control'
import { IEditorOption } from '../../../interface/Editor'
import { IElement, IElementPosition } from '../../../interface/Element'
import { EventBusMap } from '../../../interface/EventBus'
import { IRange } from '../../../interface/Range'
Expand All @@ -28,6 +31,7 @@ import { Listener } from '../../listener/Listener'
import { RangeManager } from '../../range/RangeManager'
import { Draw } from '../Draw'
import { CheckboxControl } from './checkbox/CheckboxControl'
import { ControlSearch } from './interactive/ControlSearch'
import { SelectControl } from './select/SelectControl'
import { TextControl } from './text/TextControl'

Expand All @@ -40,19 +44,42 @@ export class Control {
private range: RangeManager
private listener: Listener
private eventBus: EventBus<EventBusMap>
private options: IControlOption
private controlSearch: ControlSearch
private options: DeepRequired<IEditorOption>
private controlOptions: IControlOption
private activeControl: IControlInstance | null

constructor(draw: Draw) {
this.draw = draw
this.range = draw.getRange()
this.listener = draw.getListener()
this.eventBus = draw.getEventBus()
this.controlSearch = new ControlSearch(this)

this.options = draw.getOptions().control
this.options = draw.getOptions()
this.controlOptions = this.options.control
this.activeControl = null
}

// 搜索高亮匹配
public setHighlightList(payload: IControlHighlight[]) {
this.controlSearch.setHighlightList(payload)
}

public computeHighlightList() {
const highlightList = this.controlSearch.getHighlightList()
if (highlightList.length) {
this.controlSearch.computeHighlightList()
}
}

public renderHighlightList(ctx: CanvasRenderingContext2D, pageNo: number) {
const highlightMatchResult = this.controlSearch.getHighlightMatchResult()
if (highlightMatchResult.length) {
this.controlSearch.renderHighlightList(ctx, pageNo)
}
}

public getDraw(): Draw {
return this.draw
}
Expand Down Expand Up @@ -395,7 +422,7 @@ export class Control {
type: ElementType.CONTROL,
control: startElement.control,
controlComponent: ControlComponent.PLACEHOLDER,
color: this.options.placeholderColor
color: this.controlOptions.placeholderColor
}
formatElementContext(elementList, [newElement], startIndex)
this.draw.spliceElementList(
Expand Down Expand Up @@ -561,7 +588,7 @@ export class Control {
const formatValue = [{ value }]
formatElementList(formatValue, {
isHandleFirstElement: false,
editorOptions: this.draw.getOptions()
editorOptions: this.options
})
const text = new TextControl(element, this)
if (value) {
Expand Down
145 changes: 145 additions & 0 deletions src/editor/core/draw/control/interactive/ControlSearch.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
import { ElementType } from '../../../../dataset/enum/Element'
import { DeepRequired } from '../../../../interface/Common'
import {
IControlHighlight,
IControlHighlightRule
} from '../../../../interface/Control'
import { IEditorOption } from '../../../../interface/Editor'
import { IElement, IElementPosition } from '../../../../interface/Element'
import {
ISearchResult,
ISearchResultRestArgs
} from '../../../../interface/Search'
import { Draw } from '../../Draw'
import { Control } from '../Control'

type IHighlightMatchResult = (ISearchResult & IControlHighlightRule)[]

export class ControlSearch {
private draw: Draw
private options: DeepRequired<IEditorOption>
private highlightList: IControlHighlight[]
private highlightMatchResult: IHighlightMatchResult

constructor(control: Control) {
this.draw = control.getDraw()
this.options = this.draw.getOptions()

this.highlightList = []
this.highlightMatchResult = []
}

public getHighlightMatchResult(): IHighlightMatchResult {
return this.highlightMatchResult
}

public getHighlightList(): IControlHighlight[] {
return this.highlightList
}

public setHighlightList(payload: IControlHighlight[]) {
this.highlightList = payload
}

public computeHighlightList() {
const search = this.draw.getSearch()
const computeHighlight = (
elementList: IElement[],
restArgs?: ISearchResultRestArgs
) => {
let i = 0
while (i < elementList.length) {
const element = elementList[i]
i++
// 表格下钻处理
if (element.type === ElementType.TABLE) {
const trList = element.trList!
for (let r = 0; r < trList.length; r++) {
const tr = trList[r]
for (let d = 0; d < tr.tdList.length; d++) {
const td = tr.tdList[d]
const restArgs: ISearchResultRestArgs = {
tableId: element.id,
tableIndex: i - 1,
trIndex: r,
tdIndex: d,
tdId: td.id
}
computeHighlight(td.value, restArgs)
}
}
}
const controlConceptId = element?.control?.conceptId
if (!controlConceptId) continue
const highlightIndex = this.highlightList.findIndex(
highlight => highlight.conceptId === controlConceptId
)
if (!~highlightIndex) continue
// 搜索后控件结束索引
const startIndex = i
let newEndIndex = i
while (newEndIndex < elementList.length) {
const nextElement = elementList[newEndIndex]
if (nextElement.controlId !== element.controlId) break
newEndIndex++
}
i = newEndIndex
// 高亮信息
const controlElementList = elementList.slice(startIndex, newEndIndex)
const highlight = this.highlightList[highlightIndex]
const { ruleList } = highlight
for (let r = 0; r < ruleList.length; r++) {
const rule = ruleList[r]
const searchResult = search.getMatchList(
rule.keyword,
controlElementList
)
this.highlightMatchResult.push(
...searchResult.map(result => ({
...result,
...rule,
...restArgs,
index: result.index + startIndex // 实际索引
}))
)
}
}
}
this.highlightMatchResult = []
computeHighlight(this.draw.getOriginalMainElementList())
}

public renderHighlightList(ctx: CanvasRenderingContext2D, pageIndex: number) {
if (!this.highlightMatchResult?.length) return
const { searchMatchAlpha, searchMatchColor } = this.options
const positionList = this.draw.getPosition().getOriginalPositionList()
const elementList = this.draw.getOriginalElementList()
ctx.save()
for (let s = 0; s < this.highlightMatchResult.length; s++) {
const searchMatch = this.highlightMatchResult[s]
let position: IElementPosition | null = null
if (searchMatch.tableId) {
const { tableIndex, trIndex, tdIndex, index } = searchMatch
position =
elementList[tableIndex!]?.trList![trIndex!].tdList[tdIndex!]
?.positionList![index]
} else {
position = positionList[searchMatch.index]
}
if (!position) continue
const {
coordinate: { leftTop, leftBottom, rightTop },
pageNo
} = position
if (pageNo !== pageIndex) continue
ctx.fillStyle = searchMatch.backgroundColor || searchMatchColor
ctx.globalAlpha = searchMatch.alpha || searchMatchAlpha
const x = leftTop[0]
const y = leftTop[1]
const width = rightTop[0] - leftTop[0]
const height = leftBottom[1] - leftTop[1]
ctx.fillRect(x, y, width, height)
}
ctx.restore()
}
}
11 changes: 8 additions & 3 deletions src/editor/core/draw/interactive/Search.ts
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,10 @@ export class Search {
}
}

public getMatchList(payload: string): ISearchResult[] {
public getMatchList(
payload: string,
originalElementList: IElement[]
): ISearchResult[] {
const keyword = payload.toLocaleLowerCase()
const searchMatchList: ISearchResult[] = []
// 分组
Expand All @@ -162,7 +165,6 @@ export class Search {
elementList: IElement[]
index: number
}[] = []
const originalElementList = this.draw.getOriginalElementList()
const originalElementListLength = originalElementList.length
// 查找表格所在位置
const tableIndexList = []
Expand Down Expand Up @@ -264,7 +266,10 @@ export class Search {
}

public compute(payload: string) {
this.searchMatchList = this.getMatchList(payload)
this.searchMatchList = this.getMatchList(
payload,
this.draw.getOriginalElementList()
)
}

public render(ctx: CanvasRenderingContext2D, pageIndex: number) {
Expand Down
4 changes: 3 additions & 1 deletion src/editor/core/range/RangeManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -249,7 +249,9 @@ export class RangeManager {
}

public getKeywordRangeList(payload: string): IRange[] {
const searchMatchList = this.draw.getSearch().getMatchList(payload)
const searchMatchList = this.draw
.getSearch()
.getMatchList(payload, this.draw.getOriginalElementList())
const searchRangeMap: Map<string, IRange> = new Map()
for (const searchMatch of searchMatchList) {
const searchRange = searchRangeMap.get(searchMatch.groupId)
Expand Down
13 changes: 13 additions & 0 deletions src/editor/interface/Control.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,17 @@ export interface IControlCheckbox {
checkbox?: ICheckbox
}

export interface IControlHighlightRule {
keyword: string
alpha?: number
backgroundColor?: string
}

export interface IControlHighlight {
ruleList: IControlHighlightRule[]
conceptId: string
}

export interface IControlRule {
deletable?: boolean
disabled?: boolean
Expand Down Expand Up @@ -108,3 +119,5 @@ export interface ISetControlExtensionOption {
conceptId: string
extension: unknown
}

export type ISetControlHighlightOption = IControlHighlight[]

0 comments on commit b6fe212

Please sign in to comment.