const importAll = (r) => {
const subChildrens = {};
r.keys().forEach((key) => {
subChildrens[key.replace(/[^0-9]/g, '')] = r(key).default || r(key);
});
return subChildrens;
};
export default importAll(require.context('./holidaysAndFestivalsData', false, /(.js)|(.json)$/));
// 节假日数据读入
import holidaysAndFestivalsData from './readFile.js'
// 日历或日期选择插件数据来源以及操作映射
export const chunk = (arr, size) => {
return arr.length
? arr.reduce(
(res, cur) => (res[res.length - 1].length < size ? res[res.length - 1].push(cur) : res.push([cur]), res),
[[]]
)
: []
}
export const classNamesPrefix = (preFix, classNames) => {
return classNames.split(' ').map((item) => `${preFix}${item}`)
}
export const classNames = (...args) => {
const classes = []
const seen = new Set()
// 反向遍历确保后者优先
args.reverse().forEach(arg => {
if (!arg) return
if (typeof arg === 'string' || typeof arg === 'number') {
arg.toString().split(' ').forEach(c => {
if (c && !seen.has(c)) {
seen.add(c)
classes.unshift(c)
}
})
}
else if (Array.isArray(arg)) {
const result = classNames(...arg)
result.split(' ').forEach(c => {
if (c && !seen.has(c)) {
seen.add(c)
classes.unshift(c)
}
})
}
else if (typeof arg === 'object') {
for (const key in arg) {
if (arg[key] && !seen.has(key)) {
seen.add(key)
classes.unshift(key)
}
}
}
})
return classes.join(' ')
}
// 农历数据源
export const lunarCalendar = {
/* 源数据说明:
* lunarYear数据来自香港天文台提供的源数据反向推导得出,其中201项数据分别对应1900-2100年。
* 示例: 2021年 -- 0x06aa0
* ╭-------┰-------┰-------┰-------┰--------╮
* ┆ 0000 ┆ 0110 ┆ 1010 ┆ 1010 ┆ 0000 ┆
* ┠-------╊-------╊-------╊-------╊--------┨
* ┆ 20-17 ┆ 16-12 ┆ 12-9 ┆ 8-5 ┆ 4-1 ┆
* ╰-------┸-------┸-------┸-------┸--------╯
* 1-4: 表示当年有无闰年,有的话,为闰月的月份,没有的话,为0。 2021年无闰月
* 5-16:为除了闰月外的正常月份是大月还是小月,1为30天,0为29天。从1月到12月对应的是第16位到第5位,2021年各月天数[29,30,30,29,30,29,30,29,30,29,30,29]
* 17-20: 表示闰月是大月还是小月,仅当存在闰月的情况下有意义。(0/1,即闰大/小月)
*/
lunarYears: [
0x04bd8,
// 1901-2000
0x04ae0, 0x0a570, 0x054d5, 0x0d260, 0x0d950, 0x16554, 0x056a0, 0x09ad0, 0x055d2, 0x04ae0, 0x0a5b6, 0x0a4d0, 0x0d250,
0x1d255, 0x0b540, 0x0d6a0, 0x0ada2, 0x095b0, 0x14977, 0x04970, 0x0a4b0, 0x0b4b5, 0x06a50, 0x06d40, 0x1ab54, 0x02b60,
0x09570, 0x052f2, 0x04970, 0x06566, 0x0d4a0, 0x0ea50, 0x16a95, 0x05ad0, 0x02b60, 0x186e3, 0x092e0, 0x1c8d7, 0x0c950,
0x0d4a0, 0x1d8a6, 0x0b550, 0x056a0, 0x1a5b4, 0x025d0, 0x092d0, 0x0d2b2, 0x0a950, 0x0b557, 0x06ca0, 0x0b550, 0x15355,
0x04da0, 0x0a5b0, 0x14573, 0x052b0, 0x0a9a8, 0x0e950, 0x06aa0, 0x0aea6, 0x0ab50, 0x04b60, 0x0aae4, 0x0a570, 0x05260,
0x0f263, 0x0d950, 0x05b57, 0x056a0, 0x096d0, 0x04dd5, 0x04ad0, 0x0a4d0, 0x0d4d4, 0x0d250, 0x0d558, 0x0b540, 0x0b6a0,
0x195a6, 0x095b0, 0x049b0, 0x0a974, 0x0a4b0, 0x0b27a, 0x06a50, 0x06d40, 0x0af46, 0x0ab60, 0x09570, 0x04af5, 0x04970,
0x064b0, 0x074a3, 0x0ea50, 0x06b58, 0x05ac0, 0x0ab60, 0x096d5, 0x092e0, 0x0c960,
// 2001-2100
0x0d954, 0x0d4a0, 0x0da50, 0x07552, 0x056a0, 0x0abb7, 0x025d0, 0x092d0, 0x0cab5, 0x0a950, 0x0b4a0, 0x0baa4, 0x0ad50,
0x055d9, 0x04ba0, 0x0a5b0, 0x15176, 0x052b0, 0x0a930, 0x07954, 0x06aa0, 0x0ad50, 0x05b52, 0x04b60, 0x0a6e6, 0x0a4e0,
0x0d260, 0x0ea65, 0x0d530, 0x05aa0, 0x076a3, 0x096d0, 0x04afb, 0x04ad0, 0x0a4d0, 0x1d0b6, 0x0d250, 0x0d520, 0x0dd45,
0x0b5a0, 0x056d0, 0x055b2, 0x049b0, 0x0a577, 0x0a4b0, 0x0aa50, 0x1b255, 0x06d20, 0x0ada0, 0x14b63, 0x09370, 0x049f8,
0x04970, 0x064b0, 0x168a6, 0x0ea50, 0x06b20, 0x1a6c4, 0x0aae0, 0x092e0, 0x0d2e3, 0x0c960, 0x0d557, 0x0d4a0, 0x0da50,
0x05d55, 0x056a0, 0x0a6d0, 0x055d4, 0x052d0, 0x0a9b8, 0x0a950, 0x0b4a0, 0x0b6a6, 0x0ad50, 0x055a0, 0x0aba4, 0x0a5b0,
0x052b0, 0x0b273, 0x06930, 0x07337, 0x06aa0, 0x0ad50, 0x14b55, 0x04b60, 0x0a570, 0x054e4, 0x0d160, 0x0e968, 0x0d520,
0x0daa0, 0x16aa6, 0x056d0, 0x04ae0, 0x0a9d4, 0x0a2d0, 0x0d150, 0x0f252, 0x0d520,
],
// ['月','正','一','二','三','四','五','六','七','八','九','十','冬','腊']
ChinaMonths: [
'\u6708',
'\u6b63',
'\u4e8c',
'\u4e09',
'\u56db',
'\u4e94',
'\u516d',
'\u4e03',
'\u516b',
'\u4e5d',
'\u5341',
'\u51ac',
'\u814a',
],
// ['日','一','二','三','四','五','六','七','八','九','十']
ChinaDay: [
'\u65e5',
'\u4e00',
'\u4e8c',
'\u4e09',
'\u56db',
'\u4e94',
'\u516d',
'\u4e03',
'\u516b',
'\u4e5d',
'\u5341',
],
// ['初','十','廿','卅','闰']
ChinaElement: ['\u521d', '\u5341', '\u5eff', '\u5345', '\u95f0'],
// 农历日中文显示,参数日期day
toChinaDay(day) {
let str = ''
switch (day) {
case 10:
str = '\u521d\u5341'
break
case 20:
str = '\u5eff\u5341'
break
case 30:
str = '\u5345\u5341'
break
default:
str = this.ChinaElement[Math.floor(day / 10)] + this.ChinaDay[day % 10]
}
return str
},
// 农历月初一中文月显示(如农历二月初一 -> 二月,农历闰四月初一 ->闰四月)
toChinaMonth(month, isleap) {
isleap = isleap || false
return isleap
? this.ChinaElement[4] + this.ChinaMonths[month] + this.ChinaMonths[0]
: this.ChinaMonths[month] + this.ChinaMonths[0]
},
nowInfo() {
const now = new Date()
return {
y: now.getFullYear(),
m: now.getMonth() + 1,
d: now.getDate(),
}
},
// 某年农历闰月月份
leapMonth(year) {
year = year || this.nowInfo().y
return this.lunarYears[year - 1900] & 0xf
},
// 某年农历闰月天数
leapDays(year) {
year = year || this.nowInfo().y
if (this.leapMonth(year)) {
return this.lunarYears[year - 1900] & 0x10000 ? 30 : 29
}
return 0
},
// 某年份农历各月天数
lunarMonthDays(year) {
year = year || this.nowInfo().y
const lunarYear = this.lunarYears[year - 1900]
const monthDays = []
for (let i = 4
const monthDay = (lunarYear >> i) & 0x1 ? 30 : 29
monthDays.push(monthDay)
}
monthDays.reverse()
// 添加闰月
const leapM = this.leapMonth(year)
if (leapM) monthDays.splice(leapM, 0, this.leapDays(year))
return monthDays
},
// 某年农历天数
lunarYearDays(year) {
year = year || this.nowInfo().y
let num = 0
this.lunarMonthDays(year).forEach((item) => {
num += item
})
return num
},
solarToLunar(y, m, d) {
if (y < 1901 || y > 2100) return -1
let date
if (!y) {
date = new Date()
} else {
date = new Date(y, m - 1, d)
}
// 参照日期 1901-02-19 正月初一
let offset = (Date.UTC(date.getFullYear(), date.getMonth(), date.getDate()) - Date.UTC(1901, 1, 19)) / 86400000
let temp = 0
let i
for (i = 1901
temp = this.lunarYearDays(i)
offset -= temp
}
if (offset < 0) {
offset += temp
i--
}
// 农历年、月、日
let isLeap = false
let j = 1
const monthDays = this.lunarMonthDays(i)
const leapM = this.leapMonth(i)
if (offset > 0) {
for (j = 0
temp = monthDays[j]
offset -= temp
}
if (offset == 0) {
j++
}
if (offset < 0) {
offset += temp
}
} else {
// 补偿公历1901年2月的农历信息
if (offset == -23) {
return {
holidaysAndFestivalsData:
holidaysAndFestivalsData[y]?.holiday[`${calendar.format(`${y}-${m}=${d}`, 'MM-DD')}`],
lunarY: i,
lunarM: 12,
lunarMCn: this.toChinaMonth(j, false),
lunarD: 8,
lableLunarD: this.toChinaDay(8),
lunarDCn: this.toChinaDay(8),
isLeap: false,
}
}
}
// 矫正闰年月
if (leapM) {
if (j == leapM + 1) {
isLeap = true
}
if (j >= leapM + 1) {
j--
}
}
const curD = ++offset
return {
holidaysAndFestivalsData: holidaysAndFestivalsData[y]?.holiday[`${calendar.format(`${y}-${m}=${d}`, 'MM-DD')}`],
lunarY: i,
lunarM: j,
lunarMCn: this.toChinaMonth(j, isLeap),
lunarD: curD,
lableLunarD: curD === 1 ? this.toChinaMonth(j, isLeap) : this.toChinaDay(curD),
lunarDCn: this.toChinaDay(curD),
isLeap,
}
},
}
// 日历或日期选择插件数据来源工具类
export const calendar = {
monthsCn: ['一月', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月', '十月', '十一月', '十二月'],
weekDayCn: ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六'],
weekDaySimplifiedCn: ['日', '一', '二', '三', '四', '五', '六'],
getweek(date) {
// 获取星期几
date = date ? new Date(date) : new Date()
return ['一', '二', '三', '四', '五', '六', '日'][date.getDay() - 1]
},
getDayWeekCn(index) {
// 获取星期几
return this.weekDayCn[index]
},
getDayWeekCnSimplified(index) {
// 获取星期几
return this.weekDaySimplifiedCn[index]
},
getYearMonthDatas(year) {
return [31, this.isLeapYear(year) ? 29 : 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
},
getMonthCn(month) {
return this.monthsCn[month - 1]
},
getFragmentYear(startYear, endYear, fragmentLength = 10) {
// fragmentLength固定为10
// 生成 4*3 12格数据 10年期
endYear = endYear || startYear + 10
const startS = startYear - 1
const startE = startYear + fragmentLength
return [
{
...getSplitValueData(startS, 'year'),
label: startS,
alt: startS,
curType: 'pre',
cur: false,
},
...new Array(endYear - startYear).fill(0).map((_, index) => {
const startC = startYear + index;
return {
...getSplitValueData(startC, 'year'),
label: startC,
alt: startC,
cur: true,
};
}),
{
...getSplitValueData(startE, 'year'),
label: startE,
alt: startE,
curType: 'next',
cur: false,
},
]
},
getFragmentYears(startYear, fragmentLength = 10, preFragment = 1) {
// fragmentLength最大10
// 生成 4*3 12格数据 100年期 10年纪
let startYearWith = this.getYearStartFragmentYear(startYear) - fragmentLength * preFragment
const map = {}
const list = this.monthsCn.slice(0, fragmentLength + 2).map((_, index) => {
map[startYearWith] = {
cur: index > 0 && index < fragmentLength + 1,
curType: index === 0 ? 'pre' : index === fragmentLength + 1 ? 'next' : '',
start: startYearWith,
end: startYearWith + fragmentLength - 1,
alt: `${startYearWith}-${startYearWith + fragmentLength - 1}`,
label: `${startYearWith}-${startYearWith + fragmentLength - 1}`,
}
const res = map[startYearWith]
startYearWith += fragmentLength
return res
})
return {
list,
map,
}
},
getYearStartFragmentYear(year) {
// 获取year所在的以整十开始的年份
return Math.floor(year / 10) * 10
},
getToday(toDay) {
// 获取toDay的数据
const today = toDay || new Date()
return {
year: this.format(today, 'YYYY', true),
month: this.format(today, 'MM', true),
day: this.format(today, 'DD', true),
date: this.format(today, 'YYYY-MM-DD hh:mm:ss'),
}
},
getYearsData(startYear, endYear) {
const map = {}
const list = new Array(endYear - startYear + 1).fill(0).map((_, index) => {
map[startYear + index] = this.getYearData(startYear + index)
return map[startYear + index]
})
return {
map,
list,
}
},
getYearData(year) {
const map = {}
const list = this.monthsCn.map((_, index) => {
map[index + 1] = this.getYearMonthData(year, index + 1)
return map[index + 1]
})
return {
map,
list,
}
},
getYearMonthData(year, month) {
// 获取year month 渲染dom所有数据
month = parseInt(month)
if (!year || year.toString().length !== 4) {
const now = new Date()
year = now.getFullYear()
}
if (!month) {
const now = new Date()
month = now.getMonth() + 1
}
return this.getMonthData(year, month, this.getMonthHaveDays(year, month))
},
getMonthData(year, month, days) {
// 获取year month 渲染dom数据
const self = this
const firstdayweek = self.getDayWeek(new Date(`${year.toString()}-${month}-${1}`))
const monthobj = {
year,
month,
monthCn: self.getMonthCn(month),
monthdata: [],
monthalldata: [],
firstdayweek,
firstdayweekcn: self.getDayWeekCn(firstdayweek),
firstdayweekcnSimplified: self.getDayWeekCnSimplified(firstdayweek),
}
for (let i = 1
monthobj.monthdata.push(self.getDayData(year, month, i, true))
} // 获取year month 月数据
monthobj.monthalldata = self.getMonthAllData(year, month, JSON.parse(JSON.stringify(monthobj.monthdata)))
monthobj.renderMonthalldata = chunk(monthobj.monthalldata, 7)
return monthobj
},
getMonthAllData(year, month, monthdata) {
// 获取year month 渲染dom 所有数据,5*7 35或6*7格||或7*7格数据
const self = this
const count = self.getCount(monthdata)
if (monthdata[0].week === 0) {
// 本月1号为周日,补充下月数据,凑够5*7 35格数据
const curlength = monthdata.length
for (let i = 1
monthdata.push(
self.getDayData(month + 1 > 12 ? year + 1 : year, month + 1 > 12 ? 1 : month + 1, i, false, 'next')
)
}
} else {
// 本月1号不是周日,补充上月和下月数据,凑够**7 格数据
const prevmonthdays = self.getMonthHaveDays(month - 1 <= 0 ? year - 1 : year, month - 1 <= 0 ? 12 : month - 1)
const firstweek = monthdata[0].week
for (let i = prevmonthdays
monthdata.unshift(
self.getDayData(month - 1 <= 0 ? year - 1 : year, month - 1 <= 0 ? 12 : month - 1, i, false, 'pre')
)
}
const curandprevdays = monthdata.length
for (let j = 1
monthdata.push(
self.getDayData(month + 1 > 12 ? year + 1 : year, month + 1 > 12 ? 1 : month + 1, j, false, 'next')
)
}
}
return monthdata
},
getCount(monthdata) {
return Math.ceil((monthdata[0].week + monthdata.length) / 7) * 7
},
getDayData(year, month, day, cur, curType) {
// 获取某天数据
const self = this
const week = self.getDayWeek(new Date(`${year.toString()}-${month}-${day}`))
const date = `${year}-${month}-${day}`
const daydata = {
date: self.format(date, 'YYYY-MM-DD'),
dates: self.format(date, 'YYYY-MM-DD hh:mm:ss'),
quarter: self.format(date, 'Q', true),
year,
month,
day,
weekcn: self.getDayWeekCn(week),
weekcnSimplified: self.getDayWeekCnSimplified(week),
week,
cur,
curType,
label: day,
alt: self.format(date, 'YYYY年M月D日'),
...lunarCalendar.solarToLunar(year, month, day),
}
return daydata
},
getMonthHaveDays(year, month) {
// 获取某月有多少天
return this.getYearMonthDatas(year)[+month - 1]
},
getDayWeek(date) {
// 获取某一天是星期几 data:new Date("2015-7-12")
return date.getDay()
},
isLeapYear(year) {
// 是否为闰年
const cond1 = year % 4 === 0
const cond2 = year % 100 !== 0
const cond3 = year % 400 === 0
// 当条件1和条件2同时成立时,就肯定是闰年,所以条件1和条件2之间为“与”的关系。
// 如果条件1和条件2不能同时成立,但如果条件3能成立,则仍然是闰年。所以条件3与前2项为“或”的关系。
// 所以得出判断闰年的表达式:
const cond = (cond1 && cond2) || cond3
if (cond) {
return true
}
return false
},
format(dateS, format, formatToNumber) {
// example new Date().format( "当前日期为:YYYY-MM-DD,星期W,为第Q季度,时间为:hh:mm:ss:c")
const date = new Date(String(dateS) || '')
const o = {
'Y+': `${date.getFullYear()}`,
'M+': date.getMonth() + 1, // month MM
'D+': date.getDate(), // day DD
'h+': date.getHours(), // hour hh
'm+': date.getMinutes(), // minute mm
's+': date.getSeconds(), // second ss
'Q+': Math.floor(date.getMonth() / 3) + 1, // quarter 季度 q
'c+': date.getMilliseconds(), // millisecond 毫秒 c
W: ['一', '二', '三', '四', '五', '六', '日'][date.getDay() - 1], // week 星期
}
for (const k in o) {
if (new RegExp(`(${k})`).test(format)) {
format = format.replace(
RegExp.$1,
RegExp.$1.length == 1 ? o[k] : `00${o[k]}`.substr(`${o[k]}`.length >= 2 ? 2 : `${o[k]}`.length)
)
}
}
return formatToNumber ? Number(format) : format
},
distanceTime(someTime, otherTime) {
// 获取someTime到otherTime或此刻的时间间隔
let me = this
let startDate = new Date(someTime)
let endDate = otherTime ? new Date(otherTime) : new Date()
let type = '-'
let t = endDate.getTime() - startDate.getTime()
if (t < 0) {
t = startDate.getTime() - endDate.getTime()
type = ''
}
let d = 0
let h = 0
let m = 0
let s = 0
d = Math.floor(t / 1000 / 3600 / 24)
h = Math.floor((t / 1000 / 60 / 60) % 24)
m = Math.floor((t / 1000 / 60) % 60)
s = Math.floor((t / 1000) % 60)
const res = {
startDate: me.format(startDate, 'YYYY-MM-DD hh:mm:ss'),
endDate: me.format(endDate, 'YYYY-MM-DD hh:mm:ss'),
type,
days: d,
hours: h,
minutes: m,
seconds: s,
}
res.result = `${d}天${h}小时${m}分钟${s}秒`
return res
},
getBetweenDates(startDate, engDate) {
// 获取两个日期之间的datelist
const me = this
const startDateInfo = this.getToday(startDate)
const endDateInfo = this.getToday(engDate)
const dateSource = {
startYear: startDateInfo.year,
startMonth: startDateInfo.month,
startDay: startDateInfo.day,
endYear: endDateInfo.year,
endMonth: endDateInfo.month,
endDay: endDateInfo.day,
startYearMonth: me.getYearMonthDatas(startDateInfo.year),
endYearMonth: me.getYearMonthDatas(endDateInfo.year),
}
const list = []
new Array(dateSource.endYear - dateSource.startYear + 1)
.fill(0)
.map((_, index) => {
return +dateSource.startYear + index + 1
})
.forEach((year) => {
this.monthsCn.reduce((res, _, index) => {
list.push(...this.getYearMonthData(year, index + 1).monthdata)
return res
}, {})
})
// 掐头去尾
const removeStartLength = dateSource.startYearMonth
.slice(0, Number(dateSource.startMonth))
.reduce((res, next, index) => {
if (index + 1 !== Number(dateSource.startMonth)) {
res = res + next
} else {
res = res + dateSource.startDay - 1
}
return res
}, 0)
const removeEndLength = dateSource.endYearMonth
.slice(Number(dateSource.endMonth - 1), 12)
.reduce((res, next, index) => {
if (index) {
res = res + next
} else {
res = res + next - dateSource.endDay
}
return res
}, 0)
return list.splice(removeStartLength, list.length - removeEndLength - removeStartLength)
},
getYearOfDay(time) {
/* 获取某年有多少天 */
let firstDayYear = this.getFirstDayOfYear(time)
let lastDayYear = this.getLastDayOfYear(time)
let numSecond = (new Date(lastDayYear).getTime() - new Date(firstDayYear).getTime()) / 1000
return Math.ceil(numSecond / (24 * 3600))
},
getFirstDayOfYear(time) {
/* 获取某年的第一天 */
let year = new Date(time).getFullYear()
return year + '-01-01 00:00:00'
},
getLastDayOfYear(time) {
/* 获取某年最后一天 */
let year = new Date(time).getFullYear()
return year + '-12-31' + ' 23:59:59'
},
getDayOfYear(time) {
/* 获取某个日期是当年中的第几天 */
return Math.ceil(
(new Date(time).getTime() - new Date(this.getFirstDayOfYear(time)).getTime()) / 1000 / (24 * 3600)
)
},
getDayOfYearWeek(time) {
/* 获取某个日期在这一年的第几周 */
return Math.ceil(this.getDayOfYear(time) / 7)
},
}
export default calendar
// 面板类型选择顺序
export const panelTypeSort = ['century', 'year', 'month', 'date', 'hour', 'minute', 'second']
// 面板类型渲然数据源映射
export const panelTypeMap = {
century: {
// 世纪
mode: 'century',
title: '选择世纪',
cols: 3,
rows: 4,
preL: '上一世纪',
nextR: '下一世纪',
topToMode: 'century',
bodyToMode: 'year',
typeToMode: ['century'],
preLClick({ startYears, startYear, year }) {
return {
startYears: startYears - 100,
endYears: startYears - 1,
startYear: startYear - 100,
endYear: startYear - 91,
}
},
nextRClick({ startYear, startYears, year }) {
return {
startYears: startYears + 100,
endYears: startYears + 199,
startYear: startYear + 100,
endYear: startYear + 109,
}
},
bodyClick(_, { start, end }) {
return {
startYear: start,
endYear: end,
year: start,
curSelectType: 'year',
}
},
getBodyCellRenderProps(curRenderDataSource, obj) {
const { year } = curRenderDataSource
return {
ariaDisabled: false,
ariaSelected: Math.floor(year / 100) * 100 === obj.start,
}
},
getCellRenderClass({ isCalendarPanel }, { cur, curType }, { ariaSelected }) {
return {
td: classNames(
'year-panel-cell',
ariaSelected && cur && 'year-panel-selected-cell',
curType === 'pre' && 'year-panel-last-decade-cell',
curType === 'next' && 'year-panel-next-decade-cell',
isCalendarPanel && 'calendar-cell'
),
cell: 'year-panel-year',
}
},
renderClass: {
root: 'picker-container picker-century',
pnelbox: 'ant-calendar',
paneContent: 'panel',
mainpanel: 'decade-panel',
header: 'decade-panel-header',
preL: 'decade-panel-prev-century-btn',
nextR: 'decade-panel-next-century-btn',
headercenter: 'decade-panel-century',
headercenterC: 'decade-panel-century-content',
body: 'decade-panel-body',
table: 'decade-panel-table',
tbody: 'decade-panel-tbody',
},
getRenderData({ startYears }) {
const { list, map } = calendar.getFragmentYears(startYears)
return {
thead: null,
data: list,
map,
tbody: chunk(list, 3),
}
},
},
year: {
mode: 'year',
title: '选择年代',
cols: 3,
rows: 4,
preL: '上一年代',
nextR: '下一年代',
topToMode: 'century',
bodyToModemonth: 'month',
bodyTodate: 'date',
bodyToMode: 'date',
typeToMode: ['century', 'year'],
format: 'YYYY', // MM
pattern: /^(2[0-9]{3})|(19[0-9]{2})$/, // 1999-2999
preLClick({ startYear, endYear }) {
startYear -= 10
const startYears = Math.floor(startYear / 100) * 100
return {
startYears,
endYears: startYears + 99,
startYear,
endYear: endYear - 10,
}
},
nextRClick({ startYear, endYear }) {
startYear += 10
const startYears = Math.floor(startYear / 100) * 100
return {
startYears,
endYears: startYears + 99,
startYear,
endYear: endYear + 10,
}
},
bodyClick(curRenderDataSource, obj, tprops) {
const { type } = curRenderDataSource
const { year } = obj
if (panelTypeMap[type].typeToMode.includes('date')) {
return {
year,
curSelectType: 'date',
}
}
if (type === 'month') {
return {
year,
curSelectType: 'month',
}
}
return panelTypeMap.date.bodyClick(curRenderDataSource, obj, tprops)
},
getBodyCellRenderProps(curRenderDataSource, obj, { disabledDate }) {
const { year, type, result } = curRenderDataSource
const { date, cur } = obj
if (type === 'year') {
return {
ariaDisabled: disabledDate(obj, curRenderDataSource) || !cur,
ariaSelected: result.values.includes(date),
}
}
return {
ariaDisabled: false,
ariaSelected: year === obj.year,
}
},
getCellRenderClass({ isCalendarPanel }, obj, { ariaSelected }) {
const { cur, curType } = obj
return {
td: classNames(
'year-panel-cell',
getIsToday(obj, 'year') && 'today',
curType === 'pre' && 'year-panel-last-decade-cell',
curType === 'next' && 'year-panel-next-decade-cell',
ariaSelected && cur && 'year-panel-selected-cell',
isCalendarPanel && 'calendar-cell'
),
cell: 'year-panel-year',
}
},
renderClass: {
root: 'picker-container pickercentury',
pnelbox: 'ant-calendar',
paneContent: 'panel',
mainpanel: 'year-panel',
header: 'year-panel-header',
preL: 'year-panel-prev-decade-btn',
nextR: 'year-panel-next-decade-btn',
headercenter: 'year-panel-decade-select',
headercenterC: 'year-panel-decade-select-content',
th: 'column-header',
thCell: 'column-header-inner',
body: 'year-panel-body',
table: 'year-panel-table',
tbody: 'year-panel-tbody',
},
getRenderData({ startYear }) {
const data = calendar.getFragmentYear(startYear)
return {
thead: null,
data,
tbody: chunk(data, 3),
}
},
},
month: {
mode: 'month',
title: '选择月份',
cols: 3,
rows: 4,
preL: '上一年份',
nextR: '下一年份',
topToMode: 'year',
bodyToMode: 'date',
typeToMode: ['century', 'year', 'month'],
format: 'YYYY-MM', // MM
pattern: /^((0?[1-9])|(1[0-2]))$/, // 0-12
preLClick({ year }) {
year -= 1
const startYears = Math.floor(year / 100) * 100
const startYear = Math.floor(year / 10) * 10
return {
startYears,
endYears: startYears + 99,
startYear,
endYear: startYear + 9,
year,
}
},
nextRClick({ year }) {
year += 1
const startYears = Math.floor(year / 100) * 100
const startYear = Math.floor(year / 10) * 10
return {
startYears,
endYears: startYears + 99,
startYear,
endYear: startYear + 9,
year,
}
},
bodyClick(curRenderDataSource, obj, tprops) {
const { type } = curRenderDataSource
const { month } = obj
if (panelTypeMap[type].typeToMode.includes('date')) {
return {
month,
curSelectType: 'date',
}
}
return panelTypeMap.date.bodyClick(curRenderDataSource, obj, tprops)
},
getBodyCellRenderProps(curRenderDataSource, obj, { disabledDate }) {
const { month, type, result } = curRenderDataSource
const { date } = obj
if (type === 'month') {
return {
ariaDisabled: disabledDate(obj, curRenderDataSource),
ariaSelected: result.values.includes(date),
}
}
return {
ariaDisabled: false,
ariaSelected: month === obj.month,
}
},
renderClass: {
root: 'picker-container pickercentury',
pnelbox: 'ant-calendar',
paneContent: 'panel',
mainpanel: 'month-panel',
header: 'month-panel-header',
preL: 'month-panel-prev-year-btn',
nextR: 'month-panel-next-year-btn',
headercenter: 'year-panel-decade-select',
headercenterC: 'year-panel-decade-select-content',
body: 'month-panel-body',
table: 'month-panel-table',
tbody: 'month-panel-tbody',
},
getCellRenderClass({ isCalendarPanel }, obj, { ariaSelected }) {
return {
td: classNames(
'month-panel-cell',
getIsToday(obj, 'month') && 'today',
ariaSelected && 'month-panel-selected-cell',
isCalendarPanel && 'calendar-cell'
),
cell: 'month-panel-month',
}
},
getRenderData({ year }) {
const data = calendar.monthsCn.map((item, index) => ({
label: item,
alt: `${year}年${index + 1}月`,
...getSplitValueData(`${year}-${index + 1}`, 'month'),
}))
return {
thead: null,
data,
tbody: chunk(data, 3),
}
},
},
date: {
mode: 'date',
title: '选择日期',
cols: 7,
// preL: '上一年 (Control键加左方向键)',
// pre: '上个月 (翻页上键)',
// next: '下个月 (翻页下键)',
// nextR: '下一年 (Control键加右方向键)',
preL: '上一年',
pre: '上个月',
next: '下个月',
nextR: '下一年',
topToMode_pre: 'year',
bodyToMode_next: 'month',
format: 'YYYY-MM-DD',
typeToMode: ['century', 'year', 'month', 'date'],
pattern: /^((2[0-9]{3})|(19[0-9]{2}))-((0[1-9])|(1[0-2]))-((0[1-9])|([1-2][0-9])|(3[0-1]))$/, // "1900-01-01"---"2999-12-31"
preLClick({ year }) {
year -= 1
const startYears = Math.floor(year / 100) * 100
const startYear = Math.floor(year / 10) * 10
return {
startYears,
endYears: startYears + 99,
startYear,
endYear: startYear + 9,
year,
}
},
nextRClick({ year }) {
year += 1
const startYears = Math.floor(year / 100) * 100
const startYear = Math.floor(year / 10) * 10
return {
startYears,
endYears: startYears + 99,
startYear,
endYear: startYear + 9,
year,
}
},
preClick({ month, year }) {
return {
month: month === 1 ? 12 : month - 1,
year: month === 1 ? year - 1 : year,
}
},
nextClick({ month, year }) {
return {
month: month === 12 ? 1 : month + 1,
year: month === 12 ? year + 1 : year,
}
},
bodyClick(obj, item, { mode, isCalendarPanel }) {
if (isCalendarPanel) {
return {}
}
const { map, list, values } = obj.result
const { date, year, month, day } = item
if (mode !== 'multiple' && mode !== 'tags') {
const resOne = {
index: 0,
date,
year,
month,
day,
}
obj.result = {
map: {
[date]: resOne,
},
list: [resOne],
values: [date],
str: date,
}
return obj
}
if (map[date]) {
list.splice(
list.findIndex((item) => item.date === date),
1
)
values.splice(
values.findIndex((item) => item === date),
1
)
delete map[date]
} else {
map[date] = {
date,
year,
month,
day,
}
list.push(map[date])
values.push(date)
}
obj.result.str = values.join(',')
return obj
},
getBodyCellRenderProps(curRenderDataSource, obj, { disabledDate }) {
const { result } = curRenderDataSource
const { date, cur } = obj
return {
ariaDisabled: disabledDate(obj, curRenderDataSource) || !cur,
ariaSelected: result.values.includes(date),
}
},
renderClass: {
root: 'picker-container picker-century',
pnelbox: 'ant-calendar',
paneContent: 'panel',
mainpanel: 'date-panel',
header: 'header',
preL: 'prev-year-btn',
pre: 'prev-month-btn',
headercenter: 'ym-select',
headercenterL: 'year-select',
headercenterR: 'month-select',
next: 'next-month-btn',
nextR: 'next-year-btn',
body: 'body',
table: 'table',
tbody: 'tbody',
},
getCellRenderClass({ isCalendarPanel }, obj, { ariaSelected }) {
const { cur, curType } = obj
const res = {
td: classNames(
'cell',
getIsToday(obj, 'date') && 'today',
ariaSelected && cur && 'selected-date selected-day',
curType === 'pre' && 'last-month-cell last-day-of-month',
curType === 'next' && 'last-month-cell next-day-of-month'
),
cell: classNames(isCalendarPanel ? 'calendar' : 'date'),
}
return res
},
getRenderData({ year, month, isCalendarPanel }) {
const res = calendar.getYearMonthData(year, month)
return {
thead: calendar.weekDaySimplifiedCn.map((item, index) => ({
value: index === 0 ? 7 : index,
label: isCalendarPanel ? calendar.weekDayCn[index] : item,
month: item,
})),
data: res,
tbody: res.renderMonthalldata,
}
},
},
hour: {
mode: 'hour',
title: '时',
},
minute: {
mode: 'minute',
title: '分',
},
second: {
mode: 'second',
title: '秒',
},
}
// 获取初始value数据
export const getSplitValueData = (value, type) => {
const { year, month, day } = calendar.getToday(String(value))
return {
year,
month,
day,
date: calendar.format(value, panelTypeMap[type].format),
}
}
export const getDefaultValueMap = (value, mode, type) => {
value = mode === 'multiple' || mode === 'tags' ? (value && Array.isArray(value) ? value : []) : value ? [value] : []
return value.reduce(
(res, next) => {
res.map[next] = getSplitValueData(next, type)
res.map[next].index = res.list.length
res.list.push(res.map[next])
res.values.push(res.map[next].date)
res.str = res.str ? `${res.str},${res.map[next].date}` : res.map[next].date
return res
},
{
values: [],
str: '',
map: {},
list: [],
}
)
}
export const getIsToday = ({ date }, type) => {
const today = calendar.getToday()
const format = (type && panelTypeMap[type]?.format) || 'YYYY-MM-DD'
return calendar.format(today.date, format) === calendar.format(date, format)
}