Calendar.js 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325
  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. this.props.onPreviousMonth(select_year, select_month + 1);
  144. })
  145. },
  146. /**
  147. * 之后一个月
  148. */
  149. nextMonth() {
  150. let { current_year, current_month, current_day,
  151. select_year, select_month, select_day, date_num_array, first_day} = this.state;
  152. if (select_month === 11) {
  153. select_year = +select_year + 1;
  154. select_month = 0;
  155. date_num_array = this._initMonthDayNumber(select_year);
  156. } else {
  157. select_month = +select_month + 1;
  158. }
  159. first_day = H.weekOfMonth(new Date(select_year, select_month));
  160. if (current_year === select_year &&
  161. current_month === select_month) {
  162. select_day = current_day;
  163. } else {
  164. select_day = undefined;
  165. }
  166. this.setState({
  167. select_year : select_year,
  168. select_month : select_month,
  169. select_day : select_day,
  170. date_num_array : date_num_array,
  171. first_day : first_day
  172. }, () => {
  173. this.props.onNextMonth(select_year, select_month + 1);
  174. })
  175. },
  176. /**
  177. * 渲染页面
  178. * @returns {XML}
  179. */
  180. render() {
  181. let { row_number, col_number, tags } = this.props;
  182. let { current_year, current_month, current_day,
  183. select_year, select_month, select_day,
  184. history_year, history_month, history_day,
  185. date_num_array, first_day} = this.state;
  186. let month_day = date_num_array[select_month],
  187. n_day = row_number * col_number - first_day - month_day,
  188. previous_month_days = undefined,
  189. previous_days = [],
  190. current_days = [],
  191. next_days = [],
  192. total_days = [],
  193. previous_month = undefined;
  194. if (select_month === 0) {
  195. previous_month = 11;
  196. } else {
  197. previous_month = select_month - 1;
  198. }
  199. previous_month_days = date_num_array[previous_month];
  200. for (let i = 0; i < first_day; i++) {
  201. let previous_link = (<li className="item-gray" key={'previous'+i}>
  202. <a href="javascript:;">{previous_month_days - (first_day - i) + 1}</a>
  203. </li>);
  204. previous_days.push(previous_link);
  205. }
  206. let currentClassName = '',
  207. currentText = '';
  208. for (let i = 0; i < month_day; i++) {
  209. // 今天样式
  210. if (current_year == select_year && current_month == select_month && current_day == (i + 1)) {
  211. currentClassName = 'item-current';
  212. currentText = '今天';
  213. } else {
  214. currentText = i + 1;
  215. // 判断选择样式与历史样式是否相等,相等激活
  216. if (select_year == history_year && select_month == history_month && history_day == (i + 1)) {
  217. currentClassName = 'item-active';
  218. } else {
  219. currentClassName = '';
  220. }
  221. }
  222. // 添加tag样式
  223. if (tags.length > 0) {
  224. for (let j = 0; j < tags.length; j++) {
  225. if ((i + 1) === tags[j]) {
  226. currentClassName += 'item-tag';
  227. break;
  228. }
  229. }
  230. }
  231. let current_link = (<li className={currentClassName} key={'current'+i}>
  232. <a href="javascript:;" onClick={this.selectDate.bind(this, i + 1)}>
  233. {currentText}
  234. </a>
  235. </li>);
  236. current_days.push(current_link);
  237. }
  238. for (let i = 0; i < n_day; i++) {
  239. let next_link = (<li className="item-gray" key={'next'+i}>
  240. <a href="javascript:;">{i + 1}</a>
  241. </li>);
  242. next_days.push(next_link);
  243. }
  244. total_days = previous_days.concat(current_days, next_days);
  245. let ul_list = [];
  246. if (total_days.length > 0) {
  247. for (let i = 0; i < row_number; i++) {
  248. let li_list = [],
  249. start_index = i * col_number,
  250. end_index = (i + 1) * col_number;
  251. for (let j = start_index; j < end_index; j++) {
  252. li_list.push(total_days[j]);
  253. }
  254. ul_list.push(li_list);
  255. }
  256. }
  257. return (
  258. <div className="calendar">
  259. <div className="calendar-header">
  260. <i className="icon-left" onClick={this.previousMonth}></i>
  261. <span>{select_year} 年 {select_month + 1} 月</span>
  262. <i className="icon-right" onClick={this.nextMonth}></i>
  263. </div>
  264. <div className="calendar-body">
  265. <ul className="c-body-head">
  266. <li>日</li>
  267. <li>一</li>
  268. <li>二</li>
  269. <li>三</li>
  270. <li>四</li>
  271. <li>五</li>
  272. <li>六</li>
  273. </ul>
  274. <div className="c-body-content">
  275. {
  276. ul_list.map((u, index) => {
  277. return (<ul key={'ul'+index} className="content-row">{u}</ul>);
  278. })
  279. }
  280. </div>
  281. </div>
  282. </div>
  283. );
  284. }
  285. });
  286. export default Calendar;