Month.js 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333
  1. import { createNamespace, addUnit } from '../../utils';
  2. import { setScrollTop } from '../../utils/dom/scroll';
  3. import { t, bem, compareDay, getPrevDay, getNextDay, formatMonthTitle } from '../utils';
  4. import { getMonthEndDay } from '../../datetime-picker/utils';
  5. var _createNamespace = createNamespace('calendar-month'),
  6. createComponent = _createNamespace[0];
  7. export default createComponent({
  8. props: {
  9. date: Date,
  10. type: String,
  11. color: String,
  12. minDate: Date,
  13. maxDate: Date,
  14. showMark: Boolean,
  15. rowHeight: [Number, String],
  16. formatter: Function,
  17. lazyRender: Boolean,
  18. currentDate: [Date, Array],
  19. allowSameDay: Boolean,
  20. showSubtitle: Boolean,
  21. showMonthTitle: Boolean,
  22. firstDayOfWeek: Number
  23. },
  24. data: function data() {
  25. return {
  26. visible: false
  27. };
  28. },
  29. computed: {
  30. title: function title() {
  31. return formatMonthTitle(this.date);
  32. },
  33. rowHeightWithUnit: function rowHeightWithUnit() {
  34. return addUnit(this.rowHeight);
  35. },
  36. offset: function offset() {
  37. var firstDayOfWeek = this.firstDayOfWeek;
  38. var realDay = this.date.getDay();
  39. if (!firstDayOfWeek) {
  40. return realDay;
  41. }
  42. return (realDay + 7 - this.firstDayOfWeek) % 7;
  43. },
  44. totalDay: function totalDay() {
  45. return getMonthEndDay(this.date.getFullYear(), this.date.getMonth() + 1);
  46. },
  47. shouldRender: function shouldRender() {
  48. return this.visible || !this.lazyRender;
  49. },
  50. placeholders: function placeholders() {
  51. var rows = [];
  52. var count = Math.ceil((this.totalDay + this.offset) / 7);
  53. for (var day = 1; day <= count; day++) {
  54. rows.push({
  55. type: 'placeholder'
  56. });
  57. }
  58. return rows;
  59. },
  60. days: function days() {
  61. var days = [];
  62. var year = this.date.getFullYear();
  63. var month = this.date.getMonth();
  64. for (var day = 1; day <= this.totalDay; day++) {
  65. var date = new Date(year, month, day);
  66. var type = this.getDayType(date);
  67. var config = {
  68. date: date,
  69. type: type,
  70. text: day,
  71. bottomInfo: this.getBottomInfo(type)
  72. };
  73. if (this.formatter) {
  74. config = this.formatter(config);
  75. }
  76. days.push(config);
  77. }
  78. return days;
  79. }
  80. },
  81. methods: {
  82. getHeight: function getHeight() {
  83. var _this$$el;
  84. return ((_this$$el = this.$el) == null ? void 0 : _this$$el.getBoundingClientRect().height) || 0;
  85. },
  86. scrollIntoView: function scrollIntoView(body) {
  87. var _this$$refs = this.$refs,
  88. days = _this$$refs.days,
  89. month = _this$$refs.month;
  90. var el = this.showSubtitle ? days : month;
  91. var scrollTop = el.getBoundingClientRect().top - body.getBoundingClientRect().top + body.scrollTop;
  92. setScrollTop(body, scrollTop);
  93. },
  94. getMultipleDayType: function getMultipleDayType(day) {
  95. var _this = this;
  96. var isSelected = function isSelected(date) {
  97. return _this.currentDate.some(function (item) {
  98. return compareDay(item, date) === 0;
  99. });
  100. };
  101. if (isSelected(day)) {
  102. var prevDay = getPrevDay(day);
  103. var nextDay = getNextDay(day);
  104. var prevSelected = isSelected(prevDay);
  105. var nextSelected = isSelected(nextDay);
  106. if (prevSelected && nextSelected) {
  107. return 'multiple-middle';
  108. }
  109. if (prevSelected) {
  110. return 'end';
  111. }
  112. return nextSelected ? 'start' : 'multiple-selected';
  113. }
  114. return '';
  115. },
  116. getRangeDayType: function getRangeDayType(day) {
  117. var _this$currentDate = this.currentDate,
  118. startDay = _this$currentDate[0],
  119. endDay = _this$currentDate[1];
  120. if (!startDay) {
  121. return '';
  122. }
  123. var compareToStart = compareDay(day, startDay);
  124. if (!endDay) {
  125. return compareToStart === 0 ? 'start' : '';
  126. }
  127. var compareToEnd = compareDay(day, endDay);
  128. if (compareToStart === 0 && compareToEnd === 0 && this.allowSameDay) {
  129. return 'start-end';
  130. }
  131. if (compareToStart === 0) {
  132. return 'start';
  133. }
  134. if (compareToEnd === 0) {
  135. return 'end';
  136. }
  137. if (compareToStart > 0 && compareToEnd < 0) {
  138. return 'middle';
  139. }
  140. },
  141. getDayType: function getDayType(day) {
  142. var type = this.type,
  143. minDate = this.minDate,
  144. maxDate = this.maxDate,
  145. currentDate = this.currentDate;
  146. if (compareDay(day, minDate) < 0 || compareDay(day, maxDate) > 0) {
  147. return 'disabled';
  148. }
  149. if (currentDate === null) {
  150. return;
  151. }
  152. if (type === 'single') {
  153. return compareDay(day, currentDate) === 0 ? 'selected' : '';
  154. }
  155. if (type === 'multiple') {
  156. return this.getMultipleDayType(day);
  157. }
  158. /* istanbul ignore else */
  159. if (type === 'range') {
  160. return this.getRangeDayType(day);
  161. }
  162. },
  163. getBottomInfo: function getBottomInfo(type) {
  164. if (this.type === 'range') {
  165. if (type === 'start' || type === 'end') {
  166. return t(type);
  167. }
  168. if (type === 'start-end') {
  169. return t('startEnd');
  170. }
  171. }
  172. },
  173. getDayStyle: function getDayStyle(type, index) {
  174. var style = {
  175. height: this.rowHeightWithUnit
  176. };
  177. if (type === 'placeholder') {
  178. style.width = '100%';
  179. return style;
  180. }
  181. if (index === 0) {
  182. style.marginLeft = 100 * this.offset / 7 + "%";
  183. }
  184. if (this.color) {
  185. if (type === 'start' || type === 'end' || type === 'start-end' || type === 'multiple-selected' || type === 'multiple-middle') {
  186. style.background = this.color;
  187. } else if (type === 'middle') {
  188. style.color = this.color;
  189. }
  190. }
  191. return style;
  192. },
  193. genTitle: function genTitle() {
  194. var h = this.$createElement;
  195. if (this.showMonthTitle) {
  196. return h("div", {
  197. "class": bem('month-title')
  198. }, [this.title]);
  199. }
  200. },
  201. genMark: function genMark() {
  202. var h = this.$createElement;
  203. if (this.showMark && this.shouldRender) {
  204. return h("div", {
  205. "class": bem('month-mark')
  206. }, [this.date.getMonth() + 1]);
  207. }
  208. },
  209. genDays: function genDays() {
  210. var h = this.$createElement;
  211. var days = this.shouldRender ? this.days : this.placeholders;
  212. return h("div", {
  213. "ref": "days",
  214. "attrs": {
  215. "role": "grid"
  216. },
  217. "class": bem('days')
  218. }, [this.genMark(), days.map(this.genDay)]);
  219. },
  220. genTopInfo: function genTopInfo(item) {
  221. var h = this.$createElement;
  222. var slot = this.$scopedSlots['top-info'];
  223. if (item.topInfo || slot) {
  224. return h("div", {
  225. "class": bem('top-info')
  226. }, [slot ? slot(item) : item.topInfo]);
  227. }
  228. },
  229. genBottomInfo: function genBottomInfo(item) {
  230. var h = this.$createElement;
  231. var slot = this.$scopedSlots['bottom-info'];
  232. if (item.bottomInfo || slot) {
  233. return h("div", {
  234. "class": bem('bottom-info')
  235. }, [slot ? slot(item) : item.bottomInfo]);
  236. }
  237. },
  238. genDay: function genDay(item, index) {
  239. var _this2 = this;
  240. var h = this.$createElement;
  241. var type = item.type;
  242. var style = this.getDayStyle(type, index);
  243. var disabled = type === 'disabled';
  244. var onClick = function onClick() {
  245. if (!disabled) {
  246. _this2.$emit('click', item);
  247. }
  248. };
  249. if (type === 'selected') {
  250. return h("div", {
  251. "attrs": {
  252. "role": "gridcell",
  253. "tabindex": -1
  254. },
  255. "style": style,
  256. "class": [bem('day'), item.className],
  257. "on": {
  258. "click": onClick
  259. }
  260. }, [h("div", {
  261. "class": bem('selected-day'),
  262. "style": {
  263. width: this.rowHeightWithUnit,
  264. height: this.rowHeightWithUnit,
  265. background: this.color
  266. }
  267. }, [this.genTopInfo(item), item.text, this.genBottomInfo(item)])]);
  268. }
  269. return h("div", {
  270. "attrs": {
  271. "role": "gridcell",
  272. "tabindex": disabled ? null : -1
  273. },
  274. "style": style,
  275. "class": [bem('day', type), item.className],
  276. "on": {
  277. "click": onClick
  278. }
  279. }, [this.genTopInfo(item), item.text, this.genBottomInfo(item)]);
  280. }
  281. },
  282. render: function render() {
  283. var h = arguments[0];
  284. return h("div", {
  285. "class": bem('month'),
  286. "ref": "month"
  287. }, [this.genTitle(), this.genDays()]);
  288. }
  289. });