From 8f36d1fb4f161bd125d0c8a8ac72590df2d2aefe Mon Sep 17 00:00:00 2001 From: Hufe921 Date: Tue, 21 May 2024 22:15:01 +0800 Subject: [PATCH] fix: control setting row flex data error #586 --- src/editor/dataset/constant/Element.ts | 1 - src/editor/utils/element.ts | 100 ++++++++++++++++++++----- 2 files changed, 82 insertions(+), 19 deletions(-) diff --git a/src/editor/dataset/constant/Element.ts b/src/editor/dataset/constant/Element.ts index fa020a6..c3f781c 100644 --- a/src/editor/dataset/constant/Element.ts +++ b/src/editor/dataset/constant/Element.ts @@ -33,7 +33,6 @@ export const EDITOR_ELEMENT_COPY_ATTR: Array = [ 'dateId', 'dateFormat', 'groupIds', - 'rowFlex', 'rowMargin', 'textDecoration' ] diff --git a/src/editor/utils/element.ts b/src/editor/utils/element.ts index e17bf64..49c97ac 100644 --- a/src/editor/utils/element.ts +++ b/src/editor/utils/element.ts @@ -24,6 +24,7 @@ import { CONTROL_STYLE_ATTR, EDITOR_ELEMENT_CONTEXT_ATTR, EDITOR_ELEMENT_ZIP_ATTR, + EDITOR_ROW_ATTR, INLINE_ELEMENT_TYPE, INLINE_NODE_NAME, TABLE_CONTEXT_ATTR, @@ -233,7 +234,10 @@ export function formatElementList( // 移除父节点 elementList.splice(i, 1) // 控件上下文提取(压缩后的控件上下文无法提取) - const controlContext = pickObject(el, EDITOR_ELEMENT_CONTEXT_ATTR) + const controlContext = pickObject(el, [ + ...EDITOR_ELEMENT_CONTEXT_ATTR, + ...EDITOR_ROW_ATTR + ]) // 控件设置的默认样式(以前缀为基准) const controlDefaultStyle = pickObject( (el.control), @@ -671,6 +675,7 @@ export function zipElementList(payload: IElement[]): IElement[] { ...controlDefaultStyle } const controlElement: IElement = { + ...pickObject(element, EDITOR_ROW_ATTR), type: ElementType.CONTROL, value: '', control @@ -723,7 +728,7 @@ export function zipElementList(payload: IElement[]): IElement[] { return zipElementListData } -export function getElementRowFlex(node: HTMLElement) { +export function convertTextAlignToRowFlex(node: HTMLElement) { const textAlign = window.getComputedStyle(node).textAlign switch (textAlign) { case 'left': @@ -743,6 +748,10 @@ export function getElementRowFlex(node: HTMLElement) { } } +export function convertRowFlexToTextAlign(rowFlex: RowFlex) { + return rowFlex === RowFlex.ALIGNMENT ? 'justify' : rowFlex +} + export function isTextLikeElement(element: IElement): boolean { return !element.type || TEXTLIKE_ELEMENT_TYPE.includes(element.type) } @@ -823,17 +832,11 @@ export function convertElementToDom( tagName = 'sup' } else if (element.type === ElementType.SUBSCRIPT) { tagName = 'sub' - } else if ( - element.rowFlex === RowFlex.CENTER || - element.rowFlex === RowFlex.RIGHT - ) { - tagName = 'p' } const dom = document.createElement(tagName) dom.style.fontFamily = element.font || options.defaultFont if (element.rowFlex) { - const isAlignment = element.rowFlex === RowFlex.ALIGNMENT - dom.style.textAlign = isAlignment ? 'justify' : element.rowFlex + dom.style.textAlign = convertRowFlexToTextAlign(element.rowFlex) } if (element.color) { dom.style.color = element.color @@ -893,6 +896,45 @@ export function splitListElement( return listElementListMap } +export interface IElementListGroupRowFlex { + rowFlex: RowFlex | null + data: IElement[] +} + +export function groupElementListByRowFlex( + elementList: IElement[] +): IElementListGroupRowFlex[] { + const elementListGroupList: IElementListGroupRowFlex[] = [] + if (!elementList.length) return elementListGroupList + let currentRowFlex: RowFlex | null = elementList[0]?.rowFlex || null + elementListGroupList.push({ + rowFlex: currentRowFlex, + data: [elementList[0]] + }) + for (let e = 1; e < elementList.length; e++) { + const element = elementList[e] + const rowFlex = element.rowFlex || null + // 行布局相同时追加数据,否则新增分组 + if (currentRowFlex === rowFlex) { + const lastElementListGroup = + elementListGroupList[elementListGroupList.length - 1] + lastElementListGroup.data.push(element) + } else { + elementListGroupList.push({ + rowFlex, + data: [element] + }) + currentRowFlex = rowFlex + } + } + // 压缩数据 + for (let g = 0; g < elementListGroupList.length; g++) { + const elementListGroup = elementListGroupList[g] + elementListGroup.data = zipElementList(elementListGroup.data) + } + return elementListGroupList +} + export function createDomFromElementList( elementList: IElement[], options: DeepRequired @@ -953,7 +995,7 @@ export function createDomFromElementList( if (td.borderTypes?.includes(TdBorder.LEFT)) { tdDom.style.borderLeft = borderStyle } - const childDom = buildDom(zipElementList(td.value!)) + const childDom = createDomFromElementList(td.value!, options) tdDom.innerHTML = childDom.innerHTML if (td.backgroundColor) { tdDom.style.backgroundColor = td.backgroundColor @@ -974,7 +1016,7 @@ export function createDomFromElementList( const h = document.createElement( `h${titleOrderNumberMapping[element.level!]}` ) - const childDom = buildDom(zipElementList(element.valueList!)) + const childDom = buildDom(element.valueList!) h.innerHTML = childDom.innerHTML clipboardDom.append(h) } else if (element.type === ElementType.LIST) { @@ -1025,7 +1067,7 @@ export function createDomFromElementList( clipboardDom.append(tab) } else if (element.type === ElementType.CONTROL) { const controlElement = document.createElement('span') - const childDom = buildDom(zipElementList(element.control?.value || [])) + const childDom = buildDom(element.control?.value || []) controlElement.innerHTML = childDom.innerHTML clipboardDom.append(controlElement) } else if ( @@ -1045,17 +1087,39 @@ export function createDomFromElementList( if (payload[e - 1]?.type === ElementType.TITLE) { text = text.replace(/^\n/, '') } - // 块元素移除尾部换行符 - if (dom.tagName === 'P') { - text = text.replace(/\n$/, '') - } dom.innerText = text.replace(new RegExp(`${ZERO}`, 'g'), '\n') clipboardDom.append(dom) } } return clipboardDom } - return buildDom(zipElementList(elementList)) + // 按行布局分类创建dom + const clipboardDom = document.createElement('div') + const groupElementList = groupElementListByRowFlex(elementList) + for (let g = 0; g < groupElementList.length; g++) { + const elementGroupRowFlex = groupElementList[g] + // 行布局样式设置 + const rowFlexDom = document.createElement('div') + const isDefaultRowFlex = + !elementGroupRowFlex.rowFlex || + elementGroupRowFlex.rowFlex === RowFlex.LEFT + if (!isDefaultRowFlex) { + rowFlexDom.style.textAlign = convertRowFlexToTextAlign( + elementGroupRowFlex.rowFlex! + ) + } + // 布局内容 + rowFlexDom.innerHTML = buildDom(elementGroupRowFlex.data).innerHTML + // 未设置行布局时无需行布局容器 + if (!isDefaultRowFlex) { + clipboardDom.append(rowFlexDom) + } else { + rowFlexDom.childNodes.forEach(child => { + clipboardDom.append(child.cloneNode(true)) + }) + } + } + return clipboardDom } export function convertTextNodeToElement( @@ -1067,7 +1131,7 @@ export function convertTextNodeToElement( parentNode.nodeName === 'FONT' ? parentNode.parentNode : parentNode - const rowFlex = getElementRowFlex(anchorNode) + const rowFlex = convertTextAlignToRowFlex(anchorNode) const value = textNode.textContent const style = window.getComputedStyle(anchorNode) if (!value || anchorNode.nodeName === 'STYLE') return null