import { shortcut, Widget, getDate, each, range, extend, isLeapYear, Date, StartOfWeek, checkDateVoid, map, createWidget, createItems, LogicFactory, Controller, getShortDayName, getOffsetDate, isNotEmptyString, parseInt } from "@/core"; /** * Created by GUY on 2015/8/28. * @class Calendar * @extends Widget */ @shortcut() export class Calendar extends Widget { static xtype = "bi.calendar"; static getPageByDateJSON (json) { const year = getDate().getFullYear(); const month = getDate().getMonth(); let page = (json.year - year) * 12; page += json.month - 1 - month; return page; } static getDateJSONByPage (v) { const months = getDate().getMonth(); let page = v; // 对当前page做偏移,使到当前年初 page = page + months; let year = parseInt(page / 12); if (page < 0 && page % 12 !== 0) { year--; } const month = page >= 0 ? (page % 12) : ((12 + page % 12) % 12); return { year: getDate().getFullYear() + year, month: month + 1, }; } _defaultConfig () { const conf = super._defaultConfig(...arguments); return extend(conf, { baseCls: "bi-calendar", logic: { dynamic: false, }, min: "1900-01-01", // 最小日期 max: "2099-12-31", // 最大日期 year: 2015, month: 8, day: 25, }); } _dateCreator (Y, M, D) { const { min, max } = this.options, log = {}, De = getDate(); const mins = min.match(/\d+/g); const maxs = max.match(/\d+/g); De.setFullYear(Y, M, D); log.ymd = [De.getFullYear(), De.getMonth(), De.getDate()]; const MD = Date._MD.slice(0); MD[1] = isLeapYear(log.ymd[0]) ? 29 : 28; // 日期所在月第一天 De.setFullYear(log.ymd[0], log.ymd[1], 1); // 是周几 log.FDay = De.getDay(); // 当前BI.StartOfWeek与周日对齐后的FDay是周几 const offSetFDay = (7 - StartOfWeek + log.FDay) % 7; // 当前月页第一天是几号 log.PDay = MD[M === 0 ? 11 : M - 1] - offSetFDay + 1; log.NDay = 1; const items = []; each(range(42), i => { const td = {}; let YY = log.ymd[0], MM = log.ymd[1] + 1, DD; // 上个月的日期 if (i < offSetFDay) { td.lastMonth = true; DD = i + log.PDay; // 上一年 MM === 1 && (YY -= 1); MM = MM === 1 ? 12 : MM - 1; } else if (i >= offSetFDay && i < offSetFDay + MD[log.ymd[1]]) { DD = i - offSetFDay + 1; if (i - offSetFDay + 1 === log.ymd[2]) { td.currentDay = true; } } else { td.nextMonth = true; DD = log.NDay++; MM === 12 && (YY += 1); MM = MM === 12 ? 1 : MM + 1; } if (checkDateVoid(YY, MM, DD, mins, maxs)[0]) { td.disabled = true; } td.text = DD; items.push(td); }); return items; } _init () { super._init(...arguments); const { year, month, day, logic } = this.options; const items = map(this._getWeekLabel(), (i, value) => { return { type: "bi.label", height: BI.SIZE_CONSANTS.LIST_ITEM_HEIGHT, text: value, }; }); const title = createWidget({ type: "bi.button_group", height: 44, items, layouts: [{ type: "bi.center", hgap: 5, vgap: 10, }], }); this.days = createWidget({ type: "bi.button_group", items: createItems(this._getItems(), {}), value: `${year}-${month}-${day}`, layouts: [LogicFactory.createLogic("table", extend({}, logic, { columns: 7, rows: 6, columnSize: [1 / 7, 1 / 7, 1 / 7, 1 / 7, 1 / 7, 1 / 7, 1 / 7], rowSize: BI.SIZE_CONSANTS.LIST_ITEM_HEIGHT + 8, }))], }); this.days.on(Controller.EVENT_CHANGE, (...args) => { this.fireEvent(Controller.EVENT_CHANGE, ...args); }); createWidget(extend({ element: this, }, LogicFactory.createLogic("vertical", extend({}, logic, { items: LogicFactory.createLogicItemsByDirection("top", title, { el: this.days, tgap: -5, }), })))); } _getWeekLabel () { return map(range(0, 7), (idx, v) => getShortDayName((v + StartOfWeek) % 7)); } isFrontDate () { const { year, month, min, max } = this.options; let Y = year; const M = month, De = getDate(), day = De.getDay(); Y = Y | 0; De.setFullYear(Y, M, 1); const newDate = getOffsetDate(De, -1 * (day + 1)); return !!checkDateVoid(newDate.getFullYear(), newDate.getMonth(), newDate.getDate(), min, max)[0]; } isFinalDate () { const { year, month, min, max } = this.options; let Y = year; const M = month, De = getDate(), day = De.getDay(); Y = Y | 0; De.setFullYear(Y, M, 1); const newDate = getOffsetDate(De, 42 - day); return !!checkDateVoid(newDate.getFullYear(), newDate.getMonth(), newDate.getDate(), min, max)[0]; } _getItems () { const o = this.options; const days = this._dateCreator(o.year, o.month - 1, o.day); const items = []; items.push(days.slice(0, 7)); items.push(days.slice(7, 14)); items.push(days.slice(14, 21)); items.push(days.slice(21, 28)); items.push(days.slice(28, 35)); items.push(days.slice(35, 42)); return map(items, (i, item) => map(item, (j, td) => { let month = td.lastMonth ? o.month - 1 : (td.nextMonth ? o.month + 1 : o.month); let year = o.year; if (month > 12) { month = 1; year++; } else if (month < 1) { month = 12; year--; } return extend(td, { type: "bi.calendar_date_item", once: false, forceSelected: true, value: `${year}-${month}-${td.text}`, disabled: td.disabled, cls: td.lastMonth || td.nextMonth ? "bi-tips" : "", lgap: 2, rgap: 2, tgap: 4, bgap: 4, // selected: td.currentDay }); })); } _populate() { this.days.populate(this._getItems()); } setMinDate (minDate) { const o = this.options; if (isNotEmptyString(o.min)) { o.min = minDate; this._populate(); } } setMaxDate (maxDate) { const o = this.options; if (isNotEmptyString(o.max)) { o.max = maxDate; this._populate(); } } setValue (ob) { this.days.setValue([`${ob.year}-${ob.month}-${ob.day}`]); } getValue () { const date = this.days.getValue()[0].match(/\d+/g); return { year: date[0] | 0, month: date[1] | 0, day: date[2] | 0, }; } }