e4f756c5f9e9c2db9908ef0bba0c1f2847662672e4c0771d18132506d8c1b201c51893a3c20ccfdee7171132ea847f3acdabbd03fc67bc85f7a320489b355d 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. <template>
  2. <transition name="el-zoom-in-top" @before-enter="handleMenuEnter" @after-leave="$emit('dodestroy')">
  3. <div
  4. ref="popper"
  5. v-show="visible"
  6. :style="{ width: width + 'px' }"
  7. :class="popperClass"
  8. class="el-picker-panel time-select el-popper">
  9. <el-scrollbar noresize wrap-class="el-picker-panel__content">
  10. <div class="time-select-item"
  11. v-for="item in items"
  12. :class="{ selected: value === item.value, disabled: item.disabled, default: item.value === defaultValue }"
  13. :disabled="item.disabled"
  14. :key="item.value"
  15. @click="handleClick(item)">{{ item.value }}</div>
  16. </el-scrollbar>
  17. </div>
  18. </transition>
  19. </template>
  20. <script type="text/babel">
  21. import ElScrollbar from 'element-ui/packages/scrollbar';
  22. import scrollIntoView from 'element-ui/src/utils/scroll-into-view';
  23. const parseTime = function(time) {
  24. const values = (time || '').split(':');
  25. if (values.length >= 2) {
  26. const hours = parseInt(values[0], 10);
  27. const minutes = parseInt(values[1], 10);
  28. return {
  29. hours,
  30. minutes
  31. };
  32. }
  33. /* istanbul ignore next */
  34. return null;
  35. };
  36. const compareTime = function(time1, time2) {
  37. const value1 = parseTime(time1);
  38. const value2 = parseTime(time2);
  39. const minutes1 = value1.minutes + value1.hours * 60;
  40. const minutes2 = value2.minutes + value2.hours * 60;
  41. if (minutes1 === minutes2) {
  42. return 0;
  43. }
  44. return minutes1 > minutes2 ? 1 : -1;
  45. };
  46. const formatTime = function(time) {
  47. return (time.hours < 10 ? '0' + time.hours : time.hours) + ':' + (time.minutes < 10 ? '0' + time.minutes : time.minutes);
  48. };
  49. const nextTime = function(time, step) {
  50. const timeValue = parseTime(time);
  51. const stepValue = parseTime(step);
  52. const next = {
  53. hours: timeValue.hours,
  54. minutes: timeValue.minutes
  55. };
  56. next.minutes += stepValue.minutes;
  57. next.hours += stepValue.hours;
  58. next.hours += Math.floor(next.minutes / 60);
  59. next.minutes = next.minutes % 60;
  60. return formatTime(next);
  61. };
  62. export default {
  63. components: { ElScrollbar },
  64. watch: {
  65. value(val) {
  66. if (!val) return;
  67. this.$nextTick(() => this.scrollToOption());
  68. }
  69. },
  70. methods: {
  71. handleClick(item) {
  72. if (!item.disabled) {
  73. this.$emit('pick', item.value);
  74. }
  75. },
  76. handleClear() {
  77. this.$emit('pick', null);
  78. },
  79. scrollToOption(selector = '.selected') {
  80. const menu = this.$refs.popper.querySelector('.el-picker-panel__content');
  81. scrollIntoView(menu, menu.querySelector(selector));
  82. },
  83. handleMenuEnter() {
  84. const selected = this.items.map(item => item.value).indexOf(this.value) !== -1;
  85. const hasDefault = this.items.map(item => item.value).indexOf(this.defaultValue) !== -1;
  86. const option = (selected && '.selected') || (hasDefault && '.default') || '.time-select-item:not(.disabled)';
  87. this.$nextTick(() => this.scrollToOption(option));
  88. },
  89. scrollDown(step) {
  90. const items = this.items;
  91. const length = items.length;
  92. let total = items.length;
  93. let index = items.map(item => item.value).indexOf(this.value);
  94. while (total--) {
  95. index = (index + step + length) % length;
  96. if (!items[index].disabled) {
  97. this.$emit('pick', items[index].value, true);
  98. return;
  99. }
  100. }
  101. },
  102. isValidValue(date) {
  103. return this.items.filter(item => !item.disabled).map(item => item.value).indexOf(date) !== -1;
  104. },
  105. handleKeydown(event) {
  106. const keyCode = event.keyCode;
  107. if (keyCode === 38 || keyCode === 40) {
  108. const mapping = { 40: 1, 38: -1 };
  109. const offset = mapping[keyCode.toString()];
  110. this.scrollDown(offset);
  111. event.stopPropagation();
  112. return;
  113. }
  114. }
  115. },
  116. data() {
  117. return {
  118. popperClass: '',
  119. start: '09:00',
  120. end: '18:00',
  121. step: '00:30',
  122. value: '',
  123. defaultValue: '',
  124. visible: false,
  125. minTime: '',
  126. maxTime: '',
  127. width: 0
  128. };
  129. },
  130. computed: {
  131. items() {
  132. const start = this.start;
  133. const end = this.end;
  134. const step = this.step;
  135. const result = [];
  136. if (start && end && step) {
  137. let current = start;
  138. while (compareTime(current, end) <= 0) {
  139. result.push({
  140. value: current,
  141. disabled: compareTime(current, this.minTime || '-1:-1') <= 0 ||
  142. compareTime(current, this.maxTime || '100:100') >= 0
  143. });
  144. current = nextTime(current, step);
  145. }
  146. }
  147. return result;
  148. }
  149. }
  150. };
  151. </script>