From 87a8dbea1596bcdee28edbb58b02fbe2a36e6c58 Mon Sep 17 00:00:00 2001 From: Hufe921 Date: Thu, 1 Aug 2024 20:10:34 +0800 Subject: [PATCH] feat: add title disabled property #680 --- docs/en/guide/schema.md | 1 + docs/guide/schema.md | 1 + src/editor/core/command/CommandAdapt.ts | 45 ++++++++--------------- src/editor/core/draw/Draw.ts | 17 +++++++++ src/editor/core/draw/control/Control.ts | 11 +++++- src/editor/core/event/CanvasEvent.ts | 2 + src/editor/core/event/handlers/input.ts | 44 +++++++++++----------- src/editor/core/event/handlers/mouseup.ts | 5 ++- src/editor/core/event/handlers/paste.ts | 15 +++----- src/editor/interface/Title.ts | 1 + src/editor/utils/element.ts | 14 +++++-- 11 files changed, 89 insertions(+), 67 deletions(-) diff --git a/docs/en/guide/schema.md b/docs/en/guide/schema.md index e9fe133..3d65c3f 100644 --- a/docs/en/guide/schema.md +++ b/docs/en/guide/schema.md @@ -157,6 +157,7 @@ interface IElement { title?: { conceptId?: string; deletable?: boolean; + disabled?: boolean; }; // list listType?: ListType; diff --git a/docs/guide/schema.md b/docs/guide/schema.md index 11c5c55..64f04f8 100644 --- a/docs/guide/schema.md +++ b/docs/guide/schema.md @@ -157,6 +157,7 @@ interface IElement { title?: { conceptId?: string; deletable?: boolean; + disabled?: boolean; }; // 列表 listType?: ListType; diff --git a/src/editor/core/command/CommandAdapt.ts b/src/editor/core/command/CommandAdapt.ts index 799ec0e..a25c823 100644 --- a/src/editor/core/command/CommandAdapt.ts +++ b/src/editor/core/command/CommandAdapt.ts @@ -300,15 +300,13 @@ export class CommandAdapt { } public applyPainterStyle() { - const isDisabled = - this.draw.isReadonly() || this.control.getIsDisabledControl() + const isDisabled = this.draw.isReadonly() || this.draw.isDisabled() if (isDisabled) return this.canvasEvent.applyPainterStyle() } public format() { - const isDisabled = - this.draw.isReadonly() || this.control.getIsDisabledControl() + const isDisabled = this.draw.isReadonly() || this.draw.isDisabled() if (isDisabled) return const selection = this.range.getSelectionElementList() // 选区设置或设置换行处样式 @@ -336,8 +334,7 @@ export class CommandAdapt { } public font(payload: string) { - const isDisabled = - this.draw.isReadonly() || this.control.getIsDisabledControl() + const isDisabled = this.draw.isReadonly() || this.draw.isDisabled() if (isDisabled) return const selection = this.range.getSelectionElementList() if (selection?.length) { @@ -359,8 +356,7 @@ export class CommandAdapt { public size(payload: number) { const { minSize, maxSize, defaultSize } = this.options if (payload < minSize || payload > maxSize) return - const isDisabled = - this.draw.isReadonly() || this.control.getIsDisabledControl() + const isDisabled = this.draw.isReadonly() || this.draw.isDisabled() if (isDisabled) return // 选区设置或设置换行处样式 let renderOption: IDrawOption = {} @@ -396,8 +392,7 @@ export class CommandAdapt { } public sizeAdd() { - const isDisabled = - this.draw.isReadonly() || this.control.getIsDisabledControl() + const isDisabled = this.draw.isReadonly() || this.draw.isDisabled() if (isDisabled) return const selection = this.range.getTextLikeSelectionElementList() // 选区设置或设置换行处样式 @@ -436,8 +431,7 @@ export class CommandAdapt { } public sizeMinus() { - const isDisabled = - this.draw.isReadonly() || this.control.getIsDisabledControl() + const isDisabled = this.draw.isReadonly() || this.draw.isDisabled() if (isDisabled) return const selection = this.range.getTextLikeSelectionElementList() // 选区设置或设置换行处样式 @@ -476,8 +470,7 @@ export class CommandAdapt { } public bold() { - const isDisabled = - this.draw.isReadonly() || this.control.getIsDisabledControl() + const isDisabled = this.draw.isReadonly() || this.draw.isDisabled() if (isDisabled) return const selection = this.range.getSelectionElementList() if (selection?.length) { @@ -498,8 +491,7 @@ export class CommandAdapt { } public italic() { - const isDisabled = - this.draw.isReadonly() || this.control.getIsDisabledControl() + const isDisabled = this.draw.isReadonly() || this.draw.isDisabled() if (isDisabled) return const selection = this.range.getSelectionElementList() if (selection?.length) { @@ -520,8 +512,7 @@ export class CommandAdapt { } public underline(textDecoration?: ITextDecoration) { - const isDisabled = - this.draw.isReadonly() || this.control.getIsDisabledControl() + const isDisabled = this.draw.isReadonly() || this.draw.isDisabled() if (isDisabled) return const selection = this.range.getSelectionElementList() if (selection?.length) { @@ -559,8 +550,7 @@ export class CommandAdapt { } public strikeout() { - const isDisabled = - this.draw.isReadonly() || this.control.getIsDisabledControl() + const isDisabled = this.draw.isReadonly() || this.draw.isDisabled() if (isDisabled) return const selection = this.range.getSelectionElementList() if (selection?.length) { @@ -584,8 +574,7 @@ export class CommandAdapt { } public superscript() { - const isDisabled = - this.draw.isReadonly() || this.control.getIsDisabledControl() + const isDisabled = this.draw.isReadonly() || this.draw.isDisabled() if (isDisabled) return const selection = this.range.getSelectionElementList() if (!selection) return @@ -614,8 +603,7 @@ export class CommandAdapt { } public subscript() { - const isDisabled = - this.draw.isReadonly() || this.control.getIsDisabledControl() + const isDisabled = this.draw.isReadonly() || this.draw.isDisabled() if (isDisabled) return const selection = this.range.getSelectionElementList() if (!selection) return @@ -644,8 +632,7 @@ export class CommandAdapt { } public color(payload: string | null) { - const isDisabled = - this.draw.isReadonly() || this.control.getIsDisabledControl() + const isDisabled = this.draw.isReadonly() || this.draw.isDisabled() if (isDisabled) return const selection = this.range.getSelectionElementList() if (selection?.length) { @@ -676,8 +663,7 @@ export class CommandAdapt { } public highlight(payload: string | null) { - const isDisabled = - this.draw.isReadonly() || this.control.getIsDisabledControl() + const isDisabled = this.draw.isReadonly() || this.draw.isDisabled() if (isDisabled) return const selection = this.range.getSelectionElementList() if (selection?.length) { @@ -1802,8 +1788,7 @@ export class CommandAdapt { } public image(payload: IDrawImagePayload) { - const isDisabled = - this.draw.isReadonly() || this.control.getIsDisabledControl() + const isDisabled = this.draw.isReadonly() || this.draw.isDisabled() if (isDisabled) return const { startIndex, endIndex } = this.range.getRange() if (!~startIndex && !~endIndex) return diff --git a/src/editor/core/draw/Draw.ts b/src/editor/core/draw/Draw.ts index f5d5dfd..5c1d311 100644 --- a/src/editor/core/draw/Draw.ts +++ b/src/editor/core/draw/Draw.ts @@ -317,6 +317,23 @@ export class Draw { } } + public isDisabled() { + const { startIndex, endIndex } = this.range.getRange() + const elementList = this.getElementList() + if (startIndex === endIndex) { + const startElement = elementList[startIndex] + const nextElement = elementList[startIndex + 1] + return !!( + (startElement?.title?.disabled && nextElement?.title?.disabled) || + (startElement?.control?.disabled && nextElement?.control?.disabled) + ) + } + const selectionElementList = elementList.slice(startIndex + 1, endIndex + 1) + return selectionElementList.some( + element => element.title?.disabled || element.control?.disabled + ) + } + public getOriginalWidth(): number { const { paperDirection, width, height } = this.options return paperDirection === PaperDirection.VERTICAL ? width : height diff --git a/src/editor/core/draw/control/Control.ts b/src/editor/core/draw/control/Control.ts index 1efcc76..4420246 100644 --- a/src/editor/core/draw/control/Control.ts +++ b/src/editor/core/draw/control/Control.ts @@ -208,7 +208,16 @@ export class Control { } public getIsDisabledControl(): boolean { - return !!this.activeControl?.getElement().control?.disabled + if (!this.activeControl) return false + const { startIndex, endIndex } = this.range.getRange() + if (startIndex === endIndex) { + const elementList = this.getElementList() + const startElement = elementList[startIndex] + if (startElement.controlComponent === ControlComponent.POSTFIX) { + return false + } + } + return !!this.activeControl.getElement()?.control?.disabled } public getContainer(): HTMLDivElement { diff --git a/src/editor/core/event/CanvasEvent.ts b/src/editor/core/event/CanvasEvent.ts index d20598d..0dafcda 100644 --- a/src/editor/core/event/CanvasEvent.ts +++ b/src/editor/core/event/CanvasEvent.ts @@ -106,6 +106,8 @@ export class CanvasEvent { public applyPainterStyle() { const painterStyle = this.draw.getPainterStyle() if (!painterStyle) return + const isDisabled = this.draw.isReadonly() || this.draw.isDisabled() + if (isDisabled) return const selection = this.range.getSelection() if (!selection) return const painterStyleKeys = Object.keys(painterStyle) diff --git a/src/editor/core/event/handlers/input.ts b/src/editor/core/event/handlers/input.ts index c2abcdf..215d208 100644 --- a/src/editor/core/event/handlers/input.ts +++ b/src/editor/core/event/handlers/input.ts @@ -8,7 +8,7 @@ import { CanvasEvent } from '../CanvasEvent' export function input(data: string, host: CanvasEvent) { const draw = host.getDraw() - if (draw.isReadonly()) return + if (draw.isReadonly() || draw.isDisabled()) return const position = draw.getPosition() const cursorPosition = position.getCursorPosition() if (!data || !cursorPosition) return @@ -34,26 +34,28 @@ export function input(data: string, host: CanvasEvent) { const newElement: IElement = { value } - const nextElement = elementList[endIndex + 1] - if ( - !copyElement.type || - copyElement.type === TEXT || - (copyElement.type === HYPERLINK && nextElement?.type === HYPERLINK) || - (copyElement.type === DATE && nextElement?.type === DATE) || - (copyElement.type === SUBSCRIPT && nextElement?.type === SUBSCRIPT) || - (copyElement.type === SUPERSCRIPT && nextElement?.type === SUPERSCRIPT) - ) { - EDITOR_ELEMENT_COPY_ATTR.forEach(attr => { - // 在分组外无需复制分组信息 - if (attr === 'groupIds' && !nextElement?.groupIds) return - const value = copyElement[attr] as never - if (value !== undefined) { - newElement[attr] = value - } - }) - } - if (isComposing) { - newElement.underline = true + if (!copyElement.title?.disabled && !copyElement.control?.disabled) { + const nextElement = elementList[endIndex + 1] + if ( + !copyElement.type || + copyElement.type === TEXT || + (copyElement.type === HYPERLINK && nextElement?.type === HYPERLINK) || + (copyElement.type === DATE && nextElement?.type === DATE) || + (copyElement.type === SUBSCRIPT && nextElement?.type === SUBSCRIPT) || + (copyElement.type === SUPERSCRIPT && nextElement?.type === SUPERSCRIPT) + ) { + EDITOR_ELEMENT_COPY_ATTR.forEach(attr => { + // 在分组外无需复制分组信息 + if (attr === 'groupIds' && !nextElement?.groupIds) return + const value = copyElement[attr] as never + if (value !== undefined) { + newElement[attr] = value + } + }) + } + if (isComposing) { + newElement.underline = true + } } return newElement }) diff --git a/src/editor/core/event/handlers/mouseup.ts b/src/editor/core/event/handlers/mouseup.ts index 9b30448..23aac0d 100644 --- a/src/editor/core/event/handlers/mouseup.ts +++ b/src/editor/core/event/handlers/mouseup.ts @@ -48,7 +48,10 @@ export function mouseup(evt: MouseEvent, host: CanvasEvent) { // 判断是否允许拖放 if (host.isAllowDrop) { const draw = host.getDraw() - if (draw.isReadonly()) return + if (draw.isReadonly() || draw.isDisabled()) { + host.mousedown(evt) + return + } const position = draw.getPosition() const positionList = position.getPositionList() const positionContext = position.getPositionContext() diff --git a/src/editor/core/event/handlers/paste.ts b/src/editor/core/event/handlers/paste.ts index 0480eb1..6a26e67 100644 --- a/src/editor/core/event/handlers/paste.ts +++ b/src/editor/core/event/handlers/paste.ts @@ -17,8 +17,7 @@ import { IOverrideResult } from '../../override/Override' export function pasteElement(host: CanvasEvent, elementList: IElement[]) { const draw = host.getDraw() - const isReadonly = draw.isReadonly() - if (isReadonly) return + if (draw.isReadonly() || draw.isDisabled()) return const rangeManager = draw.getRange() const { startIndex } = rangeManager.getRange() const originalElementList = draw.getElementList() @@ -59,8 +58,7 @@ export function pasteElement(host: CanvasEvent, elementList: IElement[]) { export function pasteHTML(host: CanvasEvent, htmlText: string) { const draw = host.getDraw() - const isReadonly = draw.isReadonly() - if (isReadonly) return + if (draw.isReadonly() || draw.isDisabled()) return const elementList = getElementListByHTML(htmlText, { innerWidth: draw.getOriginalInnerWidth() }) @@ -69,8 +67,7 @@ export function pasteHTML(host: CanvasEvent, htmlText: string) { export function pasteImage(host: CanvasEvent, file: File | Blob) { const draw = host.getDraw() - const isReadonly = draw.isReadonly() - if (isReadonly) return + if (draw.isReadonly() || draw.isDisabled()) return const rangeManager = draw.getRange() const { startIndex } = rangeManager.getRange() const elementList = draw.getElementList() @@ -99,8 +96,7 @@ export function pasteImage(host: CanvasEvent, file: File | Blob) { export function pasteByEvent(host: CanvasEvent, evt: ClipboardEvent) { const draw = host.getDraw() - const isReadonly = draw.isReadonly() - if (isReadonly) return + if (draw.isReadonly() || draw.isDisabled()) return const clipboardData = evt.clipboardData if (!clipboardData) return // 自定义粘贴事件 @@ -157,8 +153,7 @@ export function pasteByEvent(host: CanvasEvent, evt: ClipboardEvent) { export async function pasteByApi(host: CanvasEvent, options?: IPasteOption) { const draw = host.getDraw() - const isReadonly = draw.isReadonly() - if (isReadonly) return + if (draw.isReadonly() || draw.isDisabled()) return // 自定义粘贴事件 const { paste } = draw.getOverride() if (paste) { diff --git a/src/editor/interface/Title.ts b/src/editor/interface/Title.ts index 1e97ac2..066aa6b 100644 --- a/src/editor/interface/Title.ts +++ b/src/editor/interface/Title.ts @@ -14,6 +14,7 @@ export type ITitleOption = ITitleSizeOption & {} export interface ITitleRule { deletable?: boolean + disabled?: boolean } export type ITitle = ITitleRule & { diff --git a/src/editor/utils/element.ts b/src/editor/utils/element.ts index f271367..fd30ba4 100644 --- a/src/editor/utils/element.ts +++ b/src/editor/utils/element.ts @@ -4,6 +4,7 @@ import { deepCloneOmitKeys, getUUID, isArrayEqual, + omitObject, pickObject, splitText } from '.' @@ -29,7 +30,8 @@ import { INLINE_NODE_NAME, TABLE_CONTEXT_ATTR, TABLE_TD_ZIP_ATTR, - TEXTLIKE_ELEMENT_TYPE + TEXTLIKE_ELEMENT_TYPE, + TITLE_CONTEXT_ATTR } from '../dataset/constant/Element' import { listStyleCSSMapping, @@ -818,8 +820,12 @@ export function formatElementContext( anchorIndex: number, options?: IFormatElementContextOption ) { - const copyElement = getAnchorElement(sourceElementList, anchorIndex) + let copyElement = getAnchorElement(sourceElementList, anchorIndex) if (!copyElement) return + // 标题元素禁用时不复制标题属性 + if (copyElement.title?.disabled) { + copyElement = omitObject(copyElement, TITLE_CONTEXT_ATTR) + } const { isBreakWhenWrap = false } = options || {} // 是否已经换行 let isBreakWarped = false @@ -839,9 +845,9 @@ export function formatElementContext( (!copyElement.listId && targetElement.type === ElementType.LIST) ) { const cloneAttr = [...TABLE_CONTEXT_ATTR, ...EDITOR_ROW_ATTR] - cloneProperty(cloneAttr, copyElement, targetElement) + cloneProperty(cloneAttr, copyElement!, targetElement) targetElement.valueList?.forEach(valueItem => { - cloneProperty(cloneAttr, copyElement, valueItem) + cloneProperty(cloneAttr, copyElement!, valueItem) }) continue }