From b481f6fb229f1ab26a999f41ca15fd2608682c79 Mon Sep 17 00:00:00 2001 From: Marvin Date: Tue, 17 Aug 2021 09:00:45 +0800 Subject: [PATCH 1/8] =?UTF-8?q?feat:=20today=E6=8C=89=E9=92=AE=E4=B8=8E?= =?UTF-8?q?=E4=BA=8B=E4=BB=B6=E4=BA=A4=E4=BA=92?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- devui/date-picker/components/panel/index.scss | 8 +++++++- devui/date-picker/components/panel/index.tsx | 12 +++++++++--- .../date-picker/components/today-default/index.tsx | 13 +++++++++++++ devui/date-picker/components/types.ts | 4 +++- devui/date-picker/date-picker.tsx | 11 +++++++++++ sites/components/date-picker/index.md | 4 ++-- 6 files changed, 45 insertions(+), 7 deletions(-) create mode 100644 devui/date-picker/components/today-default/index.tsx diff --git a/devui/date-picker/components/panel/index.scss b/devui/date-picker/components/panel/index.scss index 57ae53ec..c6354cb6 100644 --- a/devui/date-picker/components/panel/index.scss +++ b/devui/date-picker/components/panel/index.scss @@ -13,7 +13,6 @@ $panel-cell-active-hover-color: #ffffff; .devui-calendar-panel { width: $panel-width; - height: $panel-height; padding: $panel-padding; box-sizing: border-box; overflow: hidden; @@ -75,4 +74,11 @@ $panel-cell-active-hover-color: #ffffff; cursor: pointer; list-style: none; } + + .today-container { + padding: 8px 14px; + display: flex; + flex-direction: row; + justify-content: flex-end; + } } diff --git a/devui/date-picker/components/panel/index.tsx b/devui/date-picker/components/panel/index.tsx index fdef8292..def35d5d 100644 --- a/devui/date-picker/components/panel/index.tsx +++ b/devui/date-picker/components/panel/index.tsx @@ -2,6 +2,7 @@ import { TDatePanelProps } from '../types' import { getMonthWeeklyDays, WEEK_DAYS } from '../utils' import { handleDateEnter, cellClassName, trigEvent } from '../helper' import Toolbar from '../toolbar' +import TodayDefault from '../today-default' import './index.scss' const CalendarDatePanel = (props: TDatePanelProps) => { @@ -28,14 +29,19 @@ const CalendarDatePanel = (props: TDatePanelProps) => { row.map(day => { return ( trigEvent(props as TDatePanelProps, day)} - onMouseenter={() => handleDateEnter(props as TDatePanelProps, day)} + class={cellClassName(props, day)} + onClick={() => trigEvent(props, day)} + onMouseenter={() => handleDateEnter(props, day)} >{day.date.getDate()} ) }) }) } + {props.type !== 'range' && props.showToday ? (
+ { + typeof props.onToday === 'function' && props.onToday(today, 0) + }} /> +
) : null} ) } diff --git a/devui/date-picker/components/today-default/index.tsx b/devui/date-picker/components/today-default/index.tsx new file mode 100644 index 00000000..c9056918 --- /dev/null +++ b/devui/date-picker/components/today-default/index.tsx @@ -0,0 +1,13 @@ +const TodayDefault = (props: { onSelected?: (date: Date) => void; }) => { + const { onSelected = () => 0 } = props + return ( + + ) +} + +export default TodayDefault \ No newline at end of file diff --git a/devui/date-picker/components/types.ts b/devui/date-picker/components/types.ts index 66db1520..df82dcfc 100644 --- a/devui/date-picker/components/types.ts +++ b/devui/date-picker/components/types.ts @@ -38,16 +38,18 @@ export type TDatePanelEventProps = TDateToolbarEventProps & { onSelectStart?: TEventCallback onSelectEnd?: TEventCallback onSelecting?: TEventCallback + onToday?: TEventCallback onChange?: (type: TDatePanelType, config: TDateSelectingBase) => void } export type TDatePanelDataProps = TDateToolbarDataProps & TDateSelectingBase -export type TDatePanelProps = TDatePanelDataProps & TDatePanelEventProps +export type TDatePanelProps = { showToday?: boolean; } & TDatePanelDataProps & TDatePanelEventProps export type TProps = ({ type: 'select' + showToday?: boolean } | { type: 'range' next: Date diff --git a/devui/date-picker/date-picker.tsx b/devui/date-picker/date-picker.tsx index c8285aca..f62dbea9 100644 --- a/devui/date-picker/date-picker.tsx +++ b/devui/date-picker/date-picker.tsx @@ -30,6 +30,7 @@ export default defineComponent({ attachInputDom: { type: String }, dateMin: { type: String }, dateMax: { type: String }, + showToday: { type: Boolean, default: false }, }, setup(props, ctx) { @@ -132,6 +133,7 @@ export default defineComponent({ { + state.current = date + state.start = date + const output = setBindingDom() + invokeFunction(props.selectedDateChange, output) + if (props.autoClose) { + state.show = false + } + }} onSelected={(date: Date) => state.start = date} onSelectStart={(date: Date) => state.start = date} onSelectEnd={(date: Date) => state.end = date} diff --git a/sites/components/date-picker/index.md b/sites/components/date-picker/index.md index 84dd4a5a..65296b55 100644 --- a/sites/components/date-picker/index.md +++ b/sites/components/date-picker/index.md @@ -78,11 +78,11 @@ export default defineComponent({ #### 最简
- +
```jsx - + ``` #### 区域选择 -- Gitee From ef5038d47450fb8e5e9d9253591ea861cfc318d2 Mon Sep 17 00:00:00 2001 From: mrundef Date: Tue, 17 Aug 2021 09:27:45 +0800 Subject: [PATCH 2/8] =?UTF-8?q?fix:=20DatePicker=E7=9A=84demo=E6=9B=B4?= =?UTF-8?q?=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sites/components/date-picker/index.md | 29 ++++++++++++++++++++++++--- 1 file changed, 26 insertions(+), 3 deletions(-) diff --git a/sites/components/date-picker/index.md b/sites/components/date-picker/index.md index 65296b55..1f272cfb 100644 --- a/sites/components/date-picker/index.md +++ b/sites/components/date-picker/index.md @@ -94,6 +94,8 @@ export default defineComponent({ ``` +**在区域选择`type=range`模式下,设置显示当日按钮`show-today`无效。** + ### 区间限制
@@ -118,16 +120,37 @@ export default defineComponent({ 暂定通过`querySelector`查找节点,绑定真实`dom`节点。此方案待定。 ```jsx + + +``` +
- - + +
+ + +```jsx + + ```
-- Gitee From e17a393b5571e23efbbcc05b6e305b6888204009 Mon Sep 17 00:00:00 2001 From: Marvin Date: Thu, 19 Aug 2021 08:51:22 +0800 Subject: [PATCH 4/8] =?UTF-8?q?feat:=20=E5=A2=9E=E5=8A=A0=E6=97=A5?= =?UTF-8?q?=E6=9C=9F=E6=AF=94=E8=BE=83=E6=96=B9=E6=B3=95=EF=BC=8C=E4=B8=BA?= =?UTF-8?q?=E9=85=8D=E7=BD=AE=E5=A4=8D=E6=9D=82=E9=80=BB=E8=BE=91=E5=81=9A?= =?UTF-8?q?=E5=87=86=E5=A4=87=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- devui/date-picker/components/utils.ts | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/devui/date-picker/components/utils.ts b/devui/date-picker/components/utils.ts index cb2c02a5..dcd26b4d 100644 --- a/devui/date-picker/components/utils.ts +++ b/devui/date-picker/components/utils.ts @@ -146,4 +146,14 @@ const _parseInt = (str: any, dftVal?: number) => { export const parseTime = (str?: string) : [number, number, number, number] => { const [h, m, s, ms] = str.split(/[\:\.]+/) return [_parseInt(h, 0), _parseInt(m, 0), _parseInt(s, 0), _parseInt(ms, 0)] -} \ No newline at end of file +} + +export const compareDateSort = (d1: Date, d2: Date) => { + const t1 = d1.getTime(), t2 = d2.getTime() + return t1 < t2 ? -1 : t1 > t2 ? 1 : 0 +} +export const borderDateFactory = (factor: (d1: Date, d2: Date) => Date) => (...ds: Date[]) => { + return ds.length < 2 ? ds[0] || new Date() : ds.reduce((r, v) => factor(r, v)) +} +export const getMinDate = borderDateFactory((d1: Date, d2: Date) => compareDateSort(d1, d2) < 0 ? d1 : d2) +export const getMaxDate = borderDateFactory((d1: Date, d2: Date) => compareDateSort(d1, d2) < 0 ? d2 : d1) \ No newline at end of file -- Gitee From e24172553ba4d0491d92ecf05f7990b99d22bd47 Mon Sep 17 00:00:00 2001 From: mrundef Date: Thu, 19 Aug 2021 09:14:05 +0800 Subject: [PATCH 5/8] =?UTF-8?q?fix:=20=E8=AF=AF=E5=88=A0=E9=99=A4=E9=80=BB?= =?UTF-8?q?=E8=BE=91=E6=81=A2=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- devui/date-picker/components/panel/index.tsx | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/devui/date-picker/components/panel/index.tsx b/devui/date-picker/components/panel/index.tsx index def35d5d..c9aaaab3 100644 --- a/devui/date-picker/components/panel/index.tsx +++ b/devui/date-picker/components/panel/index.tsx @@ -37,11 +37,13 @@ const CalendarDatePanel = (props: TDatePanelProps) => { }) }) } - {props.type !== 'range' && props.showToday ? (
- { - typeof props.onToday === 'function' && props.onToday(today, 0) - }} /> -
) : null} + {props.type !== 'range' ? ( +
+ { + typeof props.onToday === 'function' && props.onToday(today, 0) + }} /> +
+ ) : null} ) } -- Gitee From 6e81b6d96c392b84044b44e0d6695d38afd4ff18 Mon Sep 17 00:00:00 2001 From: mrundef Date: Thu, 19 Aug 2021 10:34:43 +0800 Subject: [PATCH 6/8] =?UTF-8?q?feat:=20today=E7=BB=84=E4=BB=B6=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0`=E7=A6=81=E7=94=A8`=E5=B1=9E=E6=80=A7=EF=BC=8C?= =?UTF-8?q?=E5=A4=84=E7=90=86`=E5=BD=93=E5=A4=A9=E6=97=B6=E9=97=B4`?= =?UTF-8?q?=E4=B8=8D=E5=9C=A8=E6=97=A5=E6=9C=9F=E9=99=90=E5=AE=9A=E8=8C=83?= =?UTF-8?q?=E5=9B=B4=E5=86=85=E7=9A=84=E6=83=85=E5=86=B5=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- devui/date-picker/components/panel/index.tsx | 14 +++++++----- .../components/today-default/index.tsx | 22 ++++++++++++------- 2 files changed, 22 insertions(+), 14 deletions(-) diff --git a/devui/date-picker/components/panel/index.tsx b/devui/date-picker/components/panel/index.tsx index c9aaaab3..71526888 100644 --- a/devui/date-picker/components/panel/index.tsx +++ b/devui/date-picker/components/panel/index.tsx @@ -1,11 +1,12 @@ import { TDatePanelProps } from '../types' -import { getMonthWeeklyDays, WEEK_DAYS } from '../utils' +import { getMonthWeeklyDays, WEEK_DAYS, betweenDate } from '../utils' import { handleDateEnter, cellClassName, trigEvent } from '../helper' import Toolbar from '../toolbar' import TodayDefault from '../today-default' import './index.scss' const CalendarDatePanel = (props: TDatePanelProps) => { + const today = new Date() return (
{ row.map(day => { return ( trigEvent(props, day)} onMouseenter={() => handleDateEnter(props, day)} >{day.date.getDate()} @@ -38,11 +39,12 @@ const CalendarDatePanel = (props: TDatePanelProps) => { }) } {props.type !== 'range' ? ( -
- { + { typeof props.onToday === 'function' && props.onToday(today, 0) - }} /> -
+ }} + /> ) : null}
) diff --git a/devui/date-picker/components/today-default/index.tsx b/devui/date-picker/components/today-default/index.tsx index c9056918..9ed09cbf 100644 --- a/devui/date-picker/components/today-default/index.tsx +++ b/devui/date-picker/components/today-default/index.tsx @@ -1,12 +1,18 @@ -const TodayDefault = (props: { onSelected?: (date: Date) => void; }) => { - const { onSelected = () => 0 } = props +type TProps = { + onSelected?: (date: Date) => void + disabled?: boolean +} + +const TodayDefault = (props: TProps) => { + const { onSelected = () => 0, disabled = false } = props return ( - +
+ +
) } -- Gitee From 5abe29fa329ec6934a0e6caa670639f8baeb2d60 Mon Sep 17 00:00:00 2001 From: mrundef Date: Thu, 19 Aug 2021 10:51:11 +0800 Subject: [PATCH 7/8] =?UTF-8?q?fix:=20=E8=B7=A8=E6=9C=88=E6=97=A5=E6=9C=9F?= =?UTF-8?q?=E9=80=89=E6=8B=A9=E7=9A=84=E4=BA=A4=E4=BA=92=E9=80=BB=E8=BE=91?= =?UTF-8?q?=E6=95=B4=E7=90=86=EF=BC=9A=201.=20=E9=9D=9E=E5=BD=93=E6=9C=88?= =?UTF-8?q?=E6=97=A5=E6=9C=9F=E5=8F=AF=E9=80=89=EF=BC=8C=E6=97=A5=E6=9C=9F?= =?UTF-8?q?=E5=8C=BA=E9=97=B4=E5=A4=96=E7=A6=81=E9=80=89=EF=BC=9B=202.=20?= =?UTF-8?q?=E5=8C=BA=E5=9F=9F=E9=80=89=E6=8B=A9=EF=BC=8C=E5=9C=A8=E9=80=89?= =?UTF-8?q?=E6=8B=A9=E7=BB=93=E6=9D=9F=E5=90=8E=EF=BC=8C=E9=87=8D=E6=96=B0?= =?UTF-8?q?=E6=95=B4=E7=90=86=E6=9C=88=E4=BB=BD=E4=BA=A4=E9=94=99=E7=9A=84?= =?UTF-8?q?=E6=98=BE=E7=A4=BA=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- devui/date-picker/components/helper.ts | 18 +++-- devui/date-picker/components/panel/index.scss | 23 ++++++- devui/date-picker/components/utils.ts | 33 ++++++++- devui/date-picker/date-picker.tsx | 69 +++++++++++++------ 4 files changed, 108 insertions(+), 35 deletions(-) diff --git a/devui/date-picker/components/helper.ts b/devui/date-picker/components/helper.ts index a756d082..805d977b 100644 --- a/devui/date-picker/components/helper.ts +++ b/devui/date-picker/components/helper.ts @@ -1,4 +1,4 @@ -import { invokeCallback, subDateDay } from './utils' +import { invokeCallback, subDateDay, betweenDate } from './utils' import { TDateCell, TDatePanelDataProps, TDatePanelProps } from './types' export const getDateKey = (date: Date): string => { @@ -6,16 +6,13 @@ export const getDateKey = (date: Date): string => { } export const cellClassName = (props: TDatePanelDataProps, day: TDateCell, base = 'cell'): string => { - if(day.current !== 0) { - return `${base} disabled` - } - const { dateMin, dateMax } = props - if(dateMin && subDateDay(day.date, dateMin) < 0) { - return `${base} disabled` - } - if(dateMax && subDateDay(dateMax, day.date) < 0) { + + if(!betweenDate(day.date, props.dateMin, props.dateMax)) { return `${base} disabled` + } else if(day.current !== 0) { + return `${base} not-current` } + const key = getDateKey(day.date) if (props.type === 'range') { if (props.dateStart) { @@ -40,9 +37,10 @@ export const cellClassName = (props: TDatePanelDataProps, day: TDateCell, base = } export const trigEvent = (props: TDatePanelProps, day: TDateCell): void => { - if(day.current !== 0) { + if(!betweenDate(day.date, props.dateMin, props.dateMax)) { return } + if (props.type === 'range') { if (!props.dateStart) { invokeCallback(props.onSelectStart, day.date) diff --git a/devui/date-picker/components/panel/index.scss b/devui/date-picker/components/panel/index.scss index c6354cb6..9fb2adae 100644 --- a/devui/date-picker/components/panel/index.scss +++ b/devui/date-picker/components/panel/index.scss @@ -54,9 +54,14 @@ $panel-cell-active-hover-color: #ffffff; background-color: $devui-disabled-bg; } - &.disabled { + &.disabled, + &.not-current { color: $devui-disabled-text; } + + &.disabled { + cursor: not-allowed; + } } } @@ -76,9 +81,23 @@ $panel-cell-active-hover-color: #ffffff; } .today-container { - padding: 8px 14px; + padding: 8px 8px; display: flex; flex-direction: row; justify-content: flex-end; + + &.disabled { + .today-button { + border: 1px solid #cccccc; + cursor: not-allowed; + } + } + + .today-button { + border: 1px solid #0066cc; + border-radius: 3px; + padding: 2px 20px; + font-size: 12px; + } } } diff --git a/devui/date-picker/components/utils.ts b/devui/date-picker/components/utils.ts index dcd26b4d..23150961 100644 --- a/devui/date-picker/components/utils.ts +++ b/devui/date-picker/components/utils.ts @@ -148,12 +148,39 @@ export const parseTime = (str?: string) : [number, number, number, number] => { return [_parseInt(h, 0), _parseInt(m, 0), _parseInt(s, 0), _parseInt(ms, 0)] } -export const compareDateSort = (d1: Date, d2: Date) => { - const t1 = d1.getTime(), t2 = d2.getTime() +type TDateCounterType = 'd' | 'm' | 'y' + +export const compareDateSort = (d1: Date, d2: Date, type: TDateCounterType = 'd') => { + const t1 = dateCounter(d1, type), t2 = dateCounter(d2, type) return t1 < t2 ? -1 : t1 > t2 ? 1 : 0 } + +export const dateCounter = (date: Date, type: TDateCounterType) => { + switch(type) { + case 'y': return date.getFullYear() + case 'm': return date.getFullYear() * 12 + date.getMonth() + } + return date.getTime() / ONE_DAY >> 0 +} export const borderDateFactory = (factor: (d1: Date, d2: Date) => Date) => (...ds: Date[]) => { return ds.length < 2 ? ds[0] || new Date() : ds.reduce((r, v) => factor(r, v)) } export const getMinDate = borderDateFactory((d1: Date, d2: Date) => compareDateSort(d1, d2) < 0 ? d1 : d2) -export const getMaxDate = borderDateFactory((d1: Date, d2: Date) => compareDateSort(d1, d2) < 0 ? d2 : d1) \ No newline at end of file +export const getMaxDate = borderDateFactory((d1: Date, d2: Date) => compareDateSort(d1, d2) < 0 ? d2 : d1) + +/** + * d 是否在 [left, right] 区间 + * @param date 日期 + * @param left 最小日期 + * @param right 最大日期 + * @returns boolean + */ +export const betweenDate = (date: Date, left: any, right: any): boolean => { + if(left instanceof Date && compareDateSort(left, date, 'd') > 0) { + return false + } + if(right instanceof Date && compareDateSort(date, right, 'd') > 0) { + return false + } + return true +} \ No newline at end of file diff --git a/devui/date-picker/date-picker.tsx b/devui/date-picker/date-picker.tsx index f62dbea9..4732cb51 100644 --- a/devui/date-picker/date-picker.tsx +++ b/devui/date-picker/date-picker.tsx @@ -1,8 +1,7 @@ +import type { UnwrapRef } from 'vue' import { defineComponent, reactive, onMounted, onUnmounted, ref } from 'vue' -import { - EventManager, isIn, - traceNode, invokeFunction, -} from './utils' +import { EventManager, isIn, traceNode, invokeFunction } from './utils' +import { compareDate, compareDateSort } from './components/utils' import { TState, @@ -18,6 +17,39 @@ import Calendar from './components/calendar' import './date-picker.scss' import { parseDate } from './components/utils' +const formatProps = (props: any): TState => { + const state: TState = { + range: !!props.range, + x: '0', + y: '0', + st: true, + show: false, + input: props.attachInputDom, + } + state.current = parseDate(props.dateMin) || new Date() + state.next = new Date(state.current.getFullYear(), state.current.getMonth() + 1, 1) + return state +} + +const formatRange = (state: UnwrapRef) => { + const [start, end] = [state.start, state.end].sort((a, b) => a.getTime() - b.getTime()) + + state.start = start + state.end = end + + if(compareDateSort(start, end, 'm') !== 0) { + state.current = start + state.next = end + } else { + if(compareDateSort(start, state.current) < 0) { + state.current = start + } + if(compareDateSort(state.next, end) < 0) { + state.next = end + } + } +} + export default defineComponent({ name: 'DDatepicker', props: { @@ -36,18 +68,8 @@ export default defineComponent({ const container = ref() const evtman = new EventManager() - const current = new Date() - - const state = reactive({ - range: !!props.range, - current, - next: new Date(current.getFullYear(), current.getMonth() + 1, 1), - show: false, - input: props.attachInputDom, - st: true, - x: '0', - y: '0', - }) + + const state = reactive(formatProps(props)) // 弹出层跟踪 const handlePosition = handlePositionFactory(state, props, container) @@ -133,7 +155,6 @@ export default defineComponent({ { - state.current = state.end = state.hover = undefined + state.end = state.hover = undefined state.start = date }} onChange={() => { @@ -161,9 +182,17 @@ export default defineComponent({ state.show = false } }} - onSelected={(date: Date) => state.start = date} + onSelected={(date: Date) => { + state.start = date + if(compareDateSort(state.current, date) !== 0) { + state.current = date + } + }} onSelectStart={(date: Date) => state.start = date} - onSelectEnd={(date: Date) => state.end = date} + onSelectEnd={(date: Date) => { + state.end = date + formatRange(state) + }} onSelecting={(date: Date) => state.hover = date} onPreviousYear={(date: Date, pos: number) => handleCalendarSwitchState(state, 0, pos, date)} onPreviousMonth={(date: Date, pos: number) => handleCalendarSwitchState(state, 1, pos, date)} -- Gitee From e1576cc89f971c2e7e0231ef8bebfbe091bfb3b9 Mon Sep 17 00:00:00 2001 From: mrundef Date: Thu, 19 Aug 2021 17:35:41 +0800 Subject: [PATCH 8/8] =?UTF-8?q?feat:=20=E5=BC=B9=E5=87=BA=E5=B1=82?= =?UTF-8?q?=E5=89=A5=E7=A6=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- devui/date-picker/components/popup/index.scss | 14 +++ devui/date-picker/components/popup/index.tsx | 109 ++++++++++++++++++ devui/date-picker/date-picker.scss | 11 -- devui/date-picker/date-picker.tsx | 96 ++++----------- devui/date-picker/helper.ts | 19 +-- 5 files changed, 155 insertions(+), 94 deletions(-) create mode 100644 devui/date-picker/components/popup/index.scss create mode 100644 devui/date-picker/components/popup/index.tsx diff --git a/devui/date-picker/components/popup/index.scss b/devui/date-picker/components/popup/index.scss new file mode 100644 index 00000000..d9208c50 --- /dev/null +++ b/devui/date-picker/components/popup/index.scss @@ -0,0 +1,14 @@ +.devui-datepicker-popup { + position: fixed; + left: 0; + top: 0; + width: 0; + height: 0; + background-color: rgba(0, 0, 0, 0.2); + z-index: 99; + overflow: visible; + + .popup-tracing { + position: absolute; + } +} diff --git a/devui/date-picker/components/popup/index.tsx b/devui/date-picker/components/popup/index.tsx new file mode 100644 index 00000000..f241927b --- /dev/null +++ b/devui/date-picker/components/popup/index.tsx @@ -0,0 +1,109 @@ +import { defineComponent, reactive, renderSlot, ref, useSlots, onMounted, onUnmounted, onBeforeUpdate } from 'vue' +import { EventManager, isIn, traceNode, invokeFunction } from '../../utils' +import { + handlePositionFactory, + formatValue, + formatPlaceholder, + getAttachInputDom, +} from '../../helper' + +import './index.scss' + +type TState = { + x?: string + y?: string + attachInputDom?: string + show: boolean + st: boolean +} + +export default defineComponent({ + name: 'DDatePickerPopup', + props: { + attach: { type: String }, + onBinding: { type: Function }, + onClosed: { type: Function }, + onOpen: { type: Function }, + show: { type: Boolean }, + }, + setup(props) { + + const container = ref() + const evtman = new EventManager() + const state = reactive({ + x: '0', + y: '0', + st: true, + show: !!props.show, + }) + + let el: Element | null = null + + // 弹出层跟踪 + const handlePosition = handlePositionFactory(state, props, container) + + onBeforeUpdate(() => { + state.show = !!props.show + }) + + onMounted(() => { + // 获取绑定节点(默认input) + el = getAttachInputDom(props) + // 绑定节点不存在,作为普通组件展示。 + if (!el) { + state.st = true + state.show = true + return + } else { + state.show = false + state.st = false + } + + invokeFunction(props.onBinding) + + // 绑定节点click事件处理弹出层显示 + evtman.append(el, 'click', () => { + if(!state.show) { + state.show = true + invokeFunction(props.onOpen) + } + }) + // document层处理`点击其他区域隐藏` + evtman.append(document, 'click', (e: MouseEvent) => { + if (!state.show || e.target === el || isIn(e.target as Node, container.value)) { + return + } + state.show = false + invokeFunction(props.onClosed) + // reset() + }) + // 对绑定节点做scroll跟踪,并绑定跟踪事件 + traceNode(el).forEach(node => { + evtman.append(node, 'scroll', handlePosition) + }) + }) + + onUnmounted(() => { + evtman.dispose() + }) + + return () => { + const defaultSlot = renderSlot(useSlots(), 'default') + if (state.st) { + return defaultSlot + } + handlePosition() + return ( +
+ +
+ ) + } + } +}) \ No newline at end of file diff --git a/devui/date-picker/date-picker.scss b/devui/date-picker/date-picker.scss index 26d48111..a577a993 100644 --- a/devui/date-picker/date-picker.scss +++ b/devui/date-picker/date-picker.scss @@ -5,17 +5,6 @@ $border-width: 1px; $border-style: solid; $border-color: #dddddd; -.devui-datepicker-global-viewport { - position: fixed; - left: 0; - top: 0; - width: 0; - height: 0; - background-color: rgba(0, 0, 0, 0.2); - z-index: 99; - overflow: visible; -} - .devui-datepicker-container { margin: 0; padding: 0; diff --git a/devui/date-picker/date-picker.tsx b/devui/date-picker/date-picker.tsx index 4732cb51..e6a66364 100644 --- a/devui/date-picker/date-picker.tsx +++ b/devui/date-picker/date-picker.tsx @@ -1,11 +1,11 @@ import type { UnwrapRef } from 'vue' -import { defineComponent, reactive, onMounted, onUnmounted, ref } from 'vue' -import { EventManager, isIn, traceNode, invokeFunction } from './utils' -import { compareDate, compareDateSort } from './components/utils' +import { defineComponent, reactive, onMounted } from 'vue' +import { invokeFunction } from './utils' +import { compareDateSort } from './components/utils' +import Popup from './components/popup' import { TState, - handlePositionFactory, handleCalendarSwitchState, formatValue, formatPlaceholder, @@ -20,9 +20,6 @@ import { parseDate } from './components/utils' const formatProps = (props: any): TState => { const state: TState = { range: !!props.range, - x: '0', - y: '0', - st: true, show: false, input: props.attachInputDom, } @@ -33,18 +30,18 @@ const formatProps = (props: any): TState => { const formatRange = (state: UnwrapRef) => { const [start, end] = [state.start, state.end].sort((a, b) => a.getTime() - b.getTime()) - + state.start = start state.end = end - if(compareDateSort(start, end, 'm') !== 0) { + if (compareDateSort(start, end, 'm') !== 0) { state.current = start state.next = end } else { - if(compareDateSort(start, state.current) < 0) { + if (compareDateSort(start, state.current) < 0) { state.current = start } - if(compareDateSort(state.next, end) < 0) { + if (compareDateSort(state.next, end) < 0) { state.next = end } } @@ -66,16 +63,10 @@ export default defineComponent({ }, setup(props, ctx) { - const container = ref() - const evtman = new EventManager() - const state = reactive(formatProps(props)) - // 弹出层跟踪 - const handlePosition = handlePositionFactory(state, props, container) - // 绑定层显示值、placehoder值设置 - const setBindingDom = (el: any = getAttachInputDom(state, props)) => { + const setBindingDom = (el: any = getAttachInputDom(props)) => { const value = formatValue(state, props) const placeholder = formatPlaceholder(props) @@ -92,66 +83,21 @@ export default defineComponent({ return value } - const reset = () => { - state.hover = null - state.current = null - state.next = null - if (state.start) { - if (state.end && Math.abs(state.end.getMonth() - state.start.getMonth()) > 0) { - state.next = state.end - } - } else { - state.end = null - } - } - onMounted(() => { - // 获取绑定节点(默认input) - const el = getAttachInputDom(state, props) - // 绑定节点不存在,作为普通组件展示。 - if (!el) { - // 显示组件 - state.show = true - return - } else { - // 作为弹出层,先隐藏 - state.show = false - } - - setBindingDom(el) - - // 绑定节点click事件处理弹出层显示 - evtman.append(el, 'click', () => !state.show && (state.show = true)) - // document层处理`点击其他区域隐藏` - evtman.append(document, 'click', (e: MouseEvent) => { - if (!state.show || e.target === el || isIn(e.target as Node, container.value)) { - return - } - state.show = false - reset() - }) - // 对绑定节点做scroll跟踪,并绑定跟踪事件 - traceNode(el).forEach(node => { - evtman.append(node, 'scroll', handlePosition) - }) - }) - - onUnmounted(() => { - evtman.dispose() + setBindingDom() }) return () => { - handlePosition() - setBindingDom() return ( -
-
+ state.show = true} + onClosed={() => { + state.show = false + }} + > +
{ state.start = date - if(compareDateSort(state.current, date) !== 0) { + if (compareDateSort(state.current, date) !== 0) { state.current = date } }} @@ -200,7 +146,7 @@ export default defineComponent({ onNextYear={(date: Date, pos: number) => handleCalendarSwitchState(state, 3, pos, date)} />
-
+ ) } } diff --git a/devui/date-picker/helper.ts b/devui/date-picker/helper.ts index 0bc57373..5b002481 100644 --- a/devui/date-picker/helper.ts +++ b/devui/date-picker/helper.ts @@ -10,9 +10,6 @@ export type TState = { hover?: Date show?: boolean input?: string - st?: boolean - x?: string - y?: string } /** @@ -109,8 +106,8 @@ export const handleValue = (id: string | undefined, output: string) => { * 获取绑定节点 * @returns */ -export const getAttachInputDom = (state: TState, props: any) => { - const { attachInputDom } = props || {} +export const getAttachInputDom = (props: any) => { + const { attach, attachInputDom = attach } = props || {} if (!attachInputDom || typeof attachInputDom !== 'string') { return null } @@ -118,7 +115,6 @@ export const getAttachInputDom = (state: TState, props: any) => { if (!el) { return null } - state.st = false return el } @@ -129,14 +125,21 @@ export const getAttachInputDom = (state: TState, props: any) => { * @param container * @returns */ -export const handlePositionFactory = (state: TState, props: any, container: Ref) => () => { +export const handlePositionFactory = (state: { + x?: string + y?: string + attachInputDom?: string + show?: boolean + st?: boolean +}, props: any, container: Ref) => () => { if (!state.show) { state.x = `-100%` state.y = `-100%` return } - const el = getAttachInputDom(state, props) + const el = getAttachInputDom(props) if (!el) { + state.st = true return } const { left, top, width, height } = el.getBoundingClientRect() -- Gitee