1313 @scroll =" monthScroll"
1414 :scroll-top =" scrollTop"
1515 >
16- <view v-for =" (item, index) in months(minDate, maxDate) " :key =" index" :id =" `month${index}`" >
16+ <view v-for =" (item, index) in months" :key =" index" :id =" `month${index}`" >
1717 <month
1818 :type =" type"
1919 :date =" item.date"
@@ -60,7 +60,7 @@ export default {
6060 </script >
6161
6262<script lang="ts" setup>
63- import { computed , onBeforeMount , ref , watch } from ' vue'
63+ import { computed , ref , watch , onMounted } from ' vue'
6464import { debounce , isArray , isEqual , isNumber , requestAnimationFrame } from ' ../../common/util'
6565import { compareMonth , formatMonthTitle , getMonthEndDay , getMonths , getTimeData , getWeekLabel } from ' ../utils'
6666import Month from ' ../month/month.vue'
@@ -71,13 +71,48 @@ import type { CalendarItem } from '../types'
7171const props = defineProps (monthPanelProps )
7272const { translate } = useTranslate (' calendar-view' )
7373
74- const title = ref <string >(' ' )
7574const scrollTop = ref <number >(0 ) // 滚动位置
76- const timeValue = ref <string [] | number []>([])
77- const timeData = ref <Array <CalendarItem []>>([])
75+ const scrollIndex = ref <number >(0 ) // 当前显示的月份索引
76+ const timeValue = ref <number []>([]) // 当前选中的时分秒
77+
7878const timeType = ref <MonthPanelTimeType >(' ' ) // 当前时间类型,是开始还是结束
7979const innerValue = ref <string | number | (number | null )[]>(' ' ) // 内部保存一个值,用于判断新老值,避免监听器触发
8080
81+ // 时间picker的列数据
82+ const timeData = computed <Array <CalendarItem []>>(() => {
83+ let timeColumns: Array <CalendarItem []> = []
84+ if (props .type === ' datetime' && isNumber (props .value )) {
85+ const date = new Date (props .value )
86+ date .setHours (timeValue .value [0 ])
87+ date .setMinutes (timeValue .value [1 ])
88+ date .setSeconds (props .hideSecond ? 0 : timeValue .value [2 ])
89+ const dateTime = date .getTime ()
90+ timeColumns = getTime (dateTime ) || []
91+ } else if (isArray (props .value ) && props .type === ' datetimerange' ) {
92+ const [start, end] = props .value !
93+ const dataValue = timeType .value === ' start' ? start : end
94+ const date = new Date (dataValue || ' ' )
95+ date .setHours (timeValue .value [0 ])
96+ date .setMinutes (timeValue .value [1 ])
97+ date .setSeconds (props .hideSecond ? 0 : timeValue .value [2 ])
98+ const dateTime = date .getTime ()
99+ const finalValue = [start , end ]
100+ if (timeType .value === ' start' ) {
101+ finalValue [0 ] = dateTime
102+ } else {
103+ finalValue [1 ] = dateTime
104+ }
105+ timeColumns = getTime (finalValue , timeType .value ) || []
106+ }
107+ return timeColumns
108+ })
109+
110+ // 标题
111+ const title = computed (() => {
112+ return formatMonthTitle (months .value [scrollIndex .value ].date )
113+ })
114+
115+ // 周标题
81116const weekLabel = computed (() => {
82117 return (index : number ) => {
83118 return getWeekLabel (index - 1 )
@@ -91,26 +126,23 @@ const scrollHeight = computed(() => {
91126})
92127
93128// 月份日期和月份高度
94- const months = computed (() => {
95- return (minDate : number , maxDate : number ): MonthInfo [] => {
96- let months = getMonths (minDate , maxDate ).map ((month ) => {
97- const offset = (7 + new Date (month ).getDay () - props .firstDayOfWeek ) % 7
98- const totalDay = getMonthEndDay (new Date (month ).getFullYear (), new Date (month ).getMonth () + 1 )
99- return {
100- height: (offset + totalDay > 35 ? 64 * 6 : 64 * 5 ) + 45 ,
101- date: month
102- }
103- })
104- return months
105- }
129+ const months = computed <MonthInfo []>(() => {
130+ return getMonths (props .minDate , props .maxDate ).map ((month ) => {
131+ const offset = (7 + new Date (month ).getDay () - props .firstDayOfWeek ) % 7
132+ const totalDay = getMonthEndDay (new Date (month ).getFullYear (), new Date (month ).getMonth () + 1 )
133+ return {
134+ height: (offset + totalDay > 35 ? 64 * 6 : 64 * 5 ) + 45 ,
135+ date: month
136+ }
137+ })
106138})
107139
108140watch (
109141 () => props .type ,
110142 (val ) => {
111143 if (
112144 (val === ' datetime' && props .value ) ||
113- (val === ' datetimerange' && typeof props .value === ' object ' && props .value && props .value .length > 0 && props .value [0 ])
145+ (val === ' datetimerange' && isArray ( props .value ) && props .value && props .value .length > 0 && props .value [0 ])
114146 ) {
115147 setTime (props .value , ' start' )
116148 }
@@ -126,7 +158,7 @@ watch(
126158 (val ) => {
127159 if (isEqual (val , innerValue .value )) return
128160
129- if ((props .type === ' datetime' && val ) || (props .type === ' datetimerange' && val && typeof val === ' object ' && val .length > 0 && val [0 ])) {
161+ if ((props .type === ' datetime' && val ) || (props .type === ' datetimerange' && val && isArray ( val ) && val .length > 0 && val [0 ])) {
130162 setTime (val , ' start' )
131163 }
132164 },
@@ -136,7 +168,7 @@ watch(
136168 }
137169)
138170
139- onBeforeMount (() => {
171+ onMounted (() => {
140172 scrollIntoView ()
141173})
142174
@@ -164,14 +196,12 @@ function scrollIntoView() {
164196 activeDate = Date .now ()
165197 }
166198
167- const monthsInfo = months .value (props .minDate , props .maxDate )
168-
169199 let top: number = 0
170- for (let index = 0 ; index < monthsInfo .length ; index ++ ) {
171- if (compareMonth (monthsInfo [index ].date , activeDate ) === 0 ) {
200+ for (let index = 0 ; index < months . value .length ; index ++ ) {
201+ if (compareMonth (months . value [index ].date , activeDate ) === 0 ) {
172202 break
173203 }
174- top += monthsInfo [index ] ? Number (monthsInfo [index ].height ) : 0
204+ top += months . value [index ] ? Number (months . value [index ].height ) : 0
175205 }
176206 scrollTop .value = 0
177207 requestAnimationFrame (() => {
@@ -240,9 +270,8 @@ function setTime(value: number | (number | null)[], type?: MonthPanelTimeType) {
240270 if (isArray (value ) && value [0 ] && value [1 ] && type === ' start' && timeType .value === ' start' ) {
241271 type = ' end'
242272 }
243- timeData .value = getTime (value , type ) || []
244- timeValue .value = getTimeValue (value , type || ' ' )
245273 timeType .value = type || ' '
274+ timeValue .value = getTimeValue (value , type || ' ' )
246275}
247276function handleDateChange({ value , type }: { value: number | (number | null )[]; type? : MonthPanelTimeType }) {
248277 if (! isEqual (value , props .value )) {
@@ -259,16 +288,14 @@ function handleTimeChange({ value }: { value: any[] }) {
259288 if (! props .value ) {
260289 return
261290 }
262- if (props .type === ' datetime' && typeof props .value === ' number ' ) {
291+ if (props .type === ' datetime' && isNumber ( props .value ) ) {
263292 const date = new Date (props .value )
264293 date .setHours (value [0 ])
265294 date .setMinutes (value [1 ])
266295 date .setSeconds (props .hideSecond ? 0 : value [2 ])
267296 const dateTime = date .getTime ()
268- timeData .value = getTime (dateTime ) || []
269- timeValue .value = value
270297 handleChange (dateTime )
271- } else if (typeof props .value === ' object ' ) {
298+ } else if (isArray ( props .value ) && props . type === ' datetimerange ' ) {
272299 const [start, end] = props .value !
273300 const dataValue = timeType .value === ' start' ? start : end
274301 const date = new Date (dataValue || ' ' )
@@ -285,9 +312,6 @@ function handleTimeChange({ value }: { value: any[] }) {
285312 } else {
286313 finalValue [1 ] = dateTime
287314 }
288-
289- timeData .value = getTime (finalValue , timeType .value ) || []
290- timeValue .value = value
291315 innerValue .value = finalValue // 内部保存一个值,用于判断新老值,避免监听器触发
292316 handleChange (finalValue )
293317 }
@@ -300,24 +324,23 @@ function handlePickEnd() {
300324}
301325
302326const monthScroll = (event : { detail: { scrollTop: number } }) => {
303- const monthsInfo = months .value (props .minDate , props .maxDate )
304- if (monthsInfo .length <= 1 ) {
327+ if (months .value .length <= 1 ) {
305328 return
306329 }
307330 const scrollTop = Math .max (0 , event .detail .scrollTop )
308- doSetSubtitle (scrollTop , monthsInfo )
331+ doSetSubtitle (scrollTop )
309332}
310333
311334/**
312335 * 设置小标题
313336 * scrollTop 滚动条位置
314337 */
315- function doSetSubtitle(scrollTop : number , monthsInfo : MonthInfo [] ) {
338+ function doSetSubtitle(scrollTop : number ) {
316339 let height: number = 0 // 月份高度和
317- for (let index = 0 ; index < monthsInfo .length ; index ++ ) {
318- height = height + monthsInfo [index ].height
340+ for (let index = 0 ; index < months . value .length ; index ++ ) {
341+ height = height + months . value [index ].height
319342 if (scrollTop < height + 45 ) {
320- title .value = formatMonthTitle ( monthsInfo [ index ]. date )
343+ scrollIndex .value = index
321344 return
322345 }
323346 }
0 commit comments