Calendar.js 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321
  1. /**
  2. * Created by Ryn on 2016/8/7.
  3. * 日历组件
  4. */
  5. import React from 'react';
  6. import H from '../helpers/H';
  7. const Calendar = React.createClass({
  8. /**
  9. * 默认的属性
  10. */
  11. getDefaultProps() {
  12. return {
  13. row_number : 6,
  14. col_number : 7
  15. }
  16. },
  17. /**
  18. * 组件初始化状态
  19. */
  20. getInitialState() {
  21. return {
  22. current_year : H.getFullYear(),
  23. current_month : H.getMonth(),
  24. current_day : H.getDate(),
  25. select_year : H.getFullYear(),
  26. select_month : H.getMonth(),
  27. select_day : H.getDate(),
  28. history_year : undefined,
  29. history_month : undefined,
  30. history_day : undefined,
  31. date_num_array : []
  32. }
  33. },
  34. componentWillReceiveProps(nextProps) {
  35. // todo
  36. },
  37. /**
  38. * 组件渲染完后执行
  39. */
  40. componentDidMount() {
  41. let { year, month, day} = this.props;
  42. // 初始化状态
  43. if(year && month && day) {
  44. let date_num_array = this._initMonthDayNumber(year),
  45. first_day = H.weekOfMonth(new Date(year, month - 1));
  46. this.setState({
  47. select_year : year,
  48. select_month : month - 1,
  49. select_day : day,
  50. date_num_array : date_num_array,
  51. first_day : first_day
  52. });
  53. }
  54. },
  55. /**
  56. * 给月份数组附上每月天数
  57. * @param year 年份
  58. * @private
  59. */
  60. _initMonthDayNumber(year) {
  61. let _date_array = [];
  62. for (var i = 0; i < 12; i++) {
  63. switch (i + 1) {
  64. case 1:
  65. case 3:
  66. case 5:
  67. case 7:
  68. case 8:
  69. case 10:
  70. case 12:
  71. _date_array.push(31);
  72. break;
  73. case 4:
  74. case 6:
  75. case 9:
  76. case 11:
  77. _date_array.push(30);
  78. break;
  79. case 2:
  80. if (H.isLeapYear(year)) {
  81. _date_array.push(29);
  82. } else {
  83. _date_array.push(28);
  84. }
  85. break;
  86. default:
  87. break;
  88. }
  89. }
  90. return _date_array;
  91. },
  92. /**
  93. * 组件将要挂载
  94. * 设置月份数组以及计算出每月的第一天星期几
  95. */
  96. componentWillMount() {
  97. let date_num_array = this._initMonthDayNumber(this.state.current_year),
  98. first_day = H.weekOfMonth();
  99. this.setState({date_num_array : date_num_array, first_day : first_day});
  100. },
  101. /**
  102. * 日期选择
  103. * @param s_day
  104. */
  105. selectDate(s_day) {
  106. let { select_year, select_month} = this.state;
  107. this.setState({
  108. history_year : select_year,
  109. history_month : select_month,
  110. history_day : s_day,
  111. select_day : s_day
  112. }, () => {
  113. this.props.onSelectDate(select_year, select_month + 1, s_day);
  114. });
  115. },
  116. /**
  117. * 前一个月
  118. */
  119. previousMonth() {
  120. let { current_year, current_month, current_day,
  121. select_year, select_month, select_day, date_num_array, first_day} = this.state;
  122. if (select_month === 0) {
  123. select_year = +select_year - 1;
  124. select_month = 11;
  125. date_num_array = this._initMonthDayNumber(select_year);
  126. } else {
  127. select_month = +select_month - 1;
  128. }
  129. first_day = H.weekOfMonth(new Date(select_year, select_month));
  130. if (current_year === select_year &&
  131. current_month === select_month) {
  132. select_day = current_day;
  133. } else {
  134. select_day = undefined;
  135. }
  136. this.setState({
  137. select_year : select_year,
  138. select_month : select_month,
  139. select_day : select_day,
  140. date_num_array : date_num_array,
  141. first_day : first_day
  142. })
  143. },
  144. /**
  145. * 之后一个月
  146. */
  147. nextMonth() {
  148. let { current_year, current_month, current_day,
  149. select_year, select_month, select_day, date_num_array, first_day} = this.state;
  150. if (select_month === 11) {
  151. select_year = +select_year + 1;
  152. select_month = 0;
  153. date_num_array = this._initMonthDayNumber(select_year);
  154. } else {
  155. select_month = +select_month + 1;
  156. }
  157. first_day = H.weekOfMonth(new Date(select_year, select_month));
  158. if (current_year === select_year &&
  159. current_month === select_month) {
  160. select_day = current_day;
  161. } else {
  162. select_day = undefined;
  163. }
  164. this.setState({
  165. select_year : select_year,
  166. select_month : select_month,
  167. select_day : select_day,
  168. date_num_array : date_num_array,
  169. first_day : first_day
  170. })
  171. },
  172. /**
  173. * 渲染页面
  174. * @returns {XML}
  175. */
  176. render() {
  177. let { row_number, col_number, tags } = this.props;
  178. let { current_year, current_month, current_day,
  179. select_year, select_month, select_day,
  180. history_year, history_month, history_day,
  181. date_num_array, first_day} = this.state;
  182. let month_day = date_num_array[select_month],
  183. n_day = row_number * col_number - first_day - month_day,
  184. previous_month_days = undefined,
  185. previous_days = [],
  186. current_days = [],
  187. next_days = [],
  188. total_days = [],
  189. previous_month = undefined;
  190. if (select_month === 0) {
  191. previous_month = 11;
  192. } else {
  193. previous_month = select_month - 1;
  194. }
  195. previous_month_days = date_num_array[previous_month];
  196. for (let i = 0; i < first_day; i++) {
  197. let previous_link = (<li className="item-gray" key={'previous'+i}>
  198. <a href="javascript:;">{previous_month_days - (first_day - i) + 1}</a>
  199. </li>);
  200. previous_days.push(previous_link);
  201. }
  202. let currentClassName = '',
  203. currentText = '';
  204. for (let i = 0; i < month_day; i++) {
  205. // 今天样式
  206. if (current_year == select_year && current_month == select_month && current_day == (i + 1)) {
  207. currentClassName = 'item-current';
  208. currentText = '今天';
  209. } else {
  210. currentText = i + 1;
  211. // 判断选择样式与历史样式是否相等,相等激活
  212. if (select_year == history_year && select_month == history_month && history_day == (i + 1)) {
  213. currentClassName = 'item-active';
  214. } else {
  215. currentClassName = '';
  216. }
  217. }
  218. // 添加tag样式
  219. if (tags.length > 0) {
  220. for (let j = 0; j < tags.length; j++) {
  221. if ((i + 1) === tags[j]) {
  222. currentClassName += 'item-tag';
  223. break;
  224. }
  225. }
  226. }
  227. let current_link = (<li className={currentClassName} key={'current'+i}>
  228. <a href="javascript:;" onClick={this.selectDate.bind(this, i + 1)}>
  229. {currentText}
  230. </a>
  231. </li>);
  232. current_days.push(current_link);
  233. }
  234. for (let i = 0; i < n_day; i++) {
  235. let next_link = (<li className="item-gray" key={'next'+i}>
  236. <a href="javascript:;">{i + 1}</a>
  237. </li>);
  238. next_days.push(next_link);
  239. }
  240. total_days = previous_days.concat(current_days, next_days);
  241. let ul_list = [];
  242. if (total_days.length > 0) {
  243. for (let i = 0; i < row_number; i++) {
  244. let li_list = [],
  245. start_index = i * col_number,
  246. end_index = (i + 1) * col_number;
  247. for (let j = start_index; j < end_index; j++) {
  248. li_list.push(total_days[j]);
  249. }
  250. ul_list.push(li_list);
  251. }
  252. }
  253. return (
  254. <div className="calendar">
  255. <div className="calendar-header">
  256. <i className="icon-left" onClick={this.previousMonth}></i>
  257. <span>{select_year} 年 {select_month + 1} 月</span>
  258. <i className="icon-right" onClick={this.nextMonth}></i>
  259. </div>
  260. <div className="calendar-body">
  261. <ul className="c-body-head">
  262. <li>日</li>
  263. <li>一</li>
  264. <li>二</li>
  265. <li>三</li>
  266. <li>四</li>
  267. <li>五</li>
  268. <li>六</li>
  269. </ul>
  270. <div className="c-body-content">
  271. {
  272. ul_list.map((u, index) => {
  273. return (<ul key={'ul'+index} className="content-row">{u}</ul>);
  274. })
  275. }
  276. </div>
  277. </div>
  278. </div>
  279. );
  280. }
  281. });
  282. export default Calendar;