DatePicker.js 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. import React, { Component } from 'react'
  2. import PropTypes from 'prop-types'
  3. import Styles from './picker.css'
  4. import { getDateFormatFromSepecificDate, getCurrentYear, getCurrentMonth } from '../../utils'
  5. import Modal from '../modal/Modal'
  6. import { CHINESE_MODEL, WESTERN_MODEL, _ } from '../../const'
  7. import { DateContext, initialData } from '../../context'
  8. import {
  9. setSelectedDays,
  10. getDaysOfMonth,
  11. getWeekSort,
  12. getDaysAfterchangedYearOrMonth,
  13. getPrevYearAndMonth,
  14. getNextYearAndMonth,
  15. isInCurrentMonth,
  16. } from '../../helper'
  17. class DatePicker extends Component {
  18. constructor(props) {
  19. super(props)
  20. const { defaultDate, year, month } = this.props
  21. this.state = {
  22. year: year,
  23. month: month,
  24. value: defaultDate,
  25. showModal: false,
  26. ...initialData,
  27. }
  28. }
  29. onModalOpen = () => {
  30. this.setState({ showModal: true })
  31. }
  32. onModalClose = () => {
  33. this.setState({ showModal: false })
  34. }
  35. onInputChange = event => {
  36. this.setState({ value: event.target.value })
  37. }
  38. onInputClear = () => {
  39. this.setState({ value: '', showModal: false })
  40. }
  41. onChangeModel = model => {
  42. const { value } = this.state
  43. let nextModel = model
  44. if (model === CHINESE_MODEL) {
  45. nextModel = WESTERN_MODEL
  46. } else {
  47. nextModel = CHINESE_MODEL
  48. }
  49. const weekTags = getWeekSort(nextModel)
  50. const changeModelDays = getDaysOfMonth(_, _, nextModel)
  51. const afterSetDays = setSelectedDays(changeModelDays, value)
  52. this.setState({
  53. model: nextModel,
  54. weekTags: weekTags,
  55. days: afterSetDays,
  56. })
  57. }
  58. onSelectDay = day => {
  59. const { days } = this.state
  60. let renderDays = days
  61. if (!isInCurrentMonth(day.full)) {
  62. // 不是在【今天】这个月份,需要重新换数据源
  63. renderDays = initialData.days
  64. }
  65. const afterSetDays = setSelectedDays(renderDays, day.full)
  66. this.setState({ value: day.full, days: afterSetDays }, () => {
  67. this.onModalClose()
  68. })
  69. }
  70. _onChangeYearOrMonth = (changeYear, changeMonth) => {
  71. const {
  72. model,
  73. value,
  74. year,
  75. month,
  76. } = this.state
  77. const days = getDaysAfterchangedYearOrMonth(changeYear, changeMonth, model)
  78. const afterSetDays = setSelectedDays(days, value)
  79. this.setState({
  80. days: afterSetDays,
  81. year: changeYear === _ ? year : changeYear,
  82. month: changeMonth === _ ? month : changeMonth,
  83. })
  84. }
  85. onPrevMonth = () => {
  86. const { year, month } = this.state
  87. const yearAndMonth = getPrevYearAndMonth(year, month)
  88. /* eslint-disable no-underscore-dangle */
  89. this._onChangeYearOrMonth(yearAndMonth.year, yearAndMonth.month)
  90. }
  91. onPrevYear = () => {
  92. const { year } = this.state
  93. this._onChangeYearOrMonth(year - 1, _)
  94. }
  95. onNextMonth = () => {
  96. const { year, month } = this.state
  97. const yearAndMonth = getNextYearAndMonth(year, month)
  98. this._onChangeYearOrMonth(yearAndMonth.year, yearAndMonth.month)
  99. }
  100. onNextYear = () => {
  101. const { year } = this.state
  102. this._onChangeYearOrMonth(year + 1, _)
  103. }
  104. render() {
  105. const { inline } = this.props
  106. const { value, showModal } = this.state
  107. return (
  108. <div className={Styles.wrapper}>
  109. <div
  110. className={Styles.container}
  111. style={inline ? { display: 'inline-block' } : {}}
  112. >
  113. <input
  114. type="text"
  115. placeholder="请选择日期"
  116. className={Styles.input}
  117. value={value}
  118. onChange={e => this.onInputChange(e)}
  119. onFocus={this.onModalOpen}
  120. />
  121. <i className={Styles.calendar} />
  122. <i
  123. className={Styles.close}
  124. onClick={this.onInputClear}
  125. role="presentation"
  126. />
  127. <div className={Styles.line} />
  128. </div>
  129. <DateContext.Provider
  130. value={
  131. {
  132. ...this.state,
  133. onSelectDay: this.onSelectDay,
  134. onChangeModel: this.onChangeModel,
  135. onPrevMonth: this.onPrevMonth,
  136. onPrevYear: this.onPrevYear,
  137. onNextMonth: this.onNextMonth,
  138. onNextYear: this.onNextYear,
  139. }
  140. }
  141. >
  142. <Modal
  143. isMounted={showModal}
  144. delayTime={200}
  145. onInputChange={this.onInputChange}
  146. onCloseModal={this.onModalClose}
  147. {...this.state}
  148. />
  149. </DateContext.Provider>
  150. </div>
  151. )
  152. }
  153. }
  154. DatePicker.defaultProps = {
  155. inline: false,
  156. defaultDate: getDateFormatFromSepecificDate(),
  157. year: getCurrentYear(),
  158. month: getCurrentMonth(),
  159. }
  160. DatePicker.propTypes = {
  161. inline: PropTypes.bool,
  162. defaultDate: PropTypes.string,
  163. year: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
  164. month: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
  165. }
  166. export default DatePicker