From 81d3b4ccee9d6af0befbf92c62250ac93a9f3afd Mon Sep 17 00:00:00 2001 From: Hufe921 Date: Wed, 17 Aug 2022 22:22:46 +0800 Subject: [PATCH] feat:add time pick for date picker --- src/editor/assets/css/date/datePicker.css | 11 ++ .../core/draw/particle/date/DatePicker.ts | 105 +++++++++++++++--- src/editor/core/event/CanvasEvent.ts | 3 +- src/editor/dataset/constant/Element.ts | 4 +- 4 files changed, 108 insertions(+), 15 deletions(-) diff --git a/src/editor/assets/css/date/datePicker.css b/src/editor/assets/css/date/datePicker.css index ffdad15..7fce570 100644 --- a/src/editor/assets/css/date/datePicker.css +++ b/src/editor/assets/css/date/datePicker.css @@ -168,6 +168,17 @@ .time-wrap>li>ol>li { line-height: 30px; + cursor: pointer; + transition: all .3s; +} + +.time-wrap>li>ol>li:hover { + background-color: #eaeaea; +} + +.time-wrap>li>ol>li.active { + color: #ffffff; + background: #5175F4; } .date-menu { diff --git a/src/editor/core/draw/particle/date/DatePicker.ts b/src/editor/core/draw/particle/date/DatePicker.ts index 09a2683..444c8bd 100644 --- a/src/editor/core/draw/particle/date/DatePicker.ts +++ b/src/editor/core/draw/particle/date/DatePicker.ts @@ -42,6 +42,7 @@ export class DatePicker { private dom: IDatePickerDom private renderOptions: IRenderOption | null private isDatePicker: boolean + private pickDate: Date | null constructor(options: IDatePickerOption = {}) { this.options = { @@ -52,6 +53,7 @@ export class DatePicker { this.dom = this._createDom() this.renderOptions = null this.isDatePicker = true + this.pickDate = null this._bindEvent() } @@ -117,6 +119,7 @@ export class DatePicker { for (let i = 0; i < endIndex; i++) { const time = document.createElement('li') time.innerText = `${String(i).padStart(2, '0')}` + time.setAttribute('data-id', `${i}`) ol.append(time) } if (isHour) { @@ -197,6 +200,30 @@ export class DatePicker { this.dom.menu.submit.onclick = () => { this.dispose() } + this.dom.time.hour.onclick = (evt) => { + if (!this.pickDate) return + const li = evt.target + const id = li.dataset.id + if (!id) return + this.pickDate.setHours(Number(id)) + this._setTimePick(false) + } + this.dom.time.minute.onclick = (evt) => { + if (!this.pickDate) return + const li = evt.target + const id = li.dataset.id + if (!id) return + this.pickDate.setMinutes(Number(id)) + this._setTimePick(false) + } + this.dom.time.second.onclick = (evt) => { + if (!this.pickDate) return + const li = evt.target + const id = li.dataset.id + if (!id) return + this.pickDate.setSeconds(Number(id)) + this._setTimePick(false) + } } private _setPosition() { @@ -215,8 +242,19 @@ export class DatePicker { this.dom.container.style.top = `${top + startTop + lineHeight}px` } - private _setNow() { - this.now = new Date() + public isInvalidDate(value: Date): boolean { + return value.toDateString() === 'Invalid Date' + } + + private _setValue() { + const value = this.renderOptions?.value + if (value) { + const setDate = new Date(value) + this.now = this.isInvalidDate(setDate) ? new Date() : setDate + } else { + this.now = new Date() + } + this.pickDate = new Date(this.now) } private _update() { @@ -225,10 +263,18 @@ export class DatePicker { const localYear = localDate.getFullYear() const localMonth = localDate.getMonth() + 1 const localDay = localDate.getDate() + // 选择年月日 + let pickYear: number | null = null + let pickMonth: number | null = null + let pickDay: number | null = null + if (this.pickDate) { + pickYear = this.pickDate.getFullYear() + pickMonth = this.pickDate.getMonth() + 1 + pickDay = this.pickDate.getDate() + } // 当前年月日 const year = this.now.getFullYear() const month = this.now.getMonth() + 1 - const day = this.now.getDate() this.dom.title.now.innerText = `${year}年 ${String(month).padStart(2, '0')}月` // 日期补差 const curDate = new Date(year, month, 0) // 当月日期 @@ -246,8 +292,9 @@ export class DatePicker { dayDom.classList.add('disable') dayDom.innerText = `${i}` dayDom.onclick = () => { - this.now = new Date(year, month - 2, i) - this._update() + const newMonth = month - 2 + this.now = new Date(year, newMonth, i) + this._setDatePick(year, newMonth, i) } this.dom.day.append(dayDom) } @@ -257,13 +304,14 @@ export class DatePicker { if (localYear === year && localMonth === month && localDay === i) { dayDom.classList.add('active') } - if (i === day) { + if (this.pickDate && pickYear === year && pickMonth === month && pickDay === i) { dayDom.classList.add('select') } dayDom.innerText = `${i}` dayDom.onclick = () => { - this.now = new Date(year, month - 1, i) - this._update() + const newMonth = month - 1 + this.now = new Date(year, newMonth, i) + this._setDatePick(year, newMonth, i) } this.dom.day.append(dayDom) } @@ -275,7 +323,7 @@ export class DatePicker { dayDom.innerText = `${i}` dayDom.onclick = () => { this.now = new Date(year, month, i) - this._update() + this._setDatePick(year, month, i) } this.dom.day.append(dayDom) } @@ -290,9 +338,40 @@ export class DatePicker { this.dom.dateWrap.classList.remove('active') this.dom.timeWrap.classList.add('active') this.dom.menu.time.innerText = `返回日期` + // 设置时分秒选择 + this._setTimePick() } } + private _setDatePick(year: number, month: number, day: number) { + this.now = new Date(year, month, day) + this.pickDate?.setFullYear(year) + this.pickDate?.setMonth(month) + this.pickDate?.setDate(day) + this._update() + } + + private _setTimePick(isIntoView = true) { + const hour = this.pickDate?.getHours() || 0 + const minute = this.pickDate?.getMinutes() || 0 + const second = this.pickDate?.getSeconds() || 0 + const { hour: hourDom, minute: minuteDom, second: secondDom } = this.dom.time + const timeDomList = [hourDom, minuteDom, secondDom] + // 清空 + timeDomList.forEach(timeDom => { + timeDom.querySelectorAll('li') + .forEach(li => li.classList.remove('active')) + }) + const pickList: [HTMLOListElement, number][] = [[hourDom, hour], [minuteDom, minute], [secondDom, second]] + pickList.forEach(([dom, time]) => { + const pickDom = dom.querySelector(`[data-id='${time}']`)! + pickDom.classList.add('active') + if (isIntoView) { + pickDom.scrollIntoView() + } + }) + } + private _preMonth() { this.now.setMonth(this.now.getMonth() - 1) this._update() @@ -314,8 +393,8 @@ export class DatePicker { } private _now() { - this.now = new Date() - this._update() + this.pickDate = new Date() + this.dispose() } private _toggleVisible(isVisible: boolean) { @@ -328,7 +407,7 @@ export class DatePicker { public render(option: IRenderOption) { this.renderOptions = option - this._setNow() + this._setValue() this._update() this._setPosition() this.isDatePicker = true @@ -338,7 +417,7 @@ export class DatePicker { public dispose() { this._toggleVisible(false) - return this.now + return this.pickDate } } \ No newline at end of file diff --git a/src/editor/core/event/CanvasEvent.ts b/src/editor/core/event/CanvasEvent.ts index 3f8793e..df33b05 100644 --- a/src/editor/core/event/CanvasEvent.ts +++ b/src/editor/core/event/CanvasEvent.ts @@ -527,7 +527,7 @@ export class CanvasEvent { return } const activeControl = this.control.getActiveControl() - const { TEXT, HYPERLINK, SUBSCRIPT, SUPERSCRIPT } = ElementType + const { TEXT, HYPERLINK, SUBSCRIPT, SUPERSCRIPT, DATE } = ElementType const text = data.replaceAll(`\n`, ZERO) const elementList = this.draw.getElementList() const agentDom = this.cursor.getAgentDom() @@ -553,6 +553,7 @@ export class CanvasEvent { element.type === TEXT || (!element.type && element.value !== ZERO) || (element.type === HYPERLINK && nextElement?.type === HYPERLINK) + || (element.type === DATE && nextElement?.type === DATE) || (element.type === SUBSCRIPT && nextElement?.type === SUBSCRIPT) || (element.type === SUPERSCRIPT && nextElement?.type === SUPERSCRIPT) ) { diff --git a/src/editor/dataset/constant/Element.ts b/src/editor/dataset/constant/Element.ts index b1d59fd..4725e30 100644 --- a/src/editor/dataset/constant/Element.ts +++ b/src/editor/dataset/constant/Element.ts @@ -24,7 +24,9 @@ export const EDITOR_ELEMENT_COPY_ATTR: Array = [ 'strikeout', 'rowFlex', 'url', - 'hyperlinkId' + 'hyperlinkId', + 'dateId', + 'dateFormat' ] export const EDITOR_ELEMENT_ZIP_ATTR: Array = [