平安校园
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

422 lines
9.8 KiB

  1. class Calendar {
  2. constructor({
  3. selected,
  4. startDate,
  5. endDate,
  6. range,
  7. } = {}) {
  8. // 当前日期
  9. this.date = this.getDateObj(new Date()) // 当前初入日期
  10. // 打点信息
  11. this.selected = selected || [];
  12. // 起始时间
  13. this.startDate = startDate
  14. // 终止时间
  15. this.endDate = endDate
  16. // 是否范围选择
  17. this.range = range
  18. // 多选状态
  19. this.cleanMultipleStatus()
  20. // 每周日期
  21. this.weeks = {}
  22. this.lastHover = false
  23. }
  24. /**
  25. * 设置日期
  26. * @param {Object} date
  27. */
  28. setDate(date) {
  29. const selectDate = this.getDateObj(date)
  30. this.getWeeks(selectDate.fullDate)
  31. }
  32. /**
  33. * 清理多选状态
  34. */
  35. cleanMultipleStatus() {
  36. this.multipleStatus = {
  37. before: '',
  38. after: '',
  39. data: []
  40. }
  41. }
  42. setStartDate(startDate) {
  43. this.startDate = startDate
  44. }
  45. setEndDate(endDate) {
  46. this.endDate = endDate
  47. }
  48. getPreMonthObj(date) {
  49. date = fixIosDateFormat(date)
  50. date = new Date(date)
  51. const oldMonth = date.getMonth()
  52. date.setMonth(oldMonth - 1)
  53. const newMonth = date.getMonth()
  54. if (oldMonth !== 0 && newMonth - oldMonth === 0) {
  55. date.setMonth(newMonth - 1)
  56. }
  57. return this.getDateObj(date)
  58. }
  59. getNextMonthObj(date) {
  60. date = fixIosDateFormat(date)
  61. date = new Date(date)
  62. const oldMonth = date.getMonth()
  63. date.setMonth(oldMonth + 1)
  64. const newMonth = date.getMonth()
  65. if (newMonth - oldMonth > 1) {
  66. date.setMonth(newMonth - 1)
  67. }
  68. return this.getDateObj(date)
  69. }
  70. /**
  71. * 获取指定格式Date对象
  72. */
  73. getDateObj(date) {
  74. date = fixIosDateFormat(date)
  75. date = new Date(date)
  76. return {
  77. fullDate: getDate(date),
  78. year: date.getFullYear(),
  79. month: addZero(date.getMonth() + 1),
  80. date: addZero(date.getDate()),
  81. day: date.getDay()
  82. }
  83. }
  84. /**
  85. * 获取上一个月日期集合
  86. */
  87. getPreMonthDays(amount, dateObj) {
  88. const result = []
  89. for (let i = amount - 1; i >= 0; i--) {
  90. const month = dateObj.month - 1
  91. result.push({
  92. date: new Date(dateObj.year, month, -i).getDate(),
  93. month,
  94. disable: true
  95. })
  96. }
  97. return result
  98. }
  99. /**
  100. * 获取本月日期集合
  101. */
  102. getCurrentMonthDays(amount, dateObj) {
  103. const result = []
  104. const fullDate = this.date.fullDate
  105. for (let i = 1; i <= amount; i++) {
  106. const currentDate = `${dateObj.year}-${dateObj.month}-${addZero(i)}`
  107. const isToday = fullDate === currentDate
  108. // 获取打点信息
  109. const info = this.selected && this.selected.find((item) => {
  110. if (this.dateEqual(currentDate, item.date)) {
  111. return item
  112. }
  113. })
  114. // 日期禁用
  115. let disableBefore = true
  116. let disableAfter = true
  117. if (this.startDate) {
  118. disableBefore = dateCompare(this.startDate, currentDate)
  119. }
  120. if (this.endDate) {
  121. disableAfter = dateCompare(currentDate, this.endDate)
  122. }
  123. let multiples = this.multipleStatus.data
  124. let multiplesStatus = -1
  125. if (this.range && multiples) {
  126. multiplesStatus = multiples.findIndex((item) => {
  127. return this.dateEqual(item, currentDate)
  128. })
  129. }
  130. const checked = multiplesStatus !== -1
  131. result.push({
  132. fullDate: currentDate,
  133. year: dateObj.year,
  134. date: i,
  135. multiple: this.range ? checked : false,
  136. beforeMultiple: this.isLogicBefore(currentDate, this.multipleStatus.before, this.multipleStatus.after),
  137. afterMultiple: this.isLogicAfter(currentDate, this.multipleStatus.before, this.multipleStatus.after),
  138. month: dateObj.month,
  139. disable: (this.startDate && !dateCompare(this.startDate, currentDate)) || (this.endDate && !dateCompare(
  140. currentDate, this.endDate)),
  141. isToday,
  142. userChecked: false,
  143. extraInfo: info
  144. })
  145. }
  146. return result
  147. }
  148. /**
  149. * 获取下一个月日期集合
  150. */
  151. _getNextMonthDays(amount, dateObj) {
  152. const result = []
  153. const month = dateObj.month + 1
  154. for (let i = 1; i <= amount; i++) {
  155. result.push({
  156. date: i,
  157. month,
  158. disable: true
  159. })
  160. }
  161. return result
  162. }
  163. /**
  164. * 获取当前日期详情
  165. * @param {Object} date
  166. */
  167. getInfo(date) {
  168. if (!date) {
  169. date = new Date()
  170. }
  171. return this.calendar.find(item => item.fullDate === this.getDateObj(date).fullDate)
  172. }
  173. /**
  174. * 比较时间是否相等
  175. */
  176. dateEqual(before, after) {
  177. before = new Date(fixIosDateFormat(before))
  178. after = new Date(fixIosDateFormat(after))
  179. return before.valueOf() === after.valueOf()
  180. }
  181. /**
  182. * 比较真实起始日期
  183. */
  184. isLogicBefore(currentDate, before, after) {
  185. let logicBefore = before
  186. if (before && after) {
  187. logicBefore = dateCompare(before, after) ? before : after
  188. }
  189. return this.dateEqual(logicBefore, currentDate)
  190. }
  191. isLogicAfter(currentDate, before, after) {
  192. let logicAfter = after
  193. if (before && after) {
  194. logicAfter = dateCompare(before, after) ? after : before
  195. }
  196. return this.dateEqual(logicAfter, currentDate)
  197. }
  198. /**
  199. * 获取日期范围内所有日期
  200. * @param {Object} begin
  201. * @param {Object} end
  202. */
  203. geDateAll(begin, end) {
  204. var arr = []
  205. var ab = begin.split('-')
  206. var ae = end.split('-')
  207. var db = new Date()
  208. db.setFullYear(ab[0], ab[1] - 1, ab[2])
  209. var de = new Date()
  210. de.setFullYear(ae[0], ae[1] - 1, ae[2])
  211. var unixDb = db.getTime() - 24 * 60 * 60 * 1000
  212. var unixDe = de.getTime() - 24 * 60 * 60 * 1000
  213. for (var k = unixDb; k <= unixDe;) {
  214. k = k + 24 * 60 * 60 * 1000
  215. arr.push(this.getDateObj(new Date(parseInt(k))).fullDate)
  216. }
  217. return arr
  218. }
  219. /**
  220. * 获取多选状态
  221. */
  222. setMultiple(fullDate) {
  223. if (!this.range) return
  224. let {
  225. before,
  226. after
  227. } = this.multipleStatus
  228. if (before && after) {
  229. if (!this.lastHover) {
  230. this.lastHover = true
  231. return
  232. }
  233. this.multipleStatus.before = fullDate
  234. this.multipleStatus.after = ''
  235. this.multipleStatus.data = []
  236. this.multipleStatus.fulldate = ''
  237. this.lastHover = false
  238. } else {
  239. if (!before) {
  240. this.multipleStatus.before = fullDate
  241. this.multipleStatus.after = undefined;
  242. this.lastHover = false
  243. } else {
  244. this.multipleStatus.after = fullDate
  245. if (dateCompare(this.multipleStatus.before, this.multipleStatus.after)) {
  246. this.multipleStatus.data = this.geDateAll(this.multipleStatus.before, this.multipleStatus
  247. .after);
  248. } else {
  249. this.multipleStatus.data = this.geDateAll(this.multipleStatus.after, this.multipleStatus
  250. .before);
  251. }
  252. this.lastHover = true
  253. }
  254. }
  255. this.getWeeks(fullDate)
  256. }
  257. /**
  258. * 鼠标 hover 更新多选状态
  259. */
  260. setHoverMultiple(fullDate) {
  261. //抖音小程序点击会触发hover事件,需要避免一下
  262. // #ifndef MP-TOUTIAO
  263. if (!this.range || this.lastHover) return
  264. const {
  265. before
  266. } = this.multipleStatus
  267. if (!before) {
  268. this.multipleStatus.before = fullDate
  269. } else {
  270. this.multipleStatus.after = fullDate
  271. if (dateCompare(this.multipleStatus.before, this.multipleStatus.after)) {
  272. this.multipleStatus.data = this.geDateAll(this.multipleStatus.before, this.multipleStatus.after);
  273. } else {
  274. this.multipleStatus.data = this.geDateAll(this.multipleStatus.after, this.multipleStatus.before);
  275. }
  276. }
  277. this.getWeeks(fullDate)
  278. // #endif
  279. }
  280. /**
  281. * 更新默认值多选状态
  282. */
  283. setDefaultMultiple(before, after) {
  284. this.multipleStatus.before = before
  285. this.multipleStatus.after = after
  286. if (before && after) {
  287. if (dateCompare(before, after)) {
  288. this.multipleStatus.data = this.geDateAll(before, after);
  289. this.getWeeks(after)
  290. } else {
  291. this.multipleStatus.data = this.geDateAll(after, before);
  292. this.getWeeks(before)
  293. }
  294. }
  295. }
  296. /**
  297. * 获取每周数据
  298. * @param {Object} dateData
  299. */
  300. getWeeks(dateData) {
  301. const {
  302. year,
  303. month,
  304. } = this.getDateObj(dateData)
  305. const preMonthDayAmount = new Date(year, month - 1, 1).getDay()
  306. const preMonthDays = this.getPreMonthDays(preMonthDayAmount, this.getDateObj(dateData))
  307. const currentMonthDayAmount = new Date(year, month, 0).getDate()
  308. const currentMonthDays = this.getCurrentMonthDays(currentMonthDayAmount, this.getDateObj(dateData))
  309. const nextMonthDayAmount = 42 - preMonthDayAmount - currentMonthDayAmount
  310. const nextMonthDays = this._getNextMonthDays(nextMonthDayAmount, this.getDateObj(dateData))
  311. const calendarDays = [...preMonthDays, ...currentMonthDays, ...nextMonthDays]
  312. const weeks = new Array(6)
  313. for (let i = 0; i < calendarDays.length; i++) {
  314. const index = Math.floor(i / 7)
  315. if (!weeks[index]) {
  316. weeks[index] = new Array(7)
  317. }
  318. weeks[index][i % 7] = calendarDays[i]
  319. }
  320. this.calendar = calendarDays
  321. this.weeks = weeks
  322. }
  323. }
  324. function getDateTime(date, hideSecond) {
  325. return `${getDate(date)} ${getTime(date, hideSecond)}`
  326. }
  327. function getDate(date) {
  328. date = fixIosDateFormat(date)
  329. date = new Date(date)
  330. const year = date.getFullYear()
  331. const month = date.getMonth() + 1
  332. const day = date.getDate()
  333. return `${year}-${addZero(month)}-${addZero(day)}`
  334. }
  335. function getTime(date, hideSecond) {
  336. date = fixIosDateFormat(date)
  337. date = new Date(date)
  338. const hour = date.getHours()
  339. const minute = date.getMinutes()
  340. const second = date.getSeconds()
  341. return hideSecond ? `${addZero(hour)}:${addZero(minute)}` : `${addZero(hour)}:${addZero(minute)}:${addZero(second)}`
  342. }
  343. function addZero(num) {
  344. if (num < 10) {
  345. num = `0${num}`
  346. }
  347. return num
  348. }
  349. function getDefaultSecond(hideSecond) {
  350. return hideSecond ? '00:00' : '00:00:00'
  351. }
  352. function dateCompare(startDate, endDate) {
  353. startDate = new Date(fixIosDateFormat(startDate))
  354. endDate = new Date(fixIosDateFormat(endDate))
  355. return startDate <= endDate
  356. }
  357. function checkDate(date) {
  358. const dateReg = /((19|20)\d{2})(-|\/)\d{1,2}(-|\/)\d{1,2}/g
  359. return date.match(dateReg)
  360. }
  361. //ios低版本15及以下,无法匹配 没有 ’秒‘ 时的情况,所以需要在末尾 秒 加上 问号
  362. const dateTimeReg = /^\d{4}-(0?[1-9]|1[012])-(0?[1-9]|[12][0-9]|3[01])( [0-5]?[0-9]:[0-5]?[0-9](:[0-5]?[0-9])?)?$/;
  363. function fixIosDateFormat(value) {
  364. if (typeof value === 'string' && dateTimeReg.test(value)) {
  365. value = value.replace(/-/g, '/')
  366. }
  367. return value
  368. }
  369. export {
  370. Calendar,
  371. getDateTime,
  372. getDate,
  373. getTime,
  374. addZero,
  375. getDefaultSecond,
  376. dateCompare,
  377. checkDate,
  378. fixIosDateFormat
  379. }