diff --git a/src/editor/core/draw/Draw.ts b/src/editor/core/draw/Draw.ts index 6b04f6a..4cf93b6 100644 --- a/src/editor/core/draw/Draw.ts +++ b/src/editor/core/draw/Draw.ts @@ -39,6 +39,7 @@ import { Control } from './control/Control' import { zipElementList } from '../../utils/element' import { CheckboxParticle } from './particle/CheckboxParticle' import { DeepRequired } from '../../interface/Common' +import { ControlComponent } from '../../dataset/enum/Control' export class Draw { @@ -567,7 +568,10 @@ export class Draw { element.width = innerWidth metrics.width = innerWidth metrics.height = this.options.defaultSize - } else if (element.type === ElementType.CHECKBOX) { + } else if ( + element.type === ElementType.CHECKBOX || + element.controlComponent === ControlComponent.CHECKBOX + ) { const { width, height, gap } = this.options.checkbox const elementWidth = (width + gap * 2) * scale element.width = elementWidth @@ -707,7 +711,10 @@ export class Draw { if (this.mode !== EditorMode.CLEAN) { this.pageBreakParticle.render(ctx, element, x, y) } - } else if (element.type === ElementType.CHECKBOX) { + } else if ( + element.type === ElementType.CHECKBOX || + element.controlComponent === ControlComponent.CHECKBOX + ) { this.textParticle.complete() this.checkboxParticle.render(ctx, element, x, y + offsetY) } else { diff --git a/src/editor/core/draw/control/Control.ts b/src/editor/core/draw/control/Control.ts index e71e951..8dd242c 100644 --- a/src/editor/core/draw/control/Control.ts +++ b/src/editor/core/draw/control/Control.ts @@ -7,6 +7,7 @@ import { pickElementAttr, zipElementList } from '../../../utils/element' import { Listener } from '../../listener/Listener' import { RangeManager } from '../../range/RangeManager' import { Draw } from '../Draw' +import { CheckboxControl } from './checkbox/CheckboxControl' import { SelectControl } from './select/SelectControl' import { TextControl } from './text/TextControl' @@ -103,6 +104,8 @@ export class Control { const selectControl = new SelectControl(element, this) this.activeControl = selectControl selectControl.awake() + } else if (control.type === ControlType.CHECKBOX) { + this.activeControl = new CheckboxControl(element, this) } // 激活控件回调 setTimeout(() => { diff --git a/src/editor/core/draw/control/checkbox/CheckboxControl.ts b/src/editor/core/draw/control/checkbox/CheckboxControl.ts new file mode 100644 index 0000000..d520ab9 --- /dev/null +++ b/src/editor/core/draw/control/checkbox/CheckboxControl.ts @@ -0,0 +1,85 @@ +import { ControlComponent } from '../../../../dataset/enum/Control' +import { KeyMap } from '../../../../dataset/enum/Keymap' +import { IControlInstance } from '../../../../interface/Control' +import { IElement } from '../../../../interface/Element' +import { Control } from '../Control' + +export class CheckboxControl implements IControlInstance { + + private element: IElement + private control: Control + + constructor(element: IElement, control: Control) { + this.element = element + this.control = control + } + + public getElement(): IElement { + return this.element + } + + public getCode(): string | null { + return this.element.control?.code || null + } + + public getValue(): IElement[] { + const elementList = this.control.getElementList() + const { startIndex } = this.control.getRange() + const startElement = elementList[startIndex] + const data: IElement[] = [] + // 向左查找 + let preIndex = startIndex + while (preIndex > 0) { + const preElement = elementList[preIndex] + if ( + preElement.controlId !== startElement.controlId || + preElement.controlComponent === ControlComponent.PREFIX + ) { + break + } + if (preElement.controlComponent === ControlComponent.VALUE) { + data.unshift(preElement) + } + preIndex-- + } + // 向右查找 + let nextIndex = startIndex + 1 + while (nextIndex < elementList.length) { + const nextElement = elementList[nextIndex] + if ( + nextElement.controlId !== startElement.controlId || + nextElement.controlComponent === ControlComponent.POSTFIX + ) { + break + } + if (nextElement.controlComponent === ControlComponent.VALUE) { + data.push(nextElement) + } + nextIndex++ + } + return data + } + + public setValue(): number { + const { endIndex } = this.control.getRange() + return endIndex + } + + public keydown(evt: KeyboardEvent): number { + const range = this.control.getRange() + // 收缩边界到Value内 + this.control.shrinkBoundary() + const { startIndex, endIndex } = range + // 删除 + if (evt.key === KeyMap.Backspace || evt.key === KeyMap.Delete) { + return this.control.removeControl(startIndex) + } + return endIndex + } + + public cut(): number { + const { endIndex } = this.control.getRange() + return endIndex + } + +} \ No newline at end of file diff --git a/src/editor/core/event/CanvasEvent.ts b/src/editor/core/event/CanvasEvent.ts index 13b672d..c03102c 100644 --- a/src/editor/core/event/CanvasEvent.ts +++ b/src/editor/core/event/CanvasEvent.ts @@ -202,6 +202,7 @@ export class CanvasEvent { // 设置位置上下文 this.position.setPositionContext({ isTable: isTable || false, + isCheckbox: isCheckbox || false, isControl: isControl || false, index, trIndex, diff --git a/src/editor/core/position/Position.ts b/src/editor/core/position/Position.ts index 8fd02b5..be0c423 100644 --- a/src/editor/core/position/Position.ts +++ b/src/editor/core/position/Position.ts @@ -1,5 +1,6 @@ import { ElementType } from '../..' import { ZERO } from '../../dataset/constant/Common' +import { ControlComponent } from '../../dataset/enum/Control' import { IEditorOption } from '../../interface/Editor' import { IElementPosition } from '../../interface/Element' import { ICurrentPosition, IGetPositionByXYPayload, IPositionContext } from '../../interface/Position' @@ -97,7 +98,8 @@ export class Position { const tdValueElement = td.value[tdValueIndex] return { index, - isCheckbox: tdValueElement.type === ElementType.CHECKBOX, + isCheckbox: tdValueElement.type === ElementType.CHECKBOX || + tdValueElement.controlComponent === ControlComponent.CHECKBOX, isControl: tdValueElement.type === ElementType.CONTROL, isImage: tablePosition.isImage, isDirectHit: tablePosition.isDirectHit, @@ -121,7 +123,10 @@ export class Position { isImage: true } } - if (element.type === ElementType.CHECKBOX) { + if ( + element.type === ElementType.CHECKBOX || + element.controlComponent === ControlComponent.CHECKBOX + ) { return { index: curPositionIndex, isDirectHit: true, diff --git a/src/editor/dataset/enum/Control.ts b/src/editor/dataset/enum/Control.ts index 00670db..c40a8d4 100644 --- a/src/editor/dataset/enum/Control.ts +++ b/src/editor/dataset/enum/Control.ts @@ -1,11 +1,13 @@ export enum ControlType { TEXT = 'text', - SELECT = 'select' + SELECT = 'select', + CHECKBOX = 'checkbox' } export enum ControlComponent { PREFIX = 'prefix', POSTFIX = 'postfix', PLACEHOLDER = 'placeholder', - VALUE = 'value' + VALUE = 'value', + CHECKBOX = 'checkbox' } \ No newline at end of file diff --git a/src/editor/interface/Control.ts b/src/editor/interface/Control.ts index b0d773f..a691311 100644 --- a/src/editor/interface/Control.ts +++ b/src/editor/interface/Control.ts @@ -1,4 +1,5 @@ import { ControlType } from '../dataset/enum/Control' +import { ICheckbox } from './Checkbox' import { IElement } from './Element' export interface IValueSet { @@ -11,6 +12,14 @@ export interface IControlSelect { valueSets: IValueSet[]; } +export interface IControlCheckbox { + code: string | null; + min?: number; + max?: number; + valueSets: IValueSet[]; + checkbox?: ICheckbox; +} + export interface IControlBasic { type: ControlType; value: IElement[] | null; @@ -20,7 +29,10 @@ export interface IControlBasic { postfix?: string; } -export type IControl = IControlBasic & Partial +export type IControl = IControlBasic + & Partial + & Partial + export interface IControlOption { placeholderColor?: string; diff --git a/src/editor/interface/Position.ts b/src/editor/interface/Position.ts index 1d15f1d..5b94abe 100644 --- a/src/editor/interface/Position.ts +++ b/src/editor/interface/Position.ts @@ -29,6 +29,7 @@ export interface IGetPositionByXYPayload { export interface IPositionContext { isTable: boolean; + isCheckbox?: boolean; isControl?: boolean; index?: number; trIndex?: number; diff --git a/src/editor/utils/element.ts b/src/editor/utils/element.ts index 3614252..d77cd43 100644 --- a/src/editor/utils/element.ts +++ b/src/editor/utils/element.ts @@ -97,33 +97,68 @@ export function formatElementList(elementList: IElement[], options: IFormatEleme // 值 if ( (value && value.length) || + type === ControlType.CHECKBOX || (type === ControlType.SELECT && code && (!value || !value.length)) ) { let valueList: IElement[] = value || [] - if (!value || !value.length) { + if (type === ControlType.CHECKBOX) { + const codeList = code ? code.split(',') : [] if (Array.isArray(valueSets) && valueSets.length) { - const valueSet = valueSets.find(v => v.code === code) - if (valueSet) { - valueList = [{ - value: valueSet.value - }] + for (let v = 0; v < valueSets.length; v++) { + const valueSet = valueSets[v] + // checkbox组件 + elementList.splice(i, 0, { + controlId, + value: '', + type: el.type, + control: el.control, + controlComponent: ControlComponent.CHECKBOX, + checkbox: { + value: codeList.includes(valueSet.code) + } + }) + i++ + // 文本 + const valueStrList = valueSet.value.split('') + for (let e = 0; e < valueStrList.length; e++) { + const value = valueStrList[e] + elementList.splice(i, 0, { + controlId, + value, + type: el.type, + control: el.control, + controlComponent: ControlComponent.VALUE + }) + i++ + } } } - } - for (let v = 0; v < valueList.length; v++) { - const element = valueList[v] - const valueStrList = element.value.split('') - for (let e = 0; e < valueStrList.length; e++) { - const value = valueStrList[e] - elementList.splice(i, 0, { - ...element, - controlId, - value, - type: el.type, - control: el.control, - controlComponent: ControlComponent.VALUE - }) - i++ + } else { + if (!value || !value.length) { + if (Array.isArray(valueSets) && valueSets.length) { + const valueSet = valueSets.find(v => v.code === code) + if (valueSet) { + valueList = [{ + value: valueSet.value + }] + } + } + } + for (let v = 0; v < valueList.length; v++) { + const element = valueList[v] + const valueStrList = element.value.split('') + for (let e = 0; e < valueStrList.length; e++) { + const value = valueStrList[e] + elementList.splice(i, 0, { + ...element, + controlId, + value, + type: el.type, + control: el.control, + controlComponent: ControlComponent.VALUE + }) + i++ + } } } } else { diff --git a/src/mock.ts b/src/mock.ts index 8858643..ea78682 100644 --- a/src/mock.ts +++ b/src/mock.ts @@ -250,18 +250,20 @@ elementList.push({ elementList.push(...[{ value: '是否同意以上内容:' }, { - type: ElementType.CHECKBOX, - checkbox: { - value: true + type: ElementType.CONTROL, + control: { + type: ControlType.CHECKBOX, + code: '98175', + value: '', + valueSets: [{ + value: '同意', + code: '98175' + }, { + value: '否定', + code: '98176' + }] }, value: '' -}, { - value: '同意' -}, { - type: ElementType.CHECKBOX, - value: '' -}, { - value: '否定' }, { value: '\n' }])