368cb11f1cc300c73e73c527063452fe356479dcd1cb445e5aad1b1b00122c2ca1b84bc2d97a3cfa1e6cb14b3bf424d4e0a00098f9f91ee20ba346b8a8bc0e 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248
  1. <template>
  2. <transition
  3. name="el-zoom-in-top"
  4. @after-leave="$emit('dodestroy')">
  5. <div
  6. v-show="visible"
  7. class="el-time-range-picker el-picker-panel el-popper"
  8. :class="popperClass">
  9. <div class="el-time-range-picker__content">
  10. <div class="el-time-range-picker__cell">
  11. <div class="el-time-range-picker__header">{{ t('el.datepicker.startTime') }}</div>
  12. <div
  13. :class="{ 'has-seconds': showSeconds, 'is-arrow': arrowControl }"
  14. class="el-time-range-picker__body el-time-panel__content">
  15. <time-spinner
  16. ref="minSpinner"
  17. :show-seconds="showSeconds"
  18. :am-pm-mode="amPmMode"
  19. @change="handleMinChange"
  20. :arrow-control="arrowControl"
  21. @select-range="setMinSelectionRange"
  22. :date="minDate">
  23. </time-spinner>
  24. </div>
  25. </div>
  26. <div class="el-time-range-picker__cell">
  27. <div class="el-time-range-picker__header">{{ t('el.datepicker.endTime') }}</div>
  28. <div
  29. :class="{ 'has-seconds': showSeconds, 'is-arrow': arrowControl }"
  30. class="el-time-range-picker__body el-time-panel__content">
  31. <time-spinner
  32. ref="maxSpinner"
  33. :show-seconds="showSeconds"
  34. :am-pm-mode="amPmMode"
  35. @change="handleMaxChange"
  36. :arrow-control="arrowControl"
  37. @select-range="setMaxSelectionRange"
  38. :date="maxDate">
  39. </time-spinner>
  40. </div>
  41. </div>
  42. </div>
  43. <div class="el-time-panel__footer">
  44. <button
  45. type="button"
  46. class="el-time-panel__btn cancel"
  47. @click="handleCancel()">{{ t('el.datepicker.cancel') }}</button>
  48. <button
  49. type="button"
  50. class="el-time-panel__btn confirm"
  51. @click="handleConfirm()"
  52. :disabled="btnDisabled">{{ t('el.datepicker.confirm') }}</button>
  53. </div>
  54. </div>
  55. </transition>
  56. </template>
  57. <script type="text/babel">
  58. import {
  59. parseDate,
  60. limitTimeRange,
  61. modifyDate,
  62. clearMilliseconds,
  63. timeWithinRange
  64. } from 'element-ui/src/utils/date-util';
  65. import Locale from 'element-ui/src/mixins/locale';
  66. import TimeSpinner from '../basic/time-spinner';
  67. const MIN_TIME = parseDate('00:00:00', 'HH:mm:ss');
  68. const MAX_TIME = parseDate('23:59:59', 'HH:mm:ss');
  69. const minTimeOfDay = function(date) {
  70. return modifyDate(MIN_TIME, date.getFullYear(), date.getMonth(), date.getDate());
  71. };
  72. const maxTimeOfDay = function(date) {
  73. return modifyDate(MAX_TIME, date.getFullYear(), date.getMonth(), date.getDate());
  74. };
  75. // increase time by amount of milliseconds, but within the range of day
  76. const advanceTime = function(date, amount) {
  77. return new Date(Math.min(date.getTime() + amount, maxTimeOfDay(date).getTime()));
  78. };
  79. export default {
  80. mixins: [Locale],
  81. components: { TimeSpinner },
  82. computed: {
  83. showSeconds() {
  84. return (this.format || '').indexOf('ss') !== -1;
  85. },
  86. offset() {
  87. return this.showSeconds ? 11 : 8;
  88. },
  89. spinner() {
  90. return this.selectionRange[0] < this.offset ? this.$refs.minSpinner : this.$refs.maxSpinner;
  91. },
  92. btnDisabled() {
  93. return this.minDate.getTime() > this.maxDate.getTime();
  94. },
  95. amPmMode() {
  96. if ((this.format || '').indexOf('A') !== -1) return 'A';
  97. if ((this.format || '').indexOf('a') !== -1) return 'a';
  98. return '';
  99. }
  100. },
  101. data() {
  102. return {
  103. popperClass: '',
  104. minDate: new Date(),
  105. maxDate: new Date(),
  106. value: [],
  107. oldValue: [new Date(), new Date()],
  108. defaultValue: null,
  109. format: 'HH:mm:ss',
  110. visible: false,
  111. selectionRange: [0, 2],
  112. arrowControl: false
  113. };
  114. },
  115. watch: {
  116. value(value) {
  117. if (Array.isArray(value)) {
  118. this.minDate = new Date(value[0]);
  119. this.maxDate = new Date(value[1]);
  120. } else {
  121. if (Array.isArray(this.defaultValue)) {
  122. this.minDate = new Date(this.defaultValue[0]);
  123. this.maxDate = new Date(this.defaultValue[1]);
  124. } else if (this.defaultValue) {
  125. this.minDate = new Date(this.defaultValue);
  126. this.maxDate = advanceTime(new Date(this.defaultValue), 60 * 60 * 1000);
  127. } else {
  128. this.minDate = new Date();
  129. this.maxDate = advanceTime(new Date(), 60 * 60 * 1000);
  130. }
  131. }
  132. },
  133. visible(val) {
  134. if (val) {
  135. this.oldValue = this.value;
  136. this.$nextTick(() => this.$refs.minSpinner.emitSelectRange('hours'));
  137. }
  138. }
  139. },
  140. methods: {
  141. handleClear() {
  142. this.$emit('pick', null);
  143. },
  144. handleCancel() {
  145. this.$emit('pick', this.oldValue);
  146. },
  147. handleMinChange(date) {
  148. this.minDate = clearMilliseconds(date);
  149. this.handleChange();
  150. },
  151. handleMaxChange(date) {
  152. this.maxDate = clearMilliseconds(date);
  153. this.handleChange();
  154. },
  155. handleChange() {
  156. if (this.isValidValue([this.minDate, this.maxDate])) {
  157. this.$refs.minSpinner.selectableRange = [[minTimeOfDay(this.minDate), this.maxDate]];
  158. this.$refs.maxSpinner.selectableRange = [[this.minDate, maxTimeOfDay(this.maxDate)]];
  159. this.$emit('pick', [this.minDate, this.maxDate], true);
  160. }
  161. },
  162. setMinSelectionRange(start, end) {
  163. this.$emit('select-range', start, end, 'min');
  164. this.selectionRange = [start, end];
  165. },
  166. setMaxSelectionRange(start, end) {
  167. this.$emit('select-range', start, end, 'max');
  168. this.selectionRange = [start + this.offset, end + this.offset];
  169. },
  170. handleConfirm(visible = false) {
  171. const minSelectableRange = this.$refs.minSpinner.selectableRange;
  172. const maxSelectableRange = this.$refs.maxSpinner.selectableRange;
  173. this.minDate = limitTimeRange(this.minDate, minSelectableRange, this.format);
  174. this.maxDate = limitTimeRange(this.maxDate, maxSelectableRange, this.format);
  175. this.$emit('pick', [this.minDate, this.maxDate], visible);
  176. },
  177. adjustSpinners() {
  178. this.$refs.minSpinner.adjustSpinners();
  179. this.$refs.maxSpinner.adjustSpinners();
  180. },
  181. changeSelectionRange(step) {
  182. const list = this.showSeconds ? [0, 3, 6, 11, 14, 17] : [0, 3, 8, 11];
  183. const mapping = ['hours', 'minutes'].concat(this.showSeconds ? ['seconds'] : []);
  184. const index = list.indexOf(this.selectionRange[0]);
  185. const next = (index + step + list.length) % list.length;
  186. const half = list.length / 2;
  187. if (next < half) {
  188. this.$refs.minSpinner.emitSelectRange(mapping[next]);
  189. } else {
  190. this.$refs.maxSpinner.emitSelectRange(mapping[next - half]);
  191. }
  192. },
  193. isValidValue(date) {
  194. return Array.isArray(date) &&
  195. timeWithinRange(this.minDate, this.$refs.minSpinner.selectableRange) &&
  196. timeWithinRange(this.maxDate, this.$refs.maxSpinner.selectableRange);
  197. },
  198. handleKeydown(event) {
  199. const keyCode = event.keyCode;
  200. const mapping = { 38: -1, 40: 1, 37: -1, 39: 1 };
  201. // Left or Right
  202. if (keyCode === 37 || keyCode === 39) {
  203. const step = mapping[keyCode];
  204. this.changeSelectionRange(step);
  205. event.preventDefault();
  206. return;
  207. }
  208. // Up or Down
  209. if (keyCode === 38 || keyCode === 40) {
  210. const step = mapping[keyCode];
  211. this.spinner.scrollDown(step);
  212. event.preventDefault();
  213. return;
  214. }
  215. }
  216. }
  217. };
  218. </script>