77 >
88 <!-- 文案-->
99 <view class =" wd-picker__field" @click =" showPopup" >
10- <slot v-if =" useDefaultSlot " ></slot >
10+ <slot v-if =" $slots.default " ></slot >
1111 <view v-else :class =" ['wd-picker__cell', customCellClass]" >
1212 <view
13- v-if =" label || useLabelSlot "
13+ v-if =" label || $slots.label "
1414 :class =" `wd-picker__label ${customLabelClass} ${isRequired ? 'is-required' : ''}`"
1515 :style =" labelWidth ? 'min-width:' + labelWidth + ';max-width:' + labelWidth + ';' : ''"
1616 >
17- <block v-if =" label" >{{ label }}</ block >
18- <slot v-else name = " label" ></ slot >
17+ <slot v-if =" $slots. label" name = " label" ></ slot >
18+ <block v-else >{{ label }}</ block >
1919 </view >
2020 <view class =" wd-picker__body" >
2121 <view class =" wd-picker__value-wraper" >
@@ -319,33 +319,105 @@ const isRequired = computed(() => {
319319})
320320
321321/**
322- * @description 自定义列项筛选规则,对每列单项进行禁用校验,最终返回传入PickerView的columns数组
323- * @param {Component} picker datetimePickerView对象
324- * @return {Array} columns
322+ * @description 处理时间边界值判断
323+ * @param isStart 是否是开始时间
324+ * @param columnType 当前列类型
325+ * @param value 当前值
326+ * @param currentArray 当前完整选择的数组
327+ * @param boundary 边界值数组
328+ * @returns 是否超出边界
325329 */
326- const customColumnFormatter: DatetimePickerViewColumnFormatter = (picker ) => {
327- if (! picker ) {
328- return []
330+ function handleBoundaryValue(
331+ isStart : boolean ,
332+ columnType : DatetimePickerViewColumnType ,
333+ value : number ,
334+ currentArray : number [],
335+ boundary : number []
336+ ): boolean {
337+ const { type } = props
338+
339+ switch (type ) {
340+ case ' datetime' : {
341+ const [year, month, date, hour, minute] = boundary
342+ if (columnType === ' year' ) {
343+ return isStart ? value > year : value < year
344+ }
345+ if (columnType === ' month' && currentArray [0 ] === year ) {
346+ return isStart ? value > month : value < month
347+ }
348+ if (columnType === ' date' && currentArray [0 ] === year && currentArray [1 ] === month ) {
349+ return isStart ? value > date : value < date
350+ }
351+ if (columnType === ' hour' && currentArray [0 ] === year && currentArray [1 ] === month && currentArray [2 ] === date ) {
352+ return isStart ? value > hour : value < hour
353+ }
354+ if (columnType === ' minute' && currentArray [0 ] === year && currentArray [1 ] === month && currentArray [2 ] === date && currentArray [3 ] === hour ) {
355+ return isStart ? value > minute : value < minute
356+ }
357+ break
358+ }
359+ case ' year-month' : {
360+ const [year, month] = boundary
361+ if (columnType === ' year' ) {
362+ return isStart ? value > year : value < year
363+ }
364+ if (columnType === ' month' && currentArray [0 ] === year ) {
365+ return isStart ? value > month : value < month
366+ }
367+ break
368+ }
369+ case ' year' : {
370+ const [year] = boundary
371+ if (columnType === ' year' ) {
372+ return isStart ? value > year : value < year
373+ }
374+ break
375+ }
376+ case ' date' : {
377+ const [year, month, date] = boundary
378+ if (columnType === ' year' ) {
379+ return isStart ? value > year : value < year
380+ }
381+ if (columnType === ' month' && currentArray [0 ] === year ) {
382+ return isStart ? value > month : value < month
383+ }
384+ if (columnType === ' date' && currentArray [0 ] === year && currentArray [1 ] === month ) {
385+ return isStart ? value > date : value < date
386+ }
387+ break
388+ }
389+ case ' time' : {
390+ const [hour, minute] = boundary
391+ if (columnType === ' hour' ) {
392+ return isStart ? value > hour : value < hour
393+ }
394+ if (columnType === ' minute' && currentArray [0 ] === hour ) {
395+ return isStart ? value > minute : value < minute
396+ }
397+ break
398+ }
329399 }
400+ return false
401+ }
402+
403+ /**
404+ * @description 自定义列项筛选规则
405+ */
406+ const customColumnFormatter: DatetimePickerViewColumnFormatter = (picker ) => {
407+ if (! picker ) return []
408+
330409 const { type } = props
331410 const { startSymbol, formatter } = picker
332- // 校准上下方picker的value值,与内部innerValue对应
333411 const start = picker .correctValue (innerValue .value )
334412 const end = picker .correctValue (endInnerValue .value )
335413
336- /**
337- * 如果是上方picekr 那么将下方picker的值作为下边界
338- * 如果是下方picekr 那么将上方picker的值作为上边界
339- */
340414 const currentValue = startSymbol ? picker .getPickerValue (start , type ) : picker .getPickerValue (end , type )
341415 const boundary = startSymbol ? picker .getPickerValue (end , type ) : picker .getPickerValue (start , type )
342- // 获取当前picekr中的源列数组
343416 const columns = picker .getOriginColumns ()
344417
345- // 此时index是最外层知道当前的索引即可得到当前是哪个时间段
346- return columns .map ((column , cIndex ) => {
418+ return columns .map ((column , _ ) => {
347419 return column .values .map ((value ) => {
348- const disabled = columnDisabledRules (startSymbol , columns , cIndex , value , currentValue , boundary )
420+ const disabled = handleBoundaryValue (startSymbol , column . type , value , currentValue , boundary )
349421 return {
350422 label: formatter ? formatter (column .type , padZero (value )) : padZero (value ),
351423 value ,
@@ -415,9 +487,6 @@ function close() {
415487 onCancel ()
416488}
417489
418- /**
419- * @description 展示popup,小程序有个bug,在picker-view弹出时设置value,会触发change事件,而且会将picker-view的value多次触发change重置为第一项
420- */
421490function showPopup() {
422491 if (props .disabled || props .readonly ) return
423492
@@ -450,15 +519,34 @@ function tabChange() {
450519 * @description datetimePickerView change 事件
451520 */
452521function onChangeStart({ value }: { value: number | string }) {
453- innerValue .value = deepClone (value )
522+ if (! datetimePickerView .value ) return
523+ if (region .value && ! datetimePickerView1 .value ) return
524+
454525 if (region .value ) {
455- showTabLabel .value = [setTabLabel (), deepClone (showTabLabel .value [1 ])]
456- emit (' change' , {
457- value: [value , endInnerValue .value ]
526+ // 区间选择才需要处理边界值
527+ const currentArray = datetimePickerView .value .getPickerValue (value , props .type )
528+ const boundaryArray = datetimePickerView .value .getPickerValue (endInnerValue .value , props .type )
529+ const columns = datetimePickerView .value .getOriginColumns ()
530+
531+ // 检查是否有任何列超出边界
532+ const needsAdjust = columns .some ((column , index ) => {
533+ return handleBoundaryValue (true , column .type , currentArray [index ], currentArray , boundaryArray )
534+ })
535+
536+ innerValue .value = deepClone (needsAdjust ? endInnerValue .value : value )
537+
538+ nextTick (() => {
539+ showTabLabel .value = [setTabLabel (), deepClone (showTabLabel .value [1 ])]
540+ emit (' change' , {
541+ value: [innerValue .value , endInnerValue .value ]
542+ })
543+ // 更新两个picker的列
544+ datetimePickerView .value && datetimePickerView .value .setColumns (datetimePickerView .value .updateColumns ())
545+ datetimePickerView1 .value && datetimePickerView1 .value .setColumns (datetimePickerView1 .value .updateColumns ())
458546 })
459- datetimePickerView .value && datetimePickerView .value .setColumns (datetimePickerView .value .updateColumns ())
460- datetimePickerView1 .value && datetimePickerView1 .value .setColumns (datetimePickerView1 .value .updateColumns ())
461547 } else {
548+ // 非区间选择直接设置值即可
549+ innerValue .value = deepClone (value )
462550 emit (' change' , {
463551 value: innerValue .value
464552 })
@@ -469,13 +557,28 @@ function onChangeStart({ value }: { value: number | string }) {
469557 * @description 区域选择 下方 datetimePickerView change 事件
470558 */
471559function onChangeEnd({ value }: { value: number | string }) {
472- endInnerValue .value = deepClone (value )
473- showTabLabel .value = [deepClone (showTabLabel .value [0 ]), setTabLabel (1 )]
474- emit (' change' , {
475- value: [innerValue .value , value ]
560+ if (! datetimePickerView .value || ! datetimePickerView1 .value ) return
561+
562+ const currentArray = datetimePickerView1 .value .getPickerValue (value , props .type )
563+ const boundaryArray = datetimePickerView1 .value .getPickerValue (innerValue .value , props .type )
564+ const columns = datetimePickerView1 .value .getOriginColumns ()
565+
566+ // 检查是否有任何列超出边界
567+ const needsAdjust = columns .some ((column , index ) => {
568+ return handleBoundaryValue (false , column .type , currentArray [index ], currentArray , boundaryArray )
569+ })
570+
571+ endInnerValue .value = deepClone (needsAdjust ? innerValue .value : value )
572+
573+ nextTick (() => {
574+ showTabLabel .value = [deepClone (showTabLabel .value [0 ]), setTabLabel (1 )]
575+ emit (' change' , {
576+ value: [innerValue .value , endInnerValue .value ]
577+ })
578+ // 更新两个picker的列
579+ datetimePickerView .value && datetimePickerView .value .setColumns (datetimePickerView .value .updateColumns ())
580+ datetimePickerView1 .value && datetimePickerView1 .value .setColumns (datetimePickerView1 .value .updateColumns ())
476581 })
477- datetimePickerView .value && datetimePickerView .value .setColumns (datetimePickerView .value .updateColumns ())
478- datetimePickerView1 .value && datetimePickerView1 .value .setColumns (datetimePickerView1 .value .updateColumns ())
479582}
480583
481584/**
@@ -620,11 +723,6 @@ function defaultDisplayFormat(items: Record<string, any>[], tabLabel: boolean =
620723
621724 // 如果使用了自定义的的formatter,defaultDisplayFormat无效
622725 if (props .formatter ) {
623- /**
624- * 不建议使用 this.picker.picker.getLabels() 拉取
625- * 在初始展示时,需要使用模拟 nextTick 来等待内部 pickerView 渲染后labels才可得到format后的labels
626- * 但使用模拟nextTick会造成页面延迟展示问题,对用户感知来讲不友好,因此不适用该方法
627- */
628726 const typeMaps = {
629727 year: [' year' ],
630728 datetime: [' year' , ' month' , ' date' , ' hour' , ' minute' ],
@@ -653,100 +751,6 @@ function defaultDisplayFormat(items: Record<string, any>[], tabLabel: boolean =
653751 }
654752}
655753
656- /**
657- * @description 区域选择time禁用规则,根据传入的位置标志以及日期类型 返回该节点是否禁用
658- * @param {Boolean} isStart 时间段类型 true:start | false:end
659- * @param {Array} column 当前遍历到的列数组
660- * @param {Number} cindex 外层column的索引(对应每一个类型)
661- * @param {Number / String} value 遍历到的当前值
662- * @param {Array} currentValue 当前选中的值 this.pickerValue
663- * @param {Array} boundary 当前变量的限制值,决定禁用的边界值
664- * @return {Boolean} disabled
665- */
666- function columnDisabledRules(
667- isStart : boolean ,
668- columns : {
669- type: DatetimePickerViewColumnType
670- values: number []
671- }[],
672- cIndex : number ,
673- value : number ,
674- currentValue : number [],
675- boundary : number []
676- ) {
677- const { type } = props
678- // 0年 1月 2日 3時 4分
679- // startPicker 除最小值外 还需要有一个时间限制, endPicker 时间选择后, startPicker 的 添加一个时间限制boundary min->boundary
680- // endPicker 除最小值外 还需要有一个时间限制, startPicker 时间选择后, endPicker 的 添加一个时间限制boundary boundary->max
681- const column = columns [cIndex ]
682- // 根据当前选择年确认 ranges[0][0] minYear ranges[0][1] maxYear 以此类推
683- if (type === ' datetime' ) {
684- const year = boundary [0 ]
685- const month = boundary [1 ]
686- const date = boundary [2 ]
687- const hour = boundary [3 ]
688- const minute = boundary [4 ]
689-
690- if (column .type === ' year' ) {
691- return isStart ? value > year : value < year
692- }
693- if (column .type === ' month' && currentValue [0 ] === year ) {
694- return isStart ? value > month : value < month
695- }
696- if (column .type === ' date' && currentValue [0 ] === year && currentValue [1 ] === month ) {
697- return isStart ? value > date : value < date
698- }
699- if (column .type === ' hour' && currentValue [0 ] === year && currentValue [1 ] === month && currentValue [2 ] === date ) {
700- return isStart ? value > hour : value < hour
701- }
702- if (column .type === ' minute' && currentValue [0 ] === year && currentValue [1 ] === month && currentValue [2 ] === date && currentValue [3 ] === hour ) {
703- return isStart ? value > minute : value < minute
704- }
705- } else if (type === ' year-month' ) {
706- const year = boundary [0 ]
707- const month = boundary [1 ]
708-
709- if (column .type === ' year' ) {
710- return isStart ? value > year : value < year
711- }
712- if (column .type === ' month' && currentValue [0 ] === year ) {
713- return isStart ? value > month : value < month
714- }
715- } else if (type === ' year' ) {
716- const year = boundary [0 ]
717-
718- if (column .type === ' year' ) {
719- return isStart ? value > year : value < year
720- }
721- } else if (type === ' date' ) {
722- const year = boundary [0 ]
723- const month = boundary [1 ]
724- const date = boundary [2 ]
725-
726- if (column .type === ' year' ) {
727- return isStart ? value > year : value < year
728- }
729- if (column .type === ' month' && currentValue [0 ] === year ) {
730- return isStart ? value > month : value < month
731- }
732- if (column .type === ' date' && currentValue [0 ] === year && currentValue [1 ] === month ) {
733- return isStart ? value > date : value < date
734- }
735- } else if (type === ' time' ) {
736- const hour = boundary [0 ]
737- const minute = boundary [1 ]
738-
739- if (column .type === ' hour' ) {
740- return isStart ? value > hour : value < hour
741- }
742- if (column .type === ' minute' && currentValue [0 ] === hour ) {
743- return isStart ? value > minute : value < minute
744- }
745- }
746-
747- return false
748- }
749-
750754function setLoading(loading : boolean ) {
751755 isLoading .value = loading
752756}
0 commit comments