index.vue 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. <template>
  2. <el-select
  3. :class="['cip-time-select',{'cip-time-select--no-icon': noIcon }]"
  4. :model-value="modelValue"
  5. @update:modelValue="(value) => {
  6. $emit('change', value)
  7. $emit('update:modelValue', value)
  8. }"
  9. :disabled="!editable"
  10. :clearable="clearable"
  11. :clear-icon="clearIcon"
  12. :suffix-icon="noIcon ? '' : suffixIcon"
  13. :size="size"
  14. :placeholder="placeholder"
  15. default-first-option
  16. filterable
  17. @change="
  18. (value) => {
  19. $emit('change', value)
  20. $emit('update:modelValue', value)
  21. }
  22. "
  23. @blur="(event) => $emit('blur', event)"
  24. @focus="(event) => $emit('focus', event)"
  25. >
  26. <el-option
  27. v-for="item in items"
  28. :key="item.value"
  29. :label="item.value"
  30. :value="item.value"
  31. :disabled="item.disabled"
  32. />
  33. </el-select>
  34. </template>
  35. <script>
  36. import { computed } from 'vue'
  37. import { ElSelect, ElOption } from 'element-plus'
  38. import { Clock, CircleClose } from '@element-plus/icons-vue'
  39. import { nextTime, compareTime } from './util'
  40. export default {
  41. name: 'CipTimeSelect',
  42. components: { ElSelect, ElOption },
  43. props: {
  44. modelValue: String,
  45. editable: {
  46. type: Boolean,
  47. default: true
  48. },
  49. clearable: {
  50. type: Boolean,
  51. default: true
  52. },
  53. size: {
  54. type: String,
  55. validator: value => !value || ['large', 'default', 'small'].indexOf(value) !== -1
  56. },
  57. placeholder: {
  58. type: String,
  59. default: ' '
  60. },
  61. start: {
  62. type: String,
  63. default: '09:00'
  64. },
  65. end: {
  66. type: String,
  67. default: '18:00'
  68. },
  69. step: {
  70. type: String,
  71. default: '00:30'
  72. },
  73. minTime: {
  74. type: String,
  75. default: ''
  76. },
  77. maxTime: {
  78. type: String,
  79. default: ''
  80. },
  81. name: {
  82. type: String,
  83. default: ''
  84. },
  85. // prefixIcon: {
  86. // type: String,
  87. // default: Timer// 'el-icon-time'
  88. // },
  89. suffixIcon: {
  90. type: [String, Object],
  91. default: Clock
  92. },
  93. clearIcon: {
  94. type: [String, Object],
  95. default: CircleClose
  96. },
  97. noIcon: {
  98. type: Boolean,
  99. default: undefined
  100. }
  101. },
  102. emits: ['change', 'blur', 'focus', 'update:modelValue'],
  103. setup (props, context) {
  104. const items = computed(() => {
  105. const result = []
  106. if (props.start && props.end && props.step) {
  107. let current = props.start
  108. while (compareTime(current, props.end) <= 0) {
  109. result.push({
  110. value: current,
  111. disabled:
  112. compareTime(current, props.minTime || '-1:-1') <= 0 ||
  113. compareTime(current, props.maxTime || '100:100') >= 0
  114. })
  115. current = nextTime(current, props.step)
  116. }
  117. }
  118. return result
  119. })
  120. return {
  121. items
  122. }
  123. }
  124. }
  125. </script>
  126. <style lang="less">
  127. .cip-time-select--no-icon{
  128. .el-input__suffix{
  129. width: 22px; // 无icon时没有宽度会导致长度比有icon的短22px
  130. }
  131. }
  132. </style>