123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173 |
- <template>
- <el-select
- :model-value="modelValue"
- @update:modelValue="(value) => {
- $emit('change', value)
- $emit('update:modelValue', value)
- }"
- :disabled="!editable"
- :clearable="clearable"
- :clear-icon="clearIcon"
- :size="size"
- :placeholder="placeholder"
- default-first-option
- filterable
- @change="
- (value) => {
- $emit('change', value)
- $emit('update:modelValue', value)
- }
- "
- @blur="(event) => $emit('blur', event)"
- @focus="(event) => $emit('focus', event)"
- >
- <el-option
- v-for="item in items"
- :key="item.value"
- :label="item.value"
- :value="item.value"
- :disabled="item.disabled"
- />
- <template #prefix>
- <i :class="`el-input__icon ${prefixIcon}`"></i>
- </template>
- </el-select>
- </template>
- <script>
- import { computed } from 'vue'
- import { ElSelect, ElOption } from 'element-plus'
- const parseTime = time => {
- const values = (time || '').split(':')
- if (values.length >= 2) {
- const hours = parseInt(values[0], 10)
- const minutes = parseInt(values[1], 10)
- return {
- hours,
- minutes
- }
- }
- return null
- }
- const compareTime = (time1, time2) => {
- const value1 = parseTime(time1)
- const value2 = parseTime(time2)
- const minutes1 = value1.minutes + value1.hours * 60
- const minutes2 = value2.minutes + value2.hours * 60
- if (minutes1 === minutes2) {
- return 0
- }
- return minutes1 > minutes2 ? 1 : -1
- }
- const formatTime = (time) => {
- return (
- (time.hours < 10 ? '0' + time.hours : time.hours) +
- ':' +
- (time.minutes < 10 ? '0' + time.minutes : time.minutes)
- )
- }
- const nextTime = (time, step) => {
- const timeValue = parseTime(time)
- const stepValue = parseTime(step)
- const next = {
- hours: timeValue.hours,
- minutes: timeValue.minutes
- }
- next.minutes += stepValue.minutes
- next.hours += stepValue.hours
- next.hours += Math.floor(next.minutes / 60)
- next.minutes = next.minutes % 60
- return formatTime(next)
- }
- export default {
- name: 'ElTimeSelect',
- components: { ElSelect, ElOption },
- model: {
- prop: 'value',
- event: 'change'
- },
- props: {
- modelValue: String,
- editable: {
- type: Boolean,
- default: true
- },
- clearable: {
- type: Boolean,
- default: true
- },
- size: {
- type: String,
- default: '',
- validator: value => !value || ['medium', 'small', 'mini'].indexOf(value) !== -1
- },
- placeholder: {
- type: String,
- default: ''
- },
- start: {
- type: String,
- default: '09:00'
- },
- end: {
- type: String,
- default: '18:00'
- },
- step: {
- type: String,
- default: '00:30'
- },
- minTime: {
- type: String,
- default: ''
- },
- maxTime: {
- type: String,
- default: ''
- },
- name: {
- type: String,
- default: ''
- },
- prefixIcon: {
- type: String,
- default: 'el-icon-time'
- },
- clearIcon: {
- type: String,
- default: 'el-icon-circle-close'
- }
- },
- emits: ['change', 'blur', 'focus', 'update:modelValue'],
- setup (props, context) {
- // data
- // const value = ref(props.modelValue)
- // computed
- const items = computed(() => {
- const result = []
- if (props.start && props.end && props.step) {
- let current = props.start
- while (compareTime(current, props.end) <= 0) {
- result.push({
- value: current,
- disabled:
- compareTime(current, props.minTime || '-1:-1') <= 0 ||
- compareTime(current, props.maxTime || '100:100') >= 0
- })
- current = nextTime(current, props.step)
- }
- }
- return result
- })
- // const emitInput = (val) => {
- // context.emit('update:modelValue', val)
- // }
- return {
- items
- // emitInput
- }
- }
- }
- </script>
|