feat: set control highlight rule #332
This commit is contained in:
@@ -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']
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ import {
|
||||
IGetControlValueOption,
|
||||
IGetControlValueResult,
|
||||
ISetControlExtensionOption,
|
||||
ISetControlHighlightOption,
|
||||
ISetControlValueOption
|
||||
} from '../../interface/Control'
|
||||
import {
|
||||
@@ -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()
|
||||
}
|
||||
|
||||
@@ -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, {
|
||||
@@ -1935,6 +1937,8 @@ export class Draw {
|
||||
if (searchKeyword) {
|
||||
this.search.compute(searchKeyword)
|
||||
}
|
||||
// 控件关键词高亮
|
||||
this.control.computeHighlightList()
|
||||
}
|
||||
// 清除光标等副作用
|
||||
this.imageObserver.clearAll()
|
||||
|
||||
@@ -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,
|
||||
@@ -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'
|
||||
@@ -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'
|
||||
|
||||
@@ -40,7 +44,9 @@ 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) {
|
||||
@@ -48,11 +54,32 @@ export class Control {
|
||||
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
|
||||
}
|
||||
@@ -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(
|
||||
@@ -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) {
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
}
|
||||
@@ -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[] = []
|
||||
// 分组
|
||||
@@ -162,7 +165,6 @@ export class Search {
|
||||
elementList: IElement[]
|
||||
index: number
|
||||
}[] = []
|
||||
const originalElementList = this.draw.getOriginalElementList()
|
||||
const originalElementListLength = originalElementList.length
|
||||
// 查找表格所在位置
|
||||
const tableIndexList = []
|
||||
@@ -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) {
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
@@ -108,3 +119,5 @@ export interface ISetControlExtensionOption {
|
||||
conceptId: string
|
||||
extension: unknown
|
||||
}
|
||||
|
||||
export type ISetControlHighlightOption = IControlHighlight[]
|
||||
|
||||
Reference in New Issue
Block a user