mirror of
https://github.com/element-plus/element-plus.git
synced 2026-03-13 07:51:17 +08:00
148 lines
3.8 KiB
Vue
148 lines
3.8 KiB
Vue
<template>
|
|
<el-select
|
|
ref="select"
|
|
:model-value="value"
|
|
:disabled="_disabled"
|
|
:clearable="clearable"
|
|
:clear-icon="clearIcon"
|
|
:size="size"
|
|
:effect="effect"
|
|
:placeholder="placeholder"
|
|
default-first-option
|
|
:filterable="editable"
|
|
:empty-values="emptyValues"
|
|
:value-on-clear="valueOnClear"
|
|
:popper-class="popperClass"
|
|
:popper-style="popperStyle"
|
|
@update:model-value="(event) => $emit(UPDATE_MODEL_EVENT, event)"
|
|
@change="(event) => $emit(CHANGE_EVENT, event)"
|
|
@blur="(event) => $emit('blur', event)"
|
|
@focus="(event) => $emit('focus', event)"
|
|
@clear="() => $emit('clear')"
|
|
>
|
|
<el-option
|
|
v-for="item in items"
|
|
:key="item.value"
|
|
:label="item.value"
|
|
:value="item.value"
|
|
:disabled="item.disabled"
|
|
/>
|
|
<template #prefix>
|
|
<el-icon v-if="prefixIcon" :class="nsInput.e('prefix-icon')">
|
|
<component :is="prefixIcon" />
|
|
</el-icon>
|
|
</template>
|
|
</el-select>
|
|
</template>
|
|
|
|
<script lang="ts" setup>
|
|
import { computed, ref } from 'vue'
|
|
import dayjs from 'dayjs'
|
|
import customParseFormat from 'dayjs/plugin/customParseFormat.js'
|
|
import ElSelect from '@element-plus/components/select'
|
|
import { useFormDisabled } from '@element-plus/components/form'
|
|
import ElIcon from '@element-plus/components/icon'
|
|
import { useLocale, useNamespace } from '@element-plus/hooks'
|
|
import { CHANGE_EVENT, UPDATE_MODEL_EVENT } from '@element-plus/constants'
|
|
import { timeSelectProps } from './time-select'
|
|
import { compareTime, formatTime, nextTime, parseTime } from './utils'
|
|
|
|
dayjs.extend(customParseFormat)
|
|
|
|
const { Option: ElOption } = ElSelect
|
|
|
|
defineOptions({
|
|
name: 'ElTimeSelect',
|
|
})
|
|
|
|
defineEmits([CHANGE_EVENT, 'blur', 'focus', 'clear', UPDATE_MODEL_EVENT])
|
|
|
|
const props = defineProps(timeSelectProps)
|
|
|
|
const nsInput = useNamespace('input')
|
|
const select = ref<typeof ElSelect>()
|
|
|
|
const _disabled = useFormDisabled()
|
|
const { lang } = useLocale()
|
|
|
|
const value = computed(() => props.modelValue)
|
|
const start = computed(() => {
|
|
const time = parseTime(props.start)
|
|
return time ? formatTime(time) : null
|
|
})
|
|
|
|
const end = computed(() => {
|
|
const time = parseTime(props.end)
|
|
return time ? formatTime(time) : null
|
|
})
|
|
|
|
const step = computed(() => {
|
|
const time = parseTime(props.step)
|
|
return time ? formatTime(time) : null
|
|
})
|
|
|
|
const minTime = computed(() => {
|
|
const time = parseTime(props.minTime || '')
|
|
return time ? formatTime(time) : null
|
|
})
|
|
|
|
const maxTime = computed(() => {
|
|
const time = parseTime(props.maxTime || '')
|
|
return time ? formatTime(time) : null
|
|
})
|
|
|
|
const items = computed(() => {
|
|
const result: { value: string; disabled: boolean }[] = []
|
|
const push = (formattedValue: string, rawValue: string) => {
|
|
result.push({
|
|
value: formattedValue,
|
|
disabled:
|
|
compareTime(rawValue, minTime.value || '-1:-1') <= 0 ||
|
|
compareTime(rawValue, maxTime.value || '100:100') >= 0,
|
|
})
|
|
}
|
|
|
|
if (props.start && props.end && props.step) {
|
|
let current = start.value
|
|
let currentTime: string
|
|
while (current && end.value && compareTime(current, end.value) <= 0) {
|
|
currentTime = dayjs(current, 'HH:mm')
|
|
.locale(lang.value)
|
|
.format(props.format)
|
|
push(currentTime, current)
|
|
current = nextTime(current, step.value!)
|
|
}
|
|
if (
|
|
props.includeEndTime &&
|
|
end.value &&
|
|
result[result.length - 1]?.value !== end.value
|
|
) {
|
|
const formattedValue = dayjs(end.value, 'HH:mm')
|
|
.locale(lang.value)
|
|
.format(props.format)
|
|
push(formattedValue, end.value)
|
|
}
|
|
}
|
|
return result
|
|
})
|
|
|
|
const blur = () => {
|
|
select.value?.blur?.()
|
|
}
|
|
|
|
const focus = () => {
|
|
select.value?.focus?.()
|
|
}
|
|
|
|
defineExpose({
|
|
/**
|
|
* @description blur the Input component
|
|
*/
|
|
blur,
|
|
/**
|
|
* @description focus the Input component
|
|
*/
|
|
focus,
|
|
})
|
|
</script>
|