feat: add date control #601
This commit is contained in:
+3
-17
@@ -81,7 +81,8 @@ interface IElement {
|
|||||||
TEXT = 'text',
|
TEXT = 'text',
|
||||||
SELECT = 'select',
|
SELECT = 'select',
|
||||||
CHECKBOX = 'checkbox',
|
CHECKBOX = 'checkbox',
|
||||||
RADIO = 'radio'
|
RADIO = 'radio',
|
||||||
|
DATE = 'date'
|
||||||
};
|
};
|
||||||
value: IElement[] | null;
|
value: IElement[] | null;
|
||||||
placeholder?: string;
|
placeholder?: string;
|
||||||
@@ -102,18 +103,7 @@ interface IElement {
|
|||||||
value: string;
|
value: string;
|
||||||
code: string;
|
code: string;
|
||||||
}[];
|
}[];
|
||||||
checkbox?: {
|
dateFormat?: string;
|
||||||
value: boolean | null;
|
|
||||||
code?: string;
|
|
||||||
min?: number;
|
|
||||||
max?: number;
|
|
||||||
disabled?: boolean;
|
|
||||||
};
|
|
||||||
radio?: {
|
|
||||||
value: boolean | null;
|
|
||||||
code?: string;
|
|
||||||
disabled?: boolean;
|
|
||||||
};
|
|
||||||
font?: string;
|
font?: string;
|
||||||
size?: number;
|
size?: number;
|
||||||
bold?: boolean;
|
bold?: boolean;
|
||||||
@@ -133,14 +123,10 @@ interface IElement {
|
|||||||
// checkbox
|
// checkbox
|
||||||
checkbox?: {
|
checkbox?: {
|
||||||
value: boolean | null;
|
value: boolean | null;
|
||||||
code?: string;
|
|
||||||
disabled?: boolean;
|
|
||||||
};
|
};
|
||||||
// radio
|
// radio
|
||||||
radio?: {
|
radio?: {
|
||||||
value: boolean | null;
|
value: boolean | null;
|
||||||
code?: string;
|
|
||||||
disabled?: boolean;
|
|
||||||
};
|
};
|
||||||
// LaTeX
|
// LaTeX
|
||||||
laTexSVG?: string;
|
laTexSVG?: string;
|
||||||
|
|||||||
+2
-16
@@ -82,6 +82,7 @@ interface IElement {
|
|||||||
SELECT = 'select',
|
SELECT = 'select',
|
||||||
CHECKBOX = 'checkbox',
|
CHECKBOX = 'checkbox',
|
||||||
RADIO = 'radio'
|
RADIO = 'radio'
|
||||||
|
DATE = 'date'
|
||||||
};
|
};
|
||||||
value: IElement[] | null;
|
value: IElement[] | null;
|
||||||
placeholder?: string;
|
placeholder?: string;
|
||||||
@@ -102,18 +103,7 @@ interface IElement {
|
|||||||
value: string;
|
value: string;
|
||||||
code: string;
|
code: string;
|
||||||
}[];
|
}[];
|
||||||
checkbox?: {
|
dateFormat?: string;
|
||||||
value: boolean | null;
|
|
||||||
code?: string;
|
|
||||||
min?: number;
|
|
||||||
max?: number;
|
|
||||||
disabled?: boolean;
|
|
||||||
};
|
|
||||||
radio?: {
|
|
||||||
value: boolean | null;
|
|
||||||
code?: string;
|
|
||||||
disabled?: boolean;
|
|
||||||
};
|
|
||||||
font?: string;
|
font?: string;
|
||||||
size?: number;
|
size?: number;
|
||||||
bold?: boolean;
|
bold?: boolean;
|
||||||
@@ -133,14 +123,10 @@ interface IElement {
|
|||||||
// 复选框
|
// 复选框
|
||||||
checkbox?: {
|
checkbox?: {
|
||||||
value: boolean | null;
|
value: boolean | null;
|
||||||
code?: string;
|
|
||||||
disabled?: boolean;
|
|
||||||
};
|
};
|
||||||
// 单选框
|
// 单选框
|
||||||
radio?: {
|
radio?: {
|
||||||
value: boolean | null;
|
value: boolean | null;
|
||||||
code?: string;
|
|
||||||
disabled?: boolean;
|
|
||||||
};
|
};
|
||||||
// LaTeX
|
// LaTeX
|
||||||
laTexSVG?: string;
|
laTexSVG?: string;
|
||||||
|
|||||||
@@ -40,6 +40,7 @@ import { ControlSearch } from './interactive/ControlSearch'
|
|||||||
import { ControlBorder } from './richtext/Border'
|
import { ControlBorder } from './richtext/Border'
|
||||||
import { SelectControl } from './select/SelectControl'
|
import { SelectControl } from './select/SelectControl'
|
||||||
import { TextControl } from './text/TextControl'
|
import { TextControl } from './text/TextControl'
|
||||||
|
import { DateControl } from './date/DateControl'
|
||||||
import { MoveDirection } from '../../../dataset/enum/Observer'
|
import { MoveDirection } from '../../../dataset/enum/Observer'
|
||||||
|
|
||||||
interface IMoveCursorResult {
|
interface IMoveCursorResult {
|
||||||
@@ -223,9 +224,16 @@ export class Control {
|
|||||||
const element = elementList[range.startIndex]
|
const element = elementList[range.startIndex]
|
||||||
// 判断控件是否已经激活
|
// 判断控件是否已经激活
|
||||||
if (this.activeControl) {
|
if (this.activeControl) {
|
||||||
// 列举控件唤醒下拉弹窗
|
// 弹窗类控件唤醒弹窗,后缀处移除弹窗
|
||||||
if (this.activeControl instanceof SelectControl) {
|
if (
|
||||||
this.activeControl.awake()
|
this.activeControl instanceof SelectControl ||
|
||||||
|
this.activeControl instanceof DateControl
|
||||||
|
) {
|
||||||
|
if (element.controlComponent === ControlComponent.POSTFIX) {
|
||||||
|
this.activeControl.destroy()
|
||||||
|
} else {
|
||||||
|
this.activeControl.awake()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
const controlElement = this.activeControl.getElement()
|
const controlElement = this.activeControl.getElement()
|
||||||
if (element.controlId === controlElement.controlId) return
|
if (element.controlId === controlElement.controlId) return
|
||||||
@@ -244,6 +252,10 @@ export class Control {
|
|||||||
this.activeControl = new CheckboxControl(element, this)
|
this.activeControl = new CheckboxControl(element, this)
|
||||||
} else if (control.type === ControlType.RADIO) {
|
} else if (control.type === ControlType.RADIO) {
|
||||||
this.activeControl = new RadioControl(element, this)
|
this.activeControl = new RadioControl(element, this)
|
||||||
|
} else if (control.type === ControlType.DATE) {
|
||||||
|
const dateControl = new DateControl(element, this)
|
||||||
|
this.activeControl = dateControl
|
||||||
|
dateControl.awake()
|
||||||
}
|
}
|
||||||
// 激活控件回调
|
// 激活控件回调
|
||||||
nextTick(() => {
|
nextTick(() => {
|
||||||
@@ -269,7 +281,10 @@ export class Control {
|
|||||||
|
|
||||||
public destroyControl() {
|
public destroyControl() {
|
||||||
if (this.activeControl) {
|
if (this.activeControl) {
|
||||||
if (this.activeControl instanceof SelectControl) {
|
if (
|
||||||
|
this.activeControl instanceof SelectControl ||
|
||||||
|
this.activeControl instanceof DateControl
|
||||||
|
) {
|
||||||
this.activeControl.destroy()
|
this.activeControl.destroy()
|
||||||
}
|
}
|
||||||
this.activeControl = null
|
this.activeControl = null
|
||||||
@@ -316,7 +331,8 @@ export class Control {
|
|||||||
const element = elementList[range.startIndex]
|
const element = elementList[range.startIndex]
|
||||||
this.activeControl.setElement(element)
|
this.activeControl.setElement(element)
|
||||||
if (
|
if (
|
||||||
this.activeControl instanceof SelectControl &&
|
(this.activeControl instanceof DateControl ||
|
||||||
|
this.activeControl instanceof SelectControl) &&
|
||||||
this.activeControl.getIsPopup()
|
this.activeControl.getIsPopup()
|
||||||
) {
|
) {
|
||||||
this.activeControl.destroy()
|
this.activeControl.destroy()
|
||||||
@@ -542,14 +558,14 @@ export class Control {
|
|||||||
const nextElement = elementList[j]
|
const nextElement = elementList[j]
|
||||||
if (nextElement.controlId !== element.controlId) break
|
if (nextElement.controlId !== element.controlId) break
|
||||||
if (
|
if (
|
||||||
type === ControlType.TEXT &&
|
(type === ControlType.TEXT || type === ControlType.DATE) &&
|
||||||
nextElement.controlComponent === ControlComponent.VALUE
|
nextElement.controlComponent === ControlComponent.VALUE
|
||||||
) {
|
) {
|
||||||
textControlValue += nextElement.value
|
textControlValue += nextElement.value
|
||||||
}
|
}
|
||||||
j++
|
j++
|
||||||
}
|
}
|
||||||
if (type === ControlType.TEXT) {
|
if (type === ControlType.TEXT || type === ControlType.DATE) {
|
||||||
result.push({
|
result.push({
|
||||||
...element.control,
|
...element.control,
|
||||||
zone,
|
zone,
|
||||||
@@ -674,6 +690,14 @@ export class Control {
|
|||||||
this.activeControl = radio
|
this.activeControl = radio
|
||||||
const codes = value ? [value] : []
|
const codes = value ? [value] : []
|
||||||
radio.setSelect(codes, controlContext, controlRule)
|
radio.setSelect(codes, controlContext, controlRule)
|
||||||
|
} else if (type === ControlType.DATE) {
|
||||||
|
const date = new DateControl(element, this)
|
||||||
|
this.activeControl = date
|
||||||
|
if (value) {
|
||||||
|
date.setSelect(value, controlContext, controlRule)
|
||||||
|
} else {
|
||||||
|
date.clearSelect(controlContext, controlRule)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// 模拟控件激活后销毁
|
// 模拟控件激活后销毁
|
||||||
this.activeControl = null
|
this.activeControl = null
|
||||||
|
|||||||
@@ -0,0 +1,361 @@
|
|||||||
|
import {
|
||||||
|
CONTROL_STYLE_ATTR,
|
||||||
|
EDITOR_ELEMENT_STYLE_ATTR,
|
||||||
|
TEXTLIKE_ELEMENT_TYPE
|
||||||
|
} from '../../../../dataset/constant/Element'
|
||||||
|
import { ControlComponent } from '../../../../dataset/enum/Control'
|
||||||
|
import { ElementType } from '../../../../dataset/enum/Element'
|
||||||
|
import { KeyMap } from '../../../../dataset/enum/KeyMap'
|
||||||
|
import {
|
||||||
|
IControlContext,
|
||||||
|
IControlInstance,
|
||||||
|
IControlRuleOption
|
||||||
|
} from '../../../../interface/Control'
|
||||||
|
import { IElement } from '../../../../interface/Element'
|
||||||
|
import { omitObject, pickObject } from '../../../../utils'
|
||||||
|
import { formatElementContext } from '../../../../utils/element'
|
||||||
|
import { Draw } from '../../Draw'
|
||||||
|
import { DatePicker } from '../../particle/date/DatePicker'
|
||||||
|
import { Control } from '../Control'
|
||||||
|
|
||||||
|
export class DateControl implements IControlInstance {
|
||||||
|
private draw: Draw
|
||||||
|
private element: IElement
|
||||||
|
private control: Control
|
||||||
|
private isPopup: boolean
|
||||||
|
private datePicker: DatePicker | null
|
||||||
|
|
||||||
|
constructor(element: IElement, control: Control) {
|
||||||
|
const draw = control.getDraw()
|
||||||
|
this.draw = draw
|
||||||
|
this.element = element
|
||||||
|
this.control = control
|
||||||
|
this.isPopup = false
|
||||||
|
this.datePicker = null
|
||||||
|
}
|
||||||
|
|
||||||
|
public setElement(element: IElement) {
|
||||||
|
this.element = element
|
||||||
|
}
|
||||||
|
|
||||||
|
public getElement(): IElement {
|
||||||
|
return this.element
|
||||||
|
}
|
||||||
|
|
||||||
|
public getIsPopup(): boolean {
|
||||||
|
return this.isPopup
|
||||||
|
}
|
||||||
|
|
||||||
|
public getValueRange(context: IControlContext = {}): [number, number] | null {
|
||||||
|
const elementList = context.elementList || this.control.getElementList()
|
||||||
|
const { startIndex } = context.range || this.control.getRange()
|
||||||
|
const startElement = elementList[startIndex]
|
||||||
|
// 向左查找
|
||||||
|
let preIndex = startIndex
|
||||||
|
while (preIndex > 0) {
|
||||||
|
const preElement = elementList[preIndex]
|
||||||
|
if (
|
||||||
|
preElement.controlId !== startElement.controlId ||
|
||||||
|
preElement.controlComponent === ControlComponent.PREFIX
|
||||||
|
) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
preIndex--
|
||||||
|
}
|
||||||
|
// 向右查找
|
||||||
|
let nextIndex = startIndex + 1
|
||||||
|
while (nextIndex < elementList.length) {
|
||||||
|
const nextElement = elementList[nextIndex]
|
||||||
|
if (
|
||||||
|
nextElement.controlId !== startElement.controlId ||
|
||||||
|
nextElement.controlComponent === ControlComponent.POSTFIX
|
||||||
|
) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
nextIndex++
|
||||||
|
}
|
||||||
|
if (preIndex === nextIndex) return null
|
||||||
|
return [preIndex, nextIndex - 1]
|
||||||
|
}
|
||||||
|
|
||||||
|
public getValue(context: IControlContext = {}): IElement[] {
|
||||||
|
const elementList = context.elementList || this.control.getElementList()
|
||||||
|
const range = this.getValueRange(context)
|
||||||
|
if (!range) return []
|
||||||
|
const data: IElement[] = []
|
||||||
|
const [startIndex, endIndex] = range
|
||||||
|
for (let i = startIndex; i <= endIndex; i++) {
|
||||||
|
const element = elementList[i]
|
||||||
|
if (element.controlComponent === ControlComponent.VALUE) {
|
||||||
|
data.push(element)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return data
|
||||||
|
}
|
||||||
|
|
||||||
|
public setValue(
|
||||||
|
data: IElement[],
|
||||||
|
context: IControlContext = {},
|
||||||
|
options: IControlRuleOption = {}
|
||||||
|
): number {
|
||||||
|
// 校验是否可以设置
|
||||||
|
if (!options.isIgnoreDisabledRule && this.control.getIsDisabledControl()) {
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
const elementList = context.elementList || this.control.getElementList()
|
||||||
|
const range = context.range || this.control.getRange()
|
||||||
|
// 收缩边界到Value内
|
||||||
|
this.control.shrinkBoundary(context)
|
||||||
|
const { startIndex, endIndex } = range
|
||||||
|
const draw = this.control.getDraw()
|
||||||
|
// 移除选区元素
|
||||||
|
if (startIndex !== endIndex) {
|
||||||
|
draw.spliceElementList(elementList, startIndex + 1, endIndex - startIndex)
|
||||||
|
} else {
|
||||||
|
// 移除空白占位符
|
||||||
|
this.control.removePlaceholder(startIndex, context)
|
||||||
|
}
|
||||||
|
// 非文本类元素或前缀过渡掉样式属性
|
||||||
|
const startElement = elementList[startIndex]
|
||||||
|
const anchorElement =
|
||||||
|
(startElement.type &&
|
||||||
|
!TEXTLIKE_ELEMENT_TYPE.includes(startElement.type)) ||
|
||||||
|
startElement.controlComponent === ControlComponent.PREFIX
|
||||||
|
? pickObject(startElement, [
|
||||||
|
'control',
|
||||||
|
'controlId',
|
||||||
|
...CONTROL_STYLE_ATTR
|
||||||
|
])
|
||||||
|
: omitObject(startElement, ['type'])
|
||||||
|
// 插入起始位置
|
||||||
|
const start = range.startIndex + 1
|
||||||
|
for (let i = 0; i < data.length; i++) {
|
||||||
|
const newElement: IElement = {
|
||||||
|
...anchorElement,
|
||||||
|
...data[i],
|
||||||
|
controlComponent: ControlComponent.VALUE
|
||||||
|
}
|
||||||
|
formatElementContext(elementList, [newElement], startIndex)
|
||||||
|
draw.spliceElementList(elementList, start + i, 0, newElement)
|
||||||
|
}
|
||||||
|
return start + data.length - 1
|
||||||
|
}
|
||||||
|
|
||||||
|
public clearSelect(
|
||||||
|
context: IControlContext = {},
|
||||||
|
options: IControlRuleOption = {}
|
||||||
|
): number {
|
||||||
|
const { isIgnoreDisabledRule = false, isAddPlaceholder = true } = options
|
||||||
|
// 校验是否可以设置
|
||||||
|
if (!isIgnoreDisabledRule && this.control.getIsDisabledControl()) {
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
const range = this.getValueRange(context)
|
||||||
|
if (!range) return -1
|
||||||
|
const [leftIndex, rightIndex] = range
|
||||||
|
if (!~leftIndex || !~rightIndex) return -1
|
||||||
|
const elementList = context.elementList || this.control.getElementList()
|
||||||
|
// 删除元素
|
||||||
|
const draw = this.control.getDraw()
|
||||||
|
draw.spliceElementList(elementList, leftIndex + 1, rightIndex - leftIndex)
|
||||||
|
// 增加占位符
|
||||||
|
if (isAddPlaceholder) {
|
||||||
|
this.control.addPlaceholder(leftIndex, context)
|
||||||
|
}
|
||||||
|
return leftIndex
|
||||||
|
}
|
||||||
|
|
||||||
|
public setSelect(
|
||||||
|
date: string,
|
||||||
|
context: IControlContext = {},
|
||||||
|
options: IControlRuleOption = {}
|
||||||
|
) {
|
||||||
|
// 校验是否可以设置
|
||||||
|
if (!options.isIgnoreDisabledRule && this.control.getIsDisabledControl()) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const elementList = context.elementList || this.control.getElementList()
|
||||||
|
const range = context.range || this.control.getRange()
|
||||||
|
// 样式赋值元素-默认值的第一个字符样式,否则取默认样式
|
||||||
|
const valueElement = this.getValue(context)[0]
|
||||||
|
const styleElement = valueElement
|
||||||
|
? pickObject(valueElement, EDITOR_ELEMENT_STYLE_ATTR)
|
||||||
|
: pickObject(elementList[range.startIndex], CONTROL_STYLE_ATTR)
|
||||||
|
// 清空选项
|
||||||
|
const prefixIndex = this.clearSelect(context, {
|
||||||
|
isAddPlaceholder: false
|
||||||
|
})
|
||||||
|
if (!~prefixIndex) return
|
||||||
|
// 属性赋值元素-默认为前缀属性
|
||||||
|
const propertyElement = omitObject(
|
||||||
|
elementList[prefixIndex],
|
||||||
|
EDITOR_ELEMENT_STYLE_ATTR
|
||||||
|
)
|
||||||
|
const start = prefixIndex + 1
|
||||||
|
const draw = this.control.getDraw()
|
||||||
|
for (let i = 0; i < date.length; i++) {
|
||||||
|
const newElement: IElement = {
|
||||||
|
...styleElement,
|
||||||
|
...propertyElement,
|
||||||
|
type: ElementType.TEXT,
|
||||||
|
value: date[i],
|
||||||
|
controlComponent: ControlComponent.VALUE
|
||||||
|
}
|
||||||
|
formatElementContext(elementList, [newElement], prefixIndex)
|
||||||
|
draw.spliceElementList(elementList, start + i, 0, newElement)
|
||||||
|
}
|
||||||
|
// 重新渲染控件
|
||||||
|
if (!context.range) {
|
||||||
|
const newIndex = start + date.length - 1
|
||||||
|
this.control.repaintControl({
|
||||||
|
curIndex: newIndex
|
||||||
|
})
|
||||||
|
this.destroy()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public keydown(evt: KeyboardEvent): number | null {
|
||||||
|
if (this.control.getIsDisabledControl()) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
const elementList = this.control.getElementList()
|
||||||
|
const range = this.control.getRange()
|
||||||
|
// 收缩边界到Value内
|
||||||
|
this.control.shrinkBoundary()
|
||||||
|
const { startIndex, endIndex } = range
|
||||||
|
const startElement = elementList[startIndex]
|
||||||
|
const endElement = elementList[endIndex]
|
||||||
|
const draw = this.control.getDraw()
|
||||||
|
// backspace
|
||||||
|
if (evt.key === KeyMap.Backspace) {
|
||||||
|
// 移除选区元素
|
||||||
|
if (startIndex !== endIndex) {
|
||||||
|
draw.spliceElementList(
|
||||||
|
elementList,
|
||||||
|
startIndex + 1,
|
||||||
|
endIndex - startIndex
|
||||||
|
)
|
||||||
|
const value = this.getValue()
|
||||||
|
if (!value.length) {
|
||||||
|
this.control.addPlaceholder(startIndex)
|
||||||
|
}
|
||||||
|
return startIndex
|
||||||
|
} else {
|
||||||
|
if (
|
||||||
|
startElement.controlComponent === ControlComponent.PREFIX ||
|
||||||
|
endElement.controlComponent === ControlComponent.POSTFIX ||
|
||||||
|
startElement.controlComponent === ControlComponent.PLACEHOLDER
|
||||||
|
) {
|
||||||
|
// 前缀、后缀、占位符
|
||||||
|
return this.control.removeControl(startIndex)
|
||||||
|
} else {
|
||||||
|
// 文本
|
||||||
|
draw.spliceElementList(elementList, startIndex, 1)
|
||||||
|
const value = this.getValue()
|
||||||
|
if (!value.length) {
|
||||||
|
this.control.addPlaceholder(startIndex - 1)
|
||||||
|
}
|
||||||
|
return startIndex - 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (evt.key === KeyMap.Delete) {
|
||||||
|
// 移除选区元素
|
||||||
|
if (startIndex !== endIndex) {
|
||||||
|
draw.spliceElementList(
|
||||||
|
elementList,
|
||||||
|
startIndex + 1,
|
||||||
|
endIndex - startIndex
|
||||||
|
)
|
||||||
|
const value = this.getValue()
|
||||||
|
if (!value.length) {
|
||||||
|
this.control.addPlaceholder(startIndex)
|
||||||
|
}
|
||||||
|
return startIndex
|
||||||
|
} else {
|
||||||
|
const endNextElement = elementList[endIndex + 1]
|
||||||
|
if (
|
||||||
|
(startElement.controlComponent === ControlComponent.PREFIX &&
|
||||||
|
endNextElement.controlComponent === ControlComponent.PLACEHOLDER) ||
|
||||||
|
endNextElement.controlComponent === ControlComponent.POSTFIX ||
|
||||||
|
startElement.controlComponent === ControlComponent.PLACEHOLDER
|
||||||
|
) {
|
||||||
|
// 前缀、后缀、占位符
|
||||||
|
return this.control.removeControl(startIndex)
|
||||||
|
} else {
|
||||||
|
// 文本
|
||||||
|
draw.spliceElementList(elementList, startIndex + 1, 1)
|
||||||
|
const value = this.getValue()
|
||||||
|
if (!value.length) {
|
||||||
|
this.control.addPlaceholder(startIndex)
|
||||||
|
}
|
||||||
|
return startIndex
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return endIndex
|
||||||
|
}
|
||||||
|
|
||||||
|
public cut(): number {
|
||||||
|
if (this.control.getIsDisabledControl()) {
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
this.control.shrinkBoundary()
|
||||||
|
const { startIndex, endIndex } = this.control.getRange()
|
||||||
|
if (startIndex === endIndex) {
|
||||||
|
return startIndex
|
||||||
|
}
|
||||||
|
const draw = this.control.getDraw()
|
||||||
|
const elementList = this.control.getElementList()
|
||||||
|
draw.spliceElementList(elementList, startIndex + 1, endIndex - startIndex)
|
||||||
|
const value = this.getValue()
|
||||||
|
if (!value.length) {
|
||||||
|
this.control.addPlaceholder(startIndex)
|
||||||
|
}
|
||||||
|
return startIndex
|
||||||
|
}
|
||||||
|
|
||||||
|
public awake() {
|
||||||
|
if (this.isPopup || this.control.getIsDisabledControl()) return
|
||||||
|
const position = this.control.getPosition()
|
||||||
|
if (!position) return
|
||||||
|
const elementList = this.draw.getElementList()
|
||||||
|
const { startIndex } = this.control.getRange()
|
||||||
|
if (elementList[startIndex + 1]?.controlId !== this.element.controlId) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// 渲染日期控件
|
||||||
|
this.datePicker = new DatePicker(this.draw, {
|
||||||
|
onSubmit: this._setDate.bind(this)
|
||||||
|
})
|
||||||
|
const range = this.getValueRange()
|
||||||
|
const value = range
|
||||||
|
? elementList
|
||||||
|
.slice(range[0] + 1, range[1] + 1)
|
||||||
|
.map(el => el.value)
|
||||||
|
.join('')
|
||||||
|
: ''
|
||||||
|
const dateFormat = this.element.control?.dateFormat
|
||||||
|
this.datePicker.render({
|
||||||
|
value,
|
||||||
|
position,
|
||||||
|
dateFormat
|
||||||
|
})
|
||||||
|
// 弹窗状态
|
||||||
|
this.isPopup = true
|
||||||
|
}
|
||||||
|
|
||||||
|
public destroy() {
|
||||||
|
if (!this.isPopup) return
|
||||||
|
this.datePicker?.destroy()
|
||||||
|
this.isPopup = false
|
||||||
|
}
|
||||||
|
|
||||||
|
private _setDate(date: string) {
|
||||||
|
if (!date) {
|
||||||
|
this.clearSelect()
|
||||||
|
} else {
|
||||||
|
this.setSelect(date)
|
||||||
|
}
|
||||||
|
this.destroy()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -13,31 +13,8 @@ export class DateParticle {
|
|||||||
constructor(draw: Draw) {
|
constructor(draw: Draw) {
|
||||||
this.draw = draw
|
this.draw = draw
|
||||||
this.range = draw.getRange()
|
this.range = draw.getRange()
|
||||||
const i18n = draw.getI18n()
|
this.datePicker = new DatePicker(draw, {
|
||||||
const t = i18n.t.bind(i18n)
|
onSubmit: this._setValue.bind(this)
|
||||||
this.datePicker = new DatePicker({
|
|
||||||
mountDom: draw.getContainer(),
|
|
||||||
onSubmit: this._setValue.bind(this),
|
|
||||||
getLang: () => ({
|
|
||||||
now: t('datePicker.now'),
|
|
||||||
confirm: t('datePicker.confirm'),
|
|
||||||
return: t('datePicker.return'),
|
|
||||||
timeSelect: t('datePicker.timeSelect'),
|
|
||||||
weeks: {
|
|
||||||
sun: t('datePicker.weeks.sun'),
|
|
||||||
mon: t('datePicker.weeks.mon'),
|
|
||||||
tue: t('datePicker.weeks.tue'),
|
|
||||||
wed: t('datePicker.weeks.wed'),
|
|
||||||
thu: t('datePicker.weeks.thu'),
|
|
||||||
fri: t('datePicker.weeks.fri'),
|
|
||||||
sat: t('datePicker.weeks.sat')
|
|
||||||
},
|
|
||||||
year: t('datePicker.year'),
|
|
||||||
month: t('datePicker.month'),
|
|
||||||
hour: t('datePicker.hour'),
|
|
||||||
minute: t('datePicker.minute'),
|
|
||||||
second: t('datePicker.second')
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -111,9 +88,6 @@ export class DateParticle {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public renderDatePicker(element: IElement, position: IElementPosition) {
|
public renderDatePicker(element: IElement, position: IElementPosition) {
|
||||||
const height = this.draw.getHeight()
|
|
||||||
const pageGap = this.draw.getPageGap()
|
|
||||||
const startTop = this.draw.getPageNo() * (height + pageGap)
|
|
||||||
const elementList = this.draw.getElementList()
|
const elementList = this.draw.getElementList()
|
||||||
const range = this.getDateElementRange()
|
const range = this.getDateElementRange()
|
||||||
const value = range
|
const value = range
|
||||||
@@ -124,9 +98,8 @@ export class DateParticle {
|
|||||||
: ''
|
: ''
|
||||||
this.datePicker.render({
|
this.datePicker.render({
|
||||||
value,
|
value,
|
||||||
element,
|
|
||||||
position,
|
position,
|
||||||
startTop
|
dateFormat: element.dateFormat
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,10 @@
|
|||||||
import { EDITOR_PREFIX } from '../../../../dataset/constant/Editor'
|
import {
|
||||||
import { IElement, IElementPosition } from '../../../../interface/Element'
|
EDITOR_COMPONENT,
|
||||||
import { datePicker } from '../../../i18n/lang/zh-CN.json'
|
EDITOR_PREFIX
|
||||||
|
} from '../../../../dataset/constant/Editor'
|
||||||
|
import { EditorComponent } from '../../../../dataset/enum/Editor'
|
||||||
|
import { IElementPosition } from '../../../../interface/Element'
|
||||||
|
import { Draw } from '../../Draw'
|
||||||
|
|
||||||
export interface IDatePickerLang {
|
export interface IDatePickerLang {
|
||||||
now: string
|
now: string
|
||||||
@@ -24,9 +28,7 @@ export interface IDatePickerLang {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface IDatePickerOption {
|
export interface IDatePickerOption {
|
||||||
mountDom?: HTMLElement
|
|
||||||
onSubmit?: (date: string) => any
|
onSubmit?: (date: string) => any
|
||||||
getLang?: () => IDatePickerLang
|
|
||||||
}
|
}
|
||||||
|
|
||||||
interface IDatePickerDom {
|
interface IDatePickerDom {
|
||||||
@@ -56,12 +58,12 @@ interface IDatePickerDom {
|
|||||||
|
|
||||||
interface IRenderOption {
|
interface IRenderOption {
|
||||||
value: string
|
value: string
|
||||||
element: IElement
|
|
||||||
position: IElementPosition
|
position: IElementPosition
|
||||||
startTop?: number
|
dateFormat?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
export class DatePicker {
|
export class DatePicker {
|
||||||
|
private draw: Draw
|
||||||
private options: IDatePickerOption
|
private options: IDatePickerOption
|
||||||
private now: Date
|
private now: Date
|
||||||
private dom: IDatePickerDom
|
private dom: IDatePickerDom
|
||||||
@@ -70,12 +72,10 @@ export class DatePicker {
|
|||||||
private pickDate: Date | null
|
private pickDate: Date | null
|
||||||
private lang: IDatePickerLang
|
private lang: IDatePickerLang
|
||||||
|
|
||||||
constructor(options: IDatePickerOption = {}) {
|
constructor(draw: Draw, options: IDatePickerOption = {}) {
|
||||||
this.options = {
|
this.draw = draw
|
||||||
mountDom: document.body,
|
this.options = options
|
||||||
...options
|
this.lang = this._getLang()
|
||||||
}
|
|
||||||
this.lang = datePicker
|
|
||||||
this.now = new Date()
|
this.now = new Date()
|
||||||
this.dom = this._createDom()
|
this.dom = this._createDom()
|
||||||
this.renderOptions = null
|
this.renderOptions = null
|
||||||
@@ -87,6 +87,7 @@ export class DatePicker {
|
|||||||
private _createDom(): IDatePickerDom {
|
private _createDom(): IDatePickerDom {
|
||||||
const datePickerContainer = document.createElement('div')
|
const datePickerContainer = document.createElement('div')
|
||||||
datePickerContainer.classList.add(`${EDITOR_PREFIX}-date-container`)
|
datePickerContainer.classList.add(`${EDITOR_PREFIX}-date-container`)
|
||||||
|
datePickerContainer.setAttribute(EDITOR_COMPONENT, EditorComponent.POPUP)
|
||||||
// title-切换年月、年月显示
|
// title-切换年月、年月显示
|
||||||
const dateWrap = document.createElement('div')
|
const dateWrap = document.createElement('div')
|
||||||
dateWrap.classList.add(`${EDITOR_PREFIX}-date-wrap`)
|
dateWrap.classList.add(`${EDITOR_PREFIX}-date-wrap`)
|
||||||
@@ -181,7 +182,7 @@ export class DatePicker {
|
|||||||
datePickerContainer.append(dateWrap)
|
datePickerContainer.append(dateWrap)
|
||||||
datePickerContainer.append(timeWrap)
|
datePickerContainer.append(timeWrap)
|
||||||
datePickerContainer.append(datePickerMenu)
|
datePickerContainer.append(datePickerMenu)
|
||||||
this.options.mountDom!.append(datePickerContainer)
|
this.draw.getContainer().append(datePickerContainer)
|
||||||
return {
|
return {
|
||||||
container: datePickerContainer,
|
container: datePickerContainer,
|
||||||
dateWrap,
|
dateWrap,
|
||||||
@@ -266,13 +267,17 @@ export class DatePicker {
|
|||||||
coordinate: {
|
coordinate: {
|
||||||
leftTop: [left, top]
|
leftTop: [left, top]
|
||||||
},
|
},
|
||||||
lineHeight
|
lineHeight,
|
||||||
},
|
pageNo
|
||||||
startTop
|
}
|
||||||
} = this.renderOptions
|
} = this.renderOptions
|
||||||
|
const height = this.draw.getHeight()
|
||||||
|
const pageGap = this.draw.getPageGap()
|
||||||
|
const currentPageNo = pageNo ?? this.draw.getPageNo()
|
||||||
|
const preY = currentPageNo * (height + pageGap)
|
||||||
// 位置
|
// 位置
|
||||||
this.dom.container.style.left = `${left}px`
|
this.dom.container.style.left = `${left}px`
|
||||||
this.dom.container.style.top = `${top + (startTop || 0) + lineHeight}px`
|
this.dom.container.style.top = `${top + preY + lineHeight}px`
|
||||||
}
|
}
|
||||||
|
|
||||||
public isInvalidDate(value: Date): boolean {
|
public isInvalidDate(value: Date): boolean {
|
||||||
@@ -290,7 +295,32 @@ export class DatePicker {
|
|||||||
this.pickDate = new Date(this.now)
|
this.pickDate = new Date(this.now)
|
||||||
}
|
}
|
||||||
|
|
||||||
private _setLang() {
|
private _getLang() {
|
||||||
|
const i18n = this.draw.getI18n()
|
||||||
|
const t = i18n.t.bind(i18n)
|
||||||
|
return {
|
||||||
|
now: t('datePicker.now'),
|
||||||
|
confirm: t('datePicker.confirm'),
|
||||||
|
return: t('datePicker.return'),
|
||||||
|
timeSelect: t('datePicker.timeSelect'),
|
||||||
|
weeks: {
|
||||||
|
sun: t('datePicker.weeks.sun'),
|
||||||
|
mon: t('datePicker.weeks.mon'),
|
||||||
|
tue: t('datePicker.weeks.tue'),
|
||||||
|
wed: t('datePicker.weeks.wed'),
|
||||||
|
thu: t('datePicker.weeks.thu'),
|
||||||
|
fri: t('datePicker.weeks.fri'),
|
||||||
|
sat: t('datePicker.weeks.sat')
|
||||||
|
},
|
||||||
|
year: t('datePicker.year'),
|
||||||
|
month: t('datePicker.month'),
|
||||||
|
hour: t('datePicker.hour'),
|
||||||
|
minute: t('datePicker.minute'),
|
||||||
|
second: t('datePicker.second')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private _setLangChange() {
|
||||||
this.dom.menu.time.innerText = this.lang.timeSelect
|
this.dom.menu.time.innerText = this.lang.timeSelect
|
||||||
this.dom.menu.now.innerText = this.lang.now
|
this.dom.menu.now.innerText = this.lang.now
|
||||||
this.dom.menu.submit.innerText = this.lang.confirm
|
this.dom.menu.submit.innerText = this.lang.confirm
|
||||||
@@ -505,7 +535,7 @@ export class DatePicker {
|
|||||||
|
|
||||||
private _submit() {
|
private _submit() {
|
||||||
if (this.options.onSubmit && this.pickDate) {
|
if (this.options.onSubmit && this.pickDate) {
|
||||||
const format = this.renderOptions?.element.dateFormat
|
const format = this.renderOptions?.dateFormat
|
||||||
const pickDateString = this.formatDate(this.pickDate, format)
|
const pickDateString = this.formatDate(this.pickDate, format)
|
||||||
this.options.onSubmit(pickDateString)
|
this.options.onSubmit(pickDateString)
|
||||||
}
|
}
|
||||||
@@ -538,10 +568,8 @@ export class DatePicker {
|
|||||||
|
|
||||||
public render(option: IRenderOption) {
|
public render(option: IRenderOption) {
|
||||||
this.renderOptions = option
|
this.renderOptions = option
|
||||||
if (this.options.getLang) {
|
this.lang = this._getLang()
|
||||||
this.lang = this.options.getLang()
|
this._setLangChange()
|
||||||
this._setLang()
|
|
||||||
}
|
|
||||||
this._setValue()
|
this._setValue()
|
||||||
this._update()
|
this._update()
|
||||||
this._setPosition()
|
this._setPosition()
|
||||||
@@ -553,4 +581,8 @@ export class DatePicker {
|
|||||||
public dispose() {
|
public dispose() {
|
||||||
this._toggleVisible(false)
|
this._toggleVisible(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public destroy() {
|
||||||
|
this.dom.container.remove()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,8 @@ export enum ControlType {
|
|||||||
TEXT = 'text',
|
TEXT = 'text',
|
||||||
SELECT = 'select',
|
SELECT = 'select',
|
||||||
CHECKBOX = 'checkbox',
|
CHECKBOX = 'checkbox',
|
||||||
RADIO = 'radio'
|
RADIO = 'radio',
|
||||||
|
DATE = 'date'
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum ControlComponent {
|
export enum ControlComponent {
|
||||||
|
|||||||
@@ -1,11 +1,9 @@
|
|||||||
import { ControlType, ControlIndentation } from '../dataset/enum/Control'
|
import { ControlType, ControlIndentation } from '../dataset/enum/Control'
|
||||||
import { EditorZone } from '../dataset/enum/Editor'
|
import { EditorZone } from '../dataset/enum/Editor'
|
||||||
import { MoveDirection } from '../dataset/enum/Observer'
|
import { MoveDirection } from '../dataset/enum/Observer'
|
||||||
import { ICheckbox } from './Checkbox'
|
|
||||||
import { IDrawOption } from './Draw'
|
import { IDrawOption } from './Draw'
|
||||||
import { IElement } from './Element'
|
import { IElement } from './Element'
|
||||||
import { IPositionContext } from './Position'
|
import { IPositionContext } from './Position'
|
||||||
import { IRadio } from './Radio'
|
|
||||||
import { IRange } from './Range'
|
import { IRange } from './Range'
|
||||||
|
|
||||||
export interface IValueSet {
|
export interface IValueSet {
|
||||||
@@ -23,13 +21,15 @@ export interface IControlCheckbox {
|
|||||||
min?: number
|
min?: number
|
||||||
max?: number
|
max?: number
|
||||||
valueSets: IValueSet[]
|
valueSets: IValueSet[]
|
||||||
checkbox?: ICheckbox
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IControlRadio {
|
export interface IControlRadio {
|
||||||
code: string | null
|
code: string | null
|
||||||
valueSets: IValueSet[]
|
valueSets: IValueSet[]
|
||||||
radio?: IRadio
|
}
|
||||||
|
|
||||||
|
export interface IControlDate {
|
||||||
|
dateFormat?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IControlHighlightRule {
|
export interface IControlHighlightRule {
|
||||||
@@ -73,10 +73,11 @@ export interface IControlStyle {
|
|||||||
|
|
||||||
export type IControl = IControlBasic &
|
export type IControl = IControlBasic &
|
||||||
IControlRule &
|
IControlRule &
|
||||||
|
Partial<IControlStyle> &
|
||||||
Partial<IControlSelect> &
|
Partial<IControlSelect> &
|
||||||
Partial<IControlCheckbox> &
|
Partial<IControlCheckbox> &
|
||||||
Partial<IControlRadio> &
|
Partial<IControlRadio> &
|
||||||
Partial<IControlStyle>
|
Partial<IControlDate>
|
||||||
|
|
||||||
export interface IControlOption {
|
export interface IControlOption {
|
||||||
placeholderColor?: string
|
placeholderColor?: string
|
||||||
|
|||||||
+11
-6
@@ -385,13 +385,18 @@ elementList.push(
|
|||||||
value: '签署日期:'
|
value: '签署日期:'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
type: ElementType.CONTROL,
|
||||||
value: '',
|
value: '',
|
||||||
valueList: [
|
control: {
|
||||||
{
|
conceptId: '5',
|
||||||
value: `2022-08-10 17:30:01`
|
type: ControlType.DATE,
|
||||||
}
|
value: [
|
||||||
],
|
{
|
||||||
type: ElementType.DATE
|
value: `2022-08-10 17:30:01`
|
||||||
|
}
|
||||||
|
],
|
||||||
|
placeholder: '签署日期'
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
value: '\n'
|
value: '\n'
|
||||||
|
|||||||
Reference in New Issue
Block a user