From 53701fc46c347595722801e8bca40647cda74bcb Mon Sep 17 00:00:00 2001 From: Hufe921 Date: Wed, 5 Jun 2024 21:20:24 +0800 Subject: [PATCH] feat: add executeLocationControl api #592 --- docs/en/guide/command-execute.md | 10 ++++ docs/guide/command-execute.md | 10 ++++ src/editor/core/command/Command.ts | 2 + src/editor/core/command/CommandAdapt.ts | 80 +++++++++++++++++++++++++ src/editor/core/draw/control/Control.ts | 4 +- src/editor/interface/Position.ts | 8 ++- src/editor/utils/element.ts | 49 ++++++++++----- 7 files changed, 147 insertions(+), 16 deletions(-) diff --git a/docs/en/guide/command-execute.md b/docs/en/guide/command-execute.md index ddbae32..c4616fb 100644 --- a/docs/en/guide/command-execute.md +++ b/docs/en/guide/command-execute.md @@ -912,6 +912,16 @@ Usage: instance.command.executeSetControlHighlight(payload: ISetControlHighlightOption) ``` +## executeLocationControl + +Feature: Positioning and activating control + +Usage: + +```javascript +instance.command.executeLocationControl(controlId: string) +``` + ## executeUpdateOptions Feature: Update options diff --git a/docs/guide/command-execute.md b/docs/guide/command-execute.md index 896ea56..b91d5b1 100644 --- a/docs/guide/command-execute.md +++ b/docs/guide/command-execute.md @@ -912,6 +912,16 @@ instance.command.executeSetControlProperties(payload: ISetControlProperties) instance.command.executeSetControlHighlight(payload: ISetControlHighlightOption) ``` +## executeLocationControl + +功能:定位并激活控件 + +用法: + +```javascript +instance.command.executeLocationControl(controlId: string) +``` + ## executeUpdateOptions 功能:修改配置 diff --git a/src/editor/core/command/Command.ts b/src/editor/core/command/Command.ts index 6d704f5..9a0a55c 100644 --- a/src/editor/core/command/Command.ts +++ b/src/editor/core/command/Command.ts @@ -90,6 +90,7 @@ export class Command { public executeSetControlExtension: CommandAdapt['setControlExtension'] public executeSetControlProperties: CommandAdapt['setControlProperties'] public executeSetControlHighlight: CommandAdapt['setControlHighlight'] + public executeLocationControl: CommandAdapt['locationControl'] public executeUpdateOptions: CommandAdapt['updateOptions'] public executeInsertTitle: CommandAdapt['insertTitle'] public getCatalog: CommandAdapt['getCatalog'] @@ -236,5 +237,6 @@ export class Command { this.executeSetControlHighlight = adapt.setControlHighlight.bind(adapt) this.getControlValue = adapt.getControlValue.bind(adapt) this.getControlList = adapt.getControlList.bind(adapt) + this.executeLocationControl = adapt.locationControl.bind(adapt) } } diff --git a/src/editor/core/command/CommandAdapt.ts b/src/editor/core/command/CommandAdapt.ts index 64fe8ca..9d0b452 100644 --- a/src/editor/core/command/CommandAdapt.ts +++ b/src/editor/core/command/CommandAdapt.ts @@ -56,6 +56,7 @@ import { import { IElement, IElementStyle } from '../../interface/Element' import { IPasteOption } from '../../interface/Event' import { IMargin } from '../../interface/Margin' +import { ILocationPosition } from '../../interface/Position' import { IRange, RangeContext, RangeRect } from '../../interface/Range' import { IColgroup } from '../../interface/table/Colgroup' import { ITd } from '../../interface/table/Td' @@ -2446,6 +2447,85 @@ export class CommandAdapt { return this.draw.getControl().getList() } + public locationControl(controlId: string) { + function location( + elementList: IElement[], + zone: EditorZone + ): ILocationPosition | null { + 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 locationContext = location(td.value, zone) + if (locationContext) { + return { + ...locationContext, + positionContext: { + isTable: true, + index: i - 1, + trIndex: r, + tdIndex: d, + tdId: element.tdId, + trId: element.trId, + tableId: element.tableId + } + } + } + } + } + } + if (element?.controlId !== controlId) continue + const curIndex = i - 1 + return { + zone, + range: { + startIndex: curIndex, + endIndex: curIndex + }, + positionContext: { + isTable: false + } + } + } + return null + } + const data = [ + { + zone: EditorZone.HEADER, + elementList: this.draw.getHeaderElementList() + }, + { + zone: EditorZone.MAIN, + elementList: this.draw.getOriginalMainElementList() + }, + { + zone: EditorZone.FOOTER, + elementList: this.draw.getFooterElementList() + } + ] + for (const context of data) { + const locationContext = location(context.elementList, context.zone) + if (locationContext) { + // 设置区域、上下文、光标信息 + this.setZone(locationContext.zone) + this.position.setPositionContext(locationContext.positionContext) + this.range.replaceRange(locationContext.range) + this.draw.render({ + curIndex: locationContext.range.startIndex, + isCompute: false, + isSubmitHistory: false + }) + break + } + } + } + public getContainer(): HTMLDivElement { return this.draw.getContainer() } diff --git a/src/editor/core/draw/control/Control.ts b/src/editor/core/draw/control/Control.ts index 47581c4..eddc6e6 100644 --- a/src/editor/core/draw/control/Control.ts +++ b/src/editor/core/draw/control/Control.ts @@ -849,7 +849,9 @@ export class Control { for (const elementList of data) { getControlElementList(elementList) } - return zipElementList(controlElementList) + return zipElementList(controlElementList, { + extraPickAttrs: ['controlId'] + }) } public recordBorderInfo(x: number, y: number, width: number, height: number) { diff --git a/src/editor/interface/Position.ts b/src/editor/interface/Position.ts index 8de3a3c..3374854 100644 --- a/src/editor/interface/Position.ts +++ b/src/editor/interface/Position.ts @@ -1,4 +1,4 @@ -import { IElement, ImageDisplay } from '..' +import { IElement, ImageDisplay, IRange } from '..' import { EditorZone } from '../dataset/enum/Editor' import { IElementPosition } from './Element' import { IRow } from './Row' @@ -93,3 +93,9 @@ export interface IFloatPosition { tdValueIndex?: number zone?: EditorZone } + +export interface ILocationPosition { + zone: EditorZone + range: IRange + positionContext: IPositionContext +} diff --git a/src/editor/utils/element.ts b/src/editor/utils/element.ts index 617be2a..189c253 100644 --- a/src/editor/utils/element.ts +++ b/src/editor/utils/element.ts @@ -487,12 +487,22 @@ export function isSameElementExceptValue( } return true } - -export function pickElementAttr(payload: IElement): IElement { +interface IPickElementOption { + extraPickAttrs?: Array +} +export function pickElementAttr( + payload: IElement, + option: IPickElementOption = {} +): IElement { + const { extraPickAttrs } = option + const zipAttrs = EDITOR_ELEMENT_ZIP_ATTR + if (extraPickAttrs) { + zipAttrs.push(...extraPickAttrs) + } const element: IElement = { value: payload.value === ZERO ? `\n` : payload.value } - EDITOR_ELEMENT_ZIP_ATTR.forEach(attr => { + zipAttrs.forEach(attr => { const value = payload[attr] as never if (value !== undefined) { element[attr] = value @@ -501,7 +511,14 @@ export function pickElementAttr(payload: IElement): IElement { return element } -export function zipElementList(payload: IElement[]): IElement[] { +interface IZipElementListOption { + extraPickAttrs?: Array +} +export function zipElementList( + payload: IElement[], + options: IZipElementListOption = {} +): IElement[] { + const { extraPickAttrs } = options const elementList = deepClone(payload) const zipElementListData: IElement[] = [] let e = 0 @@ -541,7 +558,7 @@ export function zipElementList(payload: IElement[]): IElement[] { valueList.push(titleE) e++ } - titleElement.valueList = zipElementList(valueList) + titleElement.valueList = zipElementList(valueList, options) element = titleElement } } else if (element.listId && element.listType) { @@ -569,7 +586,7 @@ export function zipElementList(payload: IElement[]): IElement[] { valueList.push(listE) e++ } - listElement.valueList = zipElementList(valueList) + listElement.valueList = zipElementList(valueList, options) element = listElement } } else if (element.type === ElementType.TABLE) { @@ -599,7 +616,7 @@ export function zipElementList(payload: IElement[]): IElement[] { const zipTd: ITd = { colspan: td.colspan, rowspan: td.rowspan, - value: zipElementList(td.value) + value: zipElementList(td.value, options) } // 压缩单元格属性 TABLE_TD_ZIP_ATTR.forEach(attr => { @@ -633,7 +650,7 @@ export function zipElementList(payload: IElement[]): IElement[] { valueList.push(hyperlinkE) e++ } - hyperlinkElement.valueList = zipElementList(valueList) + hyperlinkElement.valueList = zipElementList(valueList, options) element = hyperlinkElement } } else if (element.type === ElementType.DATE) { @@ -656,7 +673,7 @@ export function zipElementList(payload: IElement[]): IElement[] { valueList.push(dateE) e++ } - dateElement.valueList = zipElementList(valueList) + dateElement.valueList = zipElementList(valueList, options) element = dateElement } } else if (element.controlId) { @@ -675,7 +692,8 @@ export function zipElementList(payload: IElement[]): IElement[] { ...pickObject(element, EDITOR_ROW_ATTR), type: ElementType.CONTROL, value: '', - control + control, + controlId } const valueList: IElement[] = [] while (e < elementList.length) { @@ -691,12 +709,12 @@ export function zipElementList(payload: IElement[]): IElement[] { } e++ } - controlElement.control!.value = zipElementList(valueList) - element = controlElement + controlElement.control!.value = zipElementList(valueList, options) + element = pickElementAttr(controlElement, { extraPickAttrs }) } } // 组合元素 - const pickElement = pickElementAttr(element) + const pickElement = pickElementAttr(element, { extraPickAttrs }) if ( !element.type || element.type === ElementType.TEXT || @@ -708,7 +726,10 @@ export function zipElementList(payload: IElement[]): IElement[] { e++ if ( nextElement && - isSameElementExceptValue(pickElement, pickElementAttr(nextElement)) + isSameElementExceptValue( + pickElement, + pickElementAttr(nextElement, { extraPickAttrs }) + ) ) { const nextValue = nextElement.value === ZERO ? '\n' : nextElement.value