feat:search in table

pr675
黄云飞 4 years ago
parent c813923fe3
commit 6c553129df

@ -1,11 +1,13 @@
import { ZERO } from "../../dataset/constant/Common"
import { EDITOR_ELEMENT_STYLE } from "../../dataset/constant/Element"
import { EditorContext } from "../../dataset/enum/Editor"
import { ElementType } from "../../dataset/enum/Element"
import { ElementStyleKey } from "../../dataset/enum/ElementStyle"
import { RowFlex } from "../../dataset/enum/Row"
import { IDrawImagePayload } from "../../interface/Draw"
import { IEditorOption } from "../../interface/Editor"
import { IElement, IElementStyle } from "../../interface/Element"
import { ISearchResult, ISearchResultRestArgs } from "../../interface/Search"
import { IColgroup } from "../../interface/table/Colgroup"
import { ITd } from "../../interface/table/Td"
import { ITr } from "../../interface/table/Tr"
@ -291,19 +293,76 @@ export class CommandAdapt {
public search(payload: string | null) {
if (payload) {
const elementList = this.draw.getElementList()
const text = elementList.map(e => !e.type || e.type === ElementType.TEXT ? e.value : ZERO)
.filter(Boolean)
.join('')
const matchStartIndexList = []
let index = text.indexOf(payload)
while (index !== -1) {
matchStartIndexList.push(index)
index = text.indexOf(payload, index + 1)
let searchMatchList: ISearchResult[] = []
// elementList按table分隔
const elementListGroup: { type: EditorContext, elementList: IElement[], index: number }[] = []
const originalElementList = this.draw.getOriginalElementList()
let lastTextElementList: IElement[] = []
for (let e = 0; e < originalElementList.length; e++) {
const element = originalElementList[e]
if (element.type === ElementType.TABLE) {
if (lastTextElementList.length) {
elementListGroup.push({
index: e,
type: EditorContext.PAGE,
elementList: lastTextElementList
})
lastTextElementList = []
}
elementListGroup.push({
index: e,
type: EditorContext.TABLE,
elementList: [element]
})
} else {
lastTextElementList.push(element)
}
}
// 搜索文本
function searchClosure(payload: string | null, type: EditorContext, elementList: IElement[], restArgs?: ISearchResultRestArgs) {
if (!payload) return
const text = elementList.map(e => !e.type || e.type === ElementType.TEXT ? e.value : ZERO)
.filter(Boolean)
.join('')
const matchStartIndexList = []
let index = text.indexOf(payload)
while (index !== -1) {
matchStartIndexList.push(index)
index = text.indexOf(payload, index + 1)
}
for (let m = 0; m < matchStartIndexList.length; m++) {
const startIndex = matchStartIndexList[m]
for (let i = 0; i < payload.length; i++) {
const index = startIndex + i
searchMatchList.push({
type,
index,
...restArgs
})
}
}
}
for (let e = 0; e < elementListGroup.length; e++) {
const group = elementListGroup[e]
if (group.type === EditorContext.TABLE) {
const tableElement = group.elementList[0]
for (let t = 0; t < tableElement.trList!.length; t++) {
const tr = tableElement.trList![t]
for (let d = 0; d < tr.tdList.length; d++) {
const td = tr.tdList[d]
const restArgs: ISearchResultRestArgs = {
tableIndex: group.index,
trIndex: t,
tdIndex: d
}
searchClosure(payload, group.type, td.value, restArgs)
}
}
} else {
searchClosure(payload, group.type, group.elementList)
}
}
const searchMatch: number[][] = matchStartIndexList
.map(i => Array(payload.length).fill(i).map((_, j) => i + j))
this.draw.setSearchMatch(searchMatch.length ? searchMatch : null)
this.draw.setSearchMatch(searchMatchList)
} else {
this.draw.setSearchMatch(null)
}

@ -24,6 +24,7 @@ import { TextParticle } from "./particle/TextParticle"
import { PageNumber } from "./frame/PageNumber"
import { GlobalObserver } from "../observer/GlobalObserver"
import { TableParticle } from "./particle/table/TableParticle"
import { ISearchResult } from "../../interface/Search"
export class Draw {
@ -53,7 +54,7 @@ export class Draw {
private rowList: IRow[]
private painterStyle: IElementStyle | null
private searchMatchList: number[][] | null
private searchMatchList: ISearchResult[] | null
private visiblePageNoList: number[]
private intersectionPageNo: number
@ -252,11 +253,11 @@ export class Draw {
}
}
public getSearchMatch(): number[][] | null {
public getSearchMatch(): ISearchResult[] | null {
return this.searchMatchList
}
public setSearchMatch(payload: number[][] | null) {
public setSearchMatch(payload: ISearchResult[] | null) {
this.searchMatchList = payload
}

@ -1,4 +1,6 @@
import { EditorContext } from "../../../dataset/enum/Editor"
import { IEditorOption } from "../../../interface/Editor"
import { IElementPosition } from "../../../interface/Element"
import { Position } from "../../position/Position"
import { Draw } from "../Draw"
@ -15,24 +17,32 @@ export class Search {
}
public render(ctx: CanvasRenderingContext2D, pageIndex: number) {
const searchMatch = this.draw.getSearchMatch()
if (!searchMatch || !searchMatch.length) return
const searchMatchList = searchMatch.flat()
const searchMatchList = this.draw.getSearchMatch()
if (!searchMatchList || !searchMatchList.length) return
const { searchMatchAlpha, searchMatchColor } = this.options
const positionList = this.position.getOriginalPositionList()
const elementList = this.draw.getOriginalElementList()
ctx.save()
ctx.globalAlpha = this.options.searchMatchAlpha
ctx.fillStyle = this.options.searchMatchColor
searchMatchList.forEach(s => {
const position = positionList[s]
if (!position) return
ctx.globalAlpha = searchMatchAlpha
ctx.fillStyle = searchMatchColor
for (let s = 0; s < searchMatchList.length; s++) {
const searchMatch = searchMatchList[s]
let position: IElementPosition | null = null
if (searchMatch.type === EditorContext.TABLE) {
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) return
if (pageNo !== pageIndex) continue
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()
}

@ -3,3 +3,8 @@ export enum EditorComponent {
MAIN = 'main',
FOOTER = 'footer'
}
export enum EditorContext {
PAGE = 'page',
TABLE = 'table'
}

@ -0,0 +1,14 @@
import { EditorContext } from "../dataset/enum/Editor"
export interface ISearchResultBasic {
type: EditorContext;
index: number;
}
export interface ISearchResultRestArgs {
tableIndex?: number;
trIndex?: number;
tdIndex?: number;
}
export type ISearchResult = ISearchResultBasic & ISearchResultRestArgs
Loading…
Cancel
Save