fix: 🐛 修复 DatetimePicker 区间选择时无法选择绑定值范围以外的时间的问题

 Closes: #1170
This commit is contained in:
不如摸鱼去 2025-07-20 21:17:08 +08:00
parent 66f796e440
commit 3c1023c9f6
4 changed files with 37 additions and 92 deletions

View File

@ -84,8 +84,7 @@ export const datetimePickerViewProps = {
/**
* picker-view的 change change 1.2.25
*/
immediateChange: makeBooleanProp(false),
startSymbol: makeBooleanProp(false)
immediateChange: makeBooleanProp(false)
}
export type DatetimePickerViewColumnType = 'year' | 'month' | 'date' | 'hour' | 'minute' | 'second'
@ -99,7 +98,7 @@ export type DatetimePickerViewFilter = (type: DatetimePickerViewColumnType, valu
export type DatetimePickerViewFormatter = (type: string, value: string) => string
export type DatetimePickerViewColumnFormatter = (picker: DatetimePickerViewInstance) => DatetimePickerViewOption[][]
export type DatetimePickerViewColumnFormatter = (picker: DatetimePickerViewExpose) => DatetimePickerViewOption[][]
export type DatetimePickerViewProps = ExtractPropTypes<typeof datetimePickerViewProps>

View File

@ -4,14 +4,15 @@ import { type DateTimeType } from './types'
* @description 便 pickerView
* @param value
* @param type picker类型
* @param useSecond 使 time datetime
*/
export function getPickerValue(value: string | number, type: DateTimeType) {
export function getPickerValue(value: string | number, type: DateTimeType, useSecond: boolean = false) {
const values: number[] = []
const date = new Date(value)
if (type === 'time') {
const pair = String(value).split(':')
values.push(parseInt(pair[0]), parseInt(pair[1]))
if (pair[2]) {
if (useSecond && pair[2]) {
values.push(parseInt(pair[2]))
}
} else {
@ -19,7 +20,10 @@ export function getPickerValue(value: string | number, type: DateTimeType) {
if (type === 'date') {
values.push(date.getDate())
} else if (type === 'datetime') {
values.push(date.getDate(), date.getHours(), date.getMinutes(), date.getSeconds())
values.push(date.getDate(), date.getHours(), date.getMinutes())
if (useSecond) {
values.push(date.getSeconds())
}
}
}
return values

View File

@ -27,7 +27,7 @@ export default {
<script lang="ts" setup>
import wdPickerView from '../wd-picker-view/wd-picker-view.vue'
import { getCurrentInstance, onBeforeMount, ref, watch } from 'vue'
import { debounce, isFunction, isDef, padZero, range, isArray, isString } from '../common/util'
import { debounce, isDef, padZero, range, isArray, isString } from '../common/util'
import { datetimePickerViewProps, type DatetimePickerViewColumnType, type DatetimePickerViewOption, type DatetimePickerViewExpose } from './types'
import type { PickerViewInstance } from '../wd-picker-view/types'
import { getPickerValue } from './util'
@ -80,7 +80,6 @@ const { proxy } = getCurrentInstance() as any
* @description updateValue 防抖函数的占位符
*/
const updateValue = debounce(() => {
// created hookobserver
if (!created.value) return
const val = correctValue(props.modelValue)
const isEqual = val === innerValue.value
@ -109,47 +108,16 @@ watch(
if (type.indexOf(target) === -1) {
console.error(`type must be one of ${type}`)
}
// type
updateValue()
},
{ deep: true, immediate: true }
)
watch(
() => props.filter,
(fn) => {
if (fn && !isFunction(fn)) {
console.error('The type of filter must be Function')
}
updateValue()
},
{ deep: true, immediate: true }
)
watch(
() => props.formatter,
(fn) => {
if (fn && !isFunction(fn)) {
console.error('The type of formatter must be Function')
}
updateValue()
},
{ deep: true, immediate: true }
)
watch(
() => props.columnFormatter,
(fn) => {
if (fn && !isFunction(fn)) {
console.error('The type of columnFormatter must be Function')
}
updateValue()
},
{ deep: true, immediate: true }
)
watch(
[
() => props.type,
() => props.filter,
() => props.formatter,
() => props.columnFormatter,
() => props.minDate,
() => props.maxDate,
() => props.minHour,
@ -392,7 +360,7 @@ function getBoundary(type: 'min' | 'max', innerValue: number) {
* @return {Array}
*/
function updateColumnValue(value: string | number) {
const values = getPickerValue(value, props.type)
const values = getPickerValue(value, props.type, props.useSecond)
// pickerViewvalue,columns
if (props.modelValue !== value) {
emit('update:modelValue', value)
@ -486,8 +454,8 @@ function columnChange(picker: PickerViewInstance) {
/** 根据计算选中项的时间戳,重新计算所有的选项列表 */
//
innerValue.value = correctValue(value)
// innerValue
// innerValue
const newColumns = updateColumns()
//
const selectedIndex = picker.getSelectedIndex().slice(0)

View File

@ -3,7 +3,6 @@
<wd-cell
v-if="!$slots.default"
:title="label"
:required="isRequired"
:size="size"
:title-width="labelWidth"
:prop="prop"
@ -101,7 +100,7 @@
:label-key="labelKey"
:formatter="formatter"
:filter="filter"
:column-formatter="isArray(modelValue) ? customColumnFormatter : undefined"
:column-formatter="isArray(modelValue) ? startColumnFormatter : undefined"
:max-hour="maxHour"
:min-hour="minHour"
:max-date="maxDate"
@ -111,7 +110,6 @@
:use-second="useSecond"
:min-second="minSecond"
:max-second="maxSecond"
:start-symbol="true"
:immediate-change="immediateChange"
@change="onChangeStart"
@pickstart="onPickStart"
@ -131,7 +129,7 @@
:label-key="labelKey"
:formatter="formatter"
:filter="filter"
:column-formatter="isArray(modelValue) ? customColumnFormatter : undefined"
:column-formatter="isArray(modelValue) ? endColumnFormatter : undefined"
:max-hour="maxHour"
:min-hour="minHour"
:max-date="maxDate"
@ -141,7 +139,6 @@
:use-second="useSecond"
:min-second="minSecond"
:max-second="maxSecond"
:start-symbol="false"
:immediate-change="immediateChange"
@change="onChangeEnd"
@pickstart="onPickStart"
@ -170,13 +167,7 @@ import wdDatetimePickerView from '../wd-datetime-picker-view/wd-datetime-picker-
import wdCell from '../wd-cell/wd-cell.vue'
import { computed, getCurrentInstance, nextTick, onBeforeMount, onMounted, ref, watch } from 'vue'
import { deepClone, isArray, isDef, isEqual, isFunction, padZero } from '../common/util'
import {
type DatetimePickerViewInstance,
type DatetimePickerViewColumnFormatter,
type DatetimePickerViewColumnType
} from '../wd-datetime-picker-view/types'
import { FORM_KEY, type FormItemRule } from '../wd-form/types'
import { useParent } from '../composables/useParent'
import { type DatetimePickerViewInstance, type DatetimePickerViewColumnType, type DatetimePickerViewExpose } from '../wd-datetime-picker-view/types'
import { useTranslate } from '../composables/useTranslate'
import { datetimePickerProps, type DatetimePickerExpose } from './types'
import dayjs from '../../dayjs'
@ -304,31 +295,6 @@ watch(
}
)
const { parent: form } = useParent(FORM_KEY)
//
const errorMessage = computed(() => {
if (form && props.prop && form.errorMessages && form.errorMessages[props.prop]) {
return form.errorMessages[props.prop]
} else {
return ''
}
})
//
const isRequired = computed(() => {
let formRequired = false
if (form && form.props.rules) {
const rules = form.props.rules
for (const key in rules) {
if (Object.prototype.hasOwnProperty.call(rules, key) && key === props.prop && Array.isArray(rules[key])) {
formRequired = rules[key].some((rule: FormItemRule) => rule.required)
}
}
}
return props.required || props.rules.some((rule) => rule.required) || formRequired
})
//
const showClear = computed(() => {
return (
@ -361,7 +327,6 @@ function handleBoundaryValue(
boundary: number[]
): boolean {
const { type, useSecond } = props
switch (type) {
case 'datetime': {
const [year, month, date, hour, minute, second] = boundary
@ -440,21 +405,28 @@ function handleBoundaryValue(
return false
}
function startColumnFormatter(picker: DatetimePickerViewExpose) {
return customColumnFormatter(picker, 'start')
}
function endColumnFormatter(picker: DatetimePickerViewExpose) {
return customColumnFormatter(picker, 'end')
}
/**
* @description 自定义列项筛选规则
*/
const customColumnFormatter: DatetimePickerViewColumnFormatter = (picker) => {
const customColumnFormatter = (picker: DatetimePickerViewExpose, pickerType: 'start' | 'end') => {
if (!picker) return []
const { type } = props
const { startSymbol, formatter } = picker
const startSymbol = pickerType === 'start'
const { formatter } = props
const start = picker.correctValue(innerValue.value)
const end = picker.correctValue(endInnerValue.value)
const currentValue = startSymbol ? getPickerValue(start, type) : getPickerValue(end, type)
const boundary = startSymbol ? getPickerValue(end, type) : getPickerValue(start, type)
const currentValue = startSymbol ? getPickerValue(start, type, props.useSecond) : getPickerValue(end, type, props.useSecond)
const boundary = startSymbol ? getPickerValue(end, type, props.useSecond) : getPickerValue(start, type, props.useSecond)
const columns = picker.getOriginColumns()
return columns.map((column, _) => {
return column.values.map((value) => {
const disabled = handleBoundaryValue(startSymbol, column.type, value, currentValue, boundary)
@ -489,7 +461,7 @@ function getSelects(picker: 'before' | 'after') {
let value = picker === 'before' ? innerValue.value : endInnerValue.value
let selected: number[] = []
if (value) {
selected = getPickerValue(value, props.type)
selected = getPickerValue(value, props.type, props.useSecond)
}
let selects = selected.map((value) => {
@ -564,8 +536,10 @@ function onChangeStart({ value }: { value: number | string }) {
if (region.value) {
//
const currentArray = getPickerValue(value, props.type)
const boundaryArray = getPickerValue(endInnerValue.value, props.type)
//
const currentArray = getPickerValue(value, props.type, props.useSecond)
const boundaryArray = getPickerValue(endInnerValue.value, props.type, props.useSecond)
const columns = datetimePickerView.value.getOriginColumns()
//