feat:search in table
This commit is contained in:
@@ -1,11 +1,13 @@
|
|||||||
import { ZERO } from "../../dataset/constant/Common"
|
import { ZERO } from "../../dataset/constant/Common"
|
||||||
import { EDITOR_ELEMENT_STYLE } from "../../dataset/constant/Element"
|
import { EDITOR_ELEMENT_STYLE } from "../../dataset/constant/Element"
|
||||||
|
import { EditorContext } from "../../dataset/enum/Editor"
|
||||||
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 { RowFlex } from "../../dataset/enum/Row"
|
import { RowFlex } from "../../dataset/enum/Row"
|
||||||
import { IDrawImagePayload } from "../../interface/Draw"
|
import { IDrawImagePayload } from "../../interface/Draw"
|
||||||
import { IEditorOption } from "../../interface/Editor"
|
import { IEditorOption } from "../../interface/Editor"
|
||||||
import { IElement, IElementStyle } from "../../interface/Element"
|
import { IElement, IElementStyle } from "../../interface/Element"
|
||||||
|
import { ISearchResult, ISearchResultRestArgs } from "../../interface/Search"
|
||||||
import { IColgroup } from "../../interface/table/Colgroup"
|
import { IColgroup } from "../../interface/table/Colgroup"
|
||||||
import { ITd } from "../../interface/table/Td"
|
import { ITd } from "../../interface/table/Td"
|
||||||
import { ITr } from "../../interface/table/Tr"
|
import { ITr } from "../../interface/table/Tr"
|
||||||
@@ -291,19 +293,76 @@ export class CommandAdapt {
|
|||||||
|
|
||||||
public search(payload: string | null) {
|
public search(payload: string | null) {
|
||||||
if (payload) {
|
if (payload) {
|
||||||
const elementList = this.draw.getElementList()
|
let searchMatchList: ISearchResult[] = []
|
||||||
const text = elementList.map(e => !e.type || e.type === ElementType.TEXT ? e.value : ZERO)
|
// elementList按table分隔
|
||||||
.filter(Boolean)
|
const elementListGroup: { type: EditorContext, elementList: IElement[], index: number }[] = []
|
||||||
.join('')
|
const originalElementList = this.draw.getOriginalElementList()
|
||||||
const matchStartIndexList = []
|
let lastTextElementList: IElement[] = []
|
||||||
let index = text.indexOf(payload)
|
for (let e = 0; e < originalElementList.length; e++) {
|
||||||
while (index !== -1) {
|
const element = originalElementList[e]
|
||||||
matchStartIndexList.push(index)
|
if (element.type === ElementType.TABLE) {
|
||||||
index = text.indexOf(payload, index + 1)
|
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)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
const searchMatch: number[][] = matchStartIndexList
|
// 搜索文本
|
||||||
.map(i => Array(payload.length).fill(i).map((_, j) => i + j))
|
function searchClosure(payload: string | null, type: EditorContext, elementList: IElement[], restArgs?: ISearchResultRestArgs) {
|
||||||
this.draw.setSearchMatch(searchMatch.length ? searchMatch : null)
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.draw.setSearchMatch(searchMatchList)
|
||||||
} else {
|
} else {
|
||||||
this.draw.setSearchMatch(null)
|
this.draw.setSearchMatch(null)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ import { TextParticle } from "./particle/TextParticle"
|
|||||||
import { PageNumber } from "./frame/PageNumber"
|
import { PageNumber } from "./frame/PageNumber"
|
||||||
import { GlobalObserver } from "../observer/GlobalObserver"
|
import { GlobalObserver } from "../observer/GlobalObserver"
|
||||||
import { TableParticle } from "./particle/table/TableParticle"
|
import { TableParticle } from "./particle/table/TableParticle"
|
||||||
|
import { ISearchResult } from "../../interface/Search"
|
||||||
|
|
||||||
export class Draw {
|
export class Draw {
|
||||||
|
|
||||||
@@ -53,7 +54,7 @@ export class Draw {
|
|||||||
|
|
||||||
private rowList: IRow[]
|
private rowList: IRow[]
|
||||||
private painterStyle: IElementStyle | null
|
private painterStyle: IElementStyle | null
|
||||||
private searchMatchList: number[][] | null
|
private searchMatchList: ISearchResult[] | null
|
||||||
private visiblePageNoList: number[]
|
private visiblePageNoList: number[]
|
||||||
private intersectionPageNo: number
|
private intersectionPageNo: number
|
||||||
|
|
||||||
@@ -252,11 +253,11 @@ export class Draw {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public getSearchMatch(): number[][] | null {
|
public getSearchMatch(): ISearchResult[] | null {
|
||||||
return this.searchMatchList
|
return this.searchMatchList
|
||||||
}
|
}
|
||||||
|
|
||||||
public setSearchMatch(payload: number[][] | null) {
|
public setSearchMatch(payload: ISearchResult[] | null) {
|
||||||
this.searchMatchList = payload
|
this.searchMatchList = payload
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
|
import { EditorContext } from "../../../dataset/enum/Editor"
|
||||||
import { IEditorOption } from "../../../interface/Editor"
|
import { IEditorOption } from "../../../interface/Editor"
|
||||||
|
import { IElementPosition } from "../../../interface/Element"
|
||||||
import { Position } from "../../position/Position"
|
import { Position } from "../../position/Position"
|
||||||
import { Draw } from "../Draw"
|
import { Draw } from "../Draw"
|
||||||
|
|
||||||
@@ -15,24 +17,32 @@ export class Search {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public render(ctx: CanvasRenderingContext2D, pageIndex: number) {
|
public render(ctx: CanvasRenderingContext2D, pageIndex: number) {
|
||||||
const searchMatch = this.draw.getSearchMatch()
|
const searchMatchList = this.draw.getSearchMatch()
|
||||||
if (!searchMatch || !searchMatch.length) return
|
if (!searchMatchList || !searchMatchList.length) return
|
||||||
const searchMatchList = searchMatch.flat()
|
const { searchMatchAlpha, searchMatchColor } = this.options
|
||||||
const positionList = this.position.getOriginalPositionList()
|
const positionList = this.position.getOriginalPositionList()
|
||||||
|
const elementList = this.draw.getOriginalElementList()
|
||||||
ctx.save()
|
ctx.save()
|
||||||
ctx.globalAlpha = this.options.searchMatchAlpha
|
ctx.globalAlpha = searchMatchAlpha
|
||||||
ctx.fillStyle = this.options.searchMatchColor
|
ctx.fillStyle = searchMatchColor
|
||||||
searchMatchList.forEach(s => {
|
for (let s = 0; s < searchMatchList.length; s++) {
|
||||||
const position = positionList[s]
|
const searchMatch = searchMatchList[s]
|
||||||
if (!position) return
|
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
|
const { coordinate: { leftTop, leftBottom, rightTop }, pageNo } = position
|
||||||
if (pageNo !== pageIndex) return
|
if (pageNo !== pageIndex) continue
|
||||||
const x = leftTop[0]
|
const x = leftTop[0]
|
||||||
const y = leftTop[1]
|
const y = leftTop[1]
|
||||||
const width = rightTop[0] - leftTop[0]
|
const width = rightTop[0] - leftTop[0]
|
||||||
const height = leftBottom[1] - leftTop[1]
|
const height = leftBottom[1] - leftTop[1]
|
||||||
ctx.fillRect(x, y, width, height)
|
ctx.fillRect(x, y, width, height)
|
||||||
})
|
}
|
||||||
ctx.restore()
|
ctx.restore()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,4 +2,9 @@ export enum EditorComponent {
|
|||||||
MENU = 'menu',
|
MENU = 'menu',
|
||||||
MAIN = 'main',
|
MAIN = 'main',
|
||||||
FOOTER = 'footer'
|
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
|
||||||
Reference in New Issue
Block a user