util.js 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422
  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. const res = this.calendar.find(item => item.fullDate === this.getDateObj(date).fullDate)
  172. return res ? res : this.getDateObj(date)
  173. }
  174. /**
  175. * 比较时间是否相等
  176. */
  177. dateEqual(before, after) {
  178. before = new Date(fixIosDateFormat(before))
  179. after = new Date(fixIosDateFormat(after))
  180. return before.valueOf() === after.valueOf()
  181. }
  182. /**
  183. * 比较真实起始日期
  184. */
  185. isLogicBefore(currentDate, before, after) {
  186. let logicBefore = before
  187. if (before && after) {
  188. logicBefore = dateCompare(before, after) ? before : after
  189. }
  190. return this.dateEqual(logicBefore, currentDate)
  191. }
  192. isLogicAfter(currentDate, before, after) {
  193. let logicAfter = after
  194. if (before && after) {
  195. logicAfter = dateCompare(before, after) ? after : before
  196. }
  197. return this.dateEqual(logicAfter, currentDate)
  198. }
  199. /**
  200. * 获取日期范围内所有日期
  201. * @param {Object} begin
  202. * @param {Object} end
  203. */
  204. geDateAll(begin, end) {
  205. var arr = []
  206. var ab = begin.split('-')
  207. var ae = end.split('-')
  208. var db = new Date()
  209. db.setFullYear(ab[0], ab[1] - 1, ab[2])
  210. var de = new Date()
  211. de.setFullYear(ae[0], ae[1] - 1, ae[2])
  212. var unixDb = db.getTime() - 24 * 60 * 60 * 1000
  213. var unixDe = de.getTime() - 24 * 60 * 60 * 1000
  214. for (var k = unixDb; k <= unixDe;) {
  215. k = k + 24 * 60 * 60 * 1000
  216. arr.push(this.getDateObj(new Date(parseInt(k))).fullDate)
  217. }
  218. return arr
  219. }
  220. /**
  221. * 获取多选状态
  222. */
  223. setMultiple(fullDate) {
  224. if (!this.range) return
  225. let {
  226. before,
  227. after
  228. } = this.multipleStatus
  229. if (before && after) {
  230. if (!this.lastHover) {
  231. this.lastHover = true
  232. return
  233. }
  234. this.multipleStatus.before = fullDate
  235. this.multipleStatus.after = ''
  236. this.multipleStatus.data = []
  237. this.multipleStatus.fulldate = ''
  238. this.lastHover = false
  239. } else {
  240. if (!before) {
  241. this.multipleStatus.before = fullDate
  242. this.multipleStatus.after = undefined;
  243. this.lastHover = false
  244. } else {
  245. this.multipleStatus.after = fullDate
  246. if (dateCompare(this.multipleStatus.before, this.multipleStatus.after)) {
  247. this.multipleStatus.data = this.geDateAll(this.multipleStatus.before, this.multipleStatus
  248. .after);
  249. } else {
  250. this.multipleStatus.data = this.geDateAll(this.multipleStatus.after, this.multipleStatus
  251. .before);
  252. }
  253. this.lastHover = true
  254. }
  255. }
  256. this.getWeeks(fullDate)
  257. }
  258. /**
  259. * 鼠标 hover 更新多选状态
  260. */
  261. setHoverMultiple(fullDate) {
  262. //抖音小程序点击会触发hover事件,需要避免一下
  263. // #ifndef MP-TOUTIAO
  264. if (!this.range || this.lastHover) return
  265. const {
  266. before
  267. } = this.multipleStatus
  268. if (!before) {
  269. this.multipleStatus.before = fullDate
  270. } else {
  271. this.multipleStatus.after = fullDate
  272. if (dateCompare(this.multipleStatus.before, this.multipleStatus.after)) {
  273. this.multipleStatus.data = this.geDateAll(this.multipleStatus.before, this.multipleStatus.after);
  274. } else {
  275. this.multipleStatus.data = this.geDateAll(this.multipleStatus.after, this.multipleStatus.before);
  276. }
  277. }
  278. this.getWeeks(fullDate)
  279. // #endif
  280. }
  281. /**
  282. * 更新默认值多选状态
  283. */
  284. setDefaultMultiple(before, after) {
  285. this.multipleStatus.before = before
  286. this.multipleStatus.after = after
  287. if (before && after) {
  288. if (dateCompare(before, after)) {
  289. this.multipleStatus.data = this.geDateAll(before, after);
  290. this.getWeeks(after)
  291. } else {
  292. this.multipleStatus.data = this.geDateAll(after, before);
  293. this.getWeeks(before)
  294. }
  295. }
  296. }
  297. /**
  298. * 获取每周数据
  299. * @param {Object} dateData
  300. */
  301. getWeeks(dateData) {
  302. const {
  303. year,
  304. month,
  305. } = this.getDateObj(dateData)
  306. const preMonthDayAmount = new Date(year, month - 1, 1).getDay()
  307. const preMonthDays = this.getPreMonthDays(preMonthDayAmount, this.getDateObj(dateData))
  308. const currentMonthDayAmount = new Date(year, month, 0).getDate()
  309. const currentMonthDays = this.getCurrentMonthDays(currentMonthDayAmount, this.getDateObj(dateData))
  310. const nextMonthDayAmount = 42 - preMonthDayAmount - currentMonthDayAmount
  311. const nextMonthDays = this._getNextMonthDays(nextMonthDayAmount, this.getDateObj(dateData))
  312. const calendarDays = [...preMonthDays, ...currentMonthDays, ...nextMonthDays]
  313. const weeks = new Array(6)
  314. for (let i = 0; i < calendarDays.length; i++) {
  315. const index = Math.floor(i / 7)
  316. if (!weeks[index]) {
  317. weeks[index] = new Array(7)
  318. }
  319. weeks[index][i % 7] = calendarDays[i]
  320. }
  321. this.calendar = calendarDays
  322. this.weeks = weeks
  323. }
  324. }
  325. function getDateTime(date, hideSecond) {
  326. return `${getDate(date)} ${getTime(date, hideSecond)}`
  327. }
  328. function getDate(date) {
  329. date = fixIosDateFormat(date)
  330. date = new Date(date)
  331. const year = date.getFullYear()
  332. const month = date.getMonth() + 1
  333. const day = date.getDate()
  334. return `${year}-${addZero(month)}-${addZero(day)}`
  335. }
  336. function getTime(date, hideSecond) {
  337. date = fixIosDateFormat(date)
  338. date = new Date(date)
  339. const hour = date.getHours()
  340. const minute = date.getMinutes()
  341. const second = date.getSeconds()
  342. return hideSecond ? `${addZero(hour)}:${addZero(minute)}` : `${addZero(hour)}:${addZero(minute)}:${addZero(second)}`
  343. }
  344. function addZero(num) {
  345. if (num < 10) {
  346. num = `0${num}`
  347. }
  348. return num
  349. }
  350. function getDefaultSecond(hideSecond) {
  351. return hideSecond ? '00:00' : '00:00:00'
  352. }
  353. function dateCompare(startDate, endDate) {
  354. startDate = new Date(fixIosDateFormat(startDate))
  355. endDate = new Date(fixIosDateFormat(endDate))
  356. return startDate <= endDate
  357. }
  358. function checkDate(date) {
  359. const dateReg = /((19|20)\d{2})(-|\/)\d{1,2}(-|\/)\d{1,2}/g
  360. return date.match(dateReg)
  361. }
  362. //ios低版本15及以下,无法匹配 没有 ’秒‘ 时的情况,所以需要在末尾 秒 加上 问号
  363. 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])?)?$/;
  364. function fixIosDateFormat(value) {
  365. if (typeof value === 'string' && dateTimeReg.test(value)) {
  366. value = value.replace(/-/g, '/')
  367. }
  368. return value
  369. }
  370. export {
  371. Calendar,
  372. getDateTime,
  373. getDate,
  374. getTime,
  375. addZero,
  376. getDefaultSecond,
  377. dateCompare,
  378. checkDate,
  379. fixIosDateFormat
  380. }