util.js 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453
  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 ? dateObj.month -1 : 12
  91. const year = month === 12 ? dateObj.year - 1 : dateObj.year
  92. const date = new Date(year,month,-i).getDate()
  93. const fullDate = `${year}-${addZero(month)}-${addZero(date)}`
  94. let multiples = this.multipleStatus.data
  95. let multiplesStatus = -1
  96. if (this.range && multiples) {
  97. multiplesStatus = multiples.findIndex((item) => {
  98. return this.dateEqual(item, fullDate)
  99. })
  100. }
  101. const checked = multiplesStatus !== -1
  102. // 获取打点信息
  103. const extraInfo = this.selected && this.selected.find((item) => {
  104. if (this.dateEqual(fullDate, item.date)) {
  105. return item
  106. }
  107. })
  108. result.push({
  109. fullDate,
  110. year,
  111. month,
  112. date,
  113. multiple: this.range ? checked : false,
  114. beforeMultiple: this.isLogicBefore(fullDate, this.multipleStatus.before, this.multipleStatus.after),
  115. afterMultiple: this.isLogicAfter(fullDate, this.multipleStatus.before, this.multipleStatus.after),
  116. disable: (this.startDate && !dateCompare(this.startDate, fullDate)) || (this.endDate && !dateCompare(fullDate,this.endDate)),
  117. isToday: fullDate === this.date.fullDate,
  118. userChecked: false,
  119. extraInfo
  120. })
  121. }
  122. return result
  123. }
  124. /**
  125. * 获取本月日期集合
  126. */
  127. getCurrentMonthDays(amount, dateObj) {
  128. const result = []
  129. const fullDate = this.date.fullDate
  130. for (let i = 1; i <= amount; i++) {
  131. const currentDate = `${dateObj.year}-${dateObj.month}-${addZero(i)}`
  132. const isToday = fullDate === currentDate
  133. // 获取打点信息
  134. const extraInfo = this.selected && this.selected.find((item) => {
  135. if (this.dateEqual(currentDate, item.date)) {
  136. return item
  137. }
  138. })
  139. // 日期禁用
  140. let disableBefore = true
  141. let disableAfter = true
  142. if (this.startDate) {
  143. disableBefore = dateCompare(this.startDate, currentDate)
  144. }
  145. if (this.endDate) {
  146. disableAfter = dateCompare(currentDate, this.endDate)
  147. }
  148. let multiples = this.multipleStatus.data
  149. let multiplesStatus = -1
  150. if (this.range && multiples) {
  151. multiplesStatus = multiples.findIndex((item) => {
  152. return this.dateEqual(item, currentDate)
  153. })
  154. }
  155. const checked = multiplesStatus !== -1
  156. result.push({
  157. fullDate: currentDate,
  158. year: dateObj.year,
  159. month: dateObj.month,
  160. date: i,
  161. multiple: this.range ? checked : false,
  162. beforeMultiple: this.isLogicBefore(currentDate, this.multipleStatus.before, this.multipleStatus.after),
  163. afterMultiple: this.isLogicAfter(currentDate, this.multipleStatus.before, this.multipleStatus.after),
  164. disable: (this.startDate && !dateCompare(this.startDate, currentDate)) || (this.endDate && !dateCompare(currentDate,this.endDate)),
  165. isToday,
  166. userChecked: false,
  167. extraInfo
  168. })
  169. }
  170. return result
  171. }
  172. /**
  173. * 获取下一个月日期集合
  174. */
  175. _getNextMonthDays(amount, dateObj) {
  176. const result = []
  177. const month = dateObj.month + 1
  178. for (let i = 1; i <= amount; i++) {
  179. const month = dateObj.month === 12 ? 1 : dateObj.month*1 + 1
  180. const year = month === 1 ? dateObj.year + 1 : dateObj.year
  181. const fullDate = `${year}-${addZero(month)}-${addZero(i)}`
  182. let multiples = this.multipleStatus.data
  183. let multiplesStatus = -1
  184. if (this.range && multiples) {
  185. multiplesStatus = multiples.findIndex((item) => {
  186. return this.dateEqual(item, fullDate)
  187. })
  188. }
  189. const checked = multiplesStatus !== -1
  190. // 获取打点信息
  191. const extraInfo = this.selected && this.selected.find((item) => {
  192. if (this.dateEqual(fullDate, item.date)) {
  193. return item
  194. }
  195. })
  196. result.push({
  197. fullDate,
  198. year,
  199. date: i,
  200. month,
  201. multiple: this.range ? checked : false,
  202. beforeMultiple: this.isLogicBefore(fullDate, this.multipleStatus.before, this.multipleStatus.after),
  203. afterMultiple: this.isLogicAfter(fullDate, this.multipleStatus.before, this.multipleStatus.after),
  204. disable: (this.startDate && !dateCompare(this.startDate, fullDate)) || (this.endDate && !dateCompare(fullDate,this.endDate)),
  205. isToday: fullDate === this.date.fullDate,
  206. userChecked: false,
  207. extraInfo
  208. })
  209. }
  210. return result
  211. }
  212. /**
  213. * 获取当前日期详情
  214. * @param {Object} date
  215. */
  216. getInfo(date) {
  217. if (!date) {
  218. date = new Date()
  219. }
  220. return this.calendar.find(item => item.fullDate === this.getDateObj(date).fullDate)
  221. }
  222. /**
  223. * 比较时间是否相等
  224. */
  225. dateEqual(before, after) {
  226. before = new Date(fixIosDateFormat(before))
  227. after = new Date(fixIosDateFormat(after))
  228. return before.valueOf() === after.valueOf()
  229. }
  230. /**
  231. * 比较真实起始日期
  232. */
  233. isLogicBefore(currentDate, before, after) {
  234. let logicBefore = before
  235. if (before && after) {
  236. logicBefore = dateCompare(before, after) ? before : after
  237. }
  238. return this.dateEqual(logicBefore, currentDate)
  239. }
  240. isLogicAfter(currentDate, before, after) {
  241. let logicAfter = after
  242. if (before && after) {
  243. logicAfter = dateCompare(before, after) ? after : before
  244. }
  245. return this.dateEqual(logicAfter, currentDate)
  246. }
  247. /**
  248. * 获取日期范围内所有日期
  249. * @param {Object} begin
  250. * @param {Object} end
  251. */
  252. geDateAll(begin, end) {
  253. var arr = []
  254. var ab = begin.split('-')
  255. var ae = end.split('-')
  256. var db = new Date()
  257. db.setFullYear(ab[0], ab[1] - 1, ab[2])
  258. var de = new Date()
  259. de.setFullYear(ae[0], ae[1] - 1, ae[2])
  260. var unixDb = db.getTime() - 24 * 60 * 60 * 1000
  261. var unixDe = de.getTime() - 24 * 60 * 60 * 1000
  262. for (var k = unixDb; k <= unixDe;) {
  263. k = k + 24 * 60 * 60 * 1000
  264. arr.push(this.getDateObj(new Date(parseInt(k))).fullDate)
  265. }
  266. return arr
  267. }
  268. /**
  269. * 获取多选状态
  270. */
  271. setMultiple(fullDate) {
  272. if (!this.range) return
  273. let {
  274. before,
  275. after
  276. } = this.multipleStatus
  277. if (before && after) {
  278. if (!this.lastHover) {
  279. this.lastHover = true
  280. return
  281. }
  282. this.multipleStatus.before = fullDate
  283. this.multipleStatus.after = ''
  284. this.multipleStatus.data = []
  285. this.multipleStatus.fulldate = ''
  286. this.lastHover = false
  287. } else {
  288. if (!before) {
  289. this.multipleStatus.before = fullDate
  290. this.lastHover = false
  291. } else {
  292. this.multipleStatus.after = fullDate
  293. if (dateCompare(this.multipleStatus.before, this.multipleStatus.after)) {
  294. this.multipleStatus.data = this.geDateAll(this.multipleStatus.before, this.multipleStatus
  295. .after);
  296. } else {
  297. this.multipleStatus.data = this.geDateAll(this.multipleStatus.after, this.multipleStatus
  298. .before);
  299. }
  300. this.lastHover = true
  301. }
  302. }
  303. this.getWeeks(fullDate)
  304. }
  305. /**
  306. * 鼠标 hover 更新多选状态
  307. */
  308. setHoverMultiple(fullDate) {
  309. if (!this.range || this.lastHover) return
  310. const { before } = this.multipleStatus
  311. if (!before) {
  312. this.multipleStatus.before = fullDate
  313. } else {
  314. this.multipleStatus.after = fullDate
  315. if (dateCompare(this.multipleStatus.before, this.multipleStatus.after)) {
  316. this.multipleStatus.data = this.geDateAll(this.multipleStatus.before, this.multipleStatus.after);
  317. } else {
  318. this.multipleStatus.data = this.geDateAll(this.multipleStatus.after, this.multipleStatus.before);
  319. }
  320. }
  321. this.getWeeks(fullDate)
  322. }
  323. /**
  324. * 更新默认值多选状态
  325. */
  326. setDefaultMultiple(before, after) {
  327. this.multipleStatus.before = before
  328. this.multipleStatus.after = after
  329. if (before && after) {
  330. if (dateCompare(before, after)) {
  331. this.multipleStatus.data = this.geDateAll(before, after);
  332. this.getWeeks(after)
  333. } else {
  334. this.multipleStatus.data = this.geDateAll(after, before);
  335. this.getWeeks(before)
  336. }
  337. }
  338. }
  339. /**
  340. * 获取每周数据
  341. * @param {Object} dateData
  342. */
  343. getWeeks(dateData) {
  344. const {
  345. year,
  346. month,
  347. } = this.getDateObj(dateData)
  348. const preMonthDayAmount = new Date(year, month - 1, 1).getDay()
  349. const preMonthDays = this.getPreMonthDays(preMonthDayAmount, this.getDateObj(dateData))
  350. const currentMonthDayAmount = new Date(year, month, 0).getDate()
  351. const currentMonthDays = this.getCurrentMonthDays(currentMonthDayAmount, this.getDateObj(dateData))
  352. const nextMonthDayAmount = 42 - preMonthDayAmount - currentMonthDayAmount
  353. const nextMonthDays = this._getNextMonthDays(nextMonthDayAmount, this.getDateObj(dateData))
  354. const calendarDays = [...preMonthDays, ...currentMonthDays, ...nextMonthDays]
  355. const weeks = new Array(6)
  356. for (let i = 0; i < calendarDays.length; i++) {
  357. const index = Math.floor(i / 7)
  358. if(!weeks[index]){
  359. weeks[index] = new Array(7)
  360. }
  361. weeks[index][i % 7] = calendarDays[i]
  362. }
  363. this.calendar = calendarDays
  364. this.weeks = weeks
  365. }
  366. }
  367. function getDateTime(date, hideSecond){
  368. return `${getDate(date)} ${getTime(date, hideSecond)}`
  369. }
  370. function getDate(date) {
  371. date = fixIosDateFormat(date)
  372. date = new Date(date)
  373. const year = date.getFullYear()
  374. const month = date.getMonth()+1
  375. const day = date.getDate()
  376. return `${year}-${addZero(month)}-${addZero(day)}`
  377. }
  378. function getTime(date, hideSecond){
  379. date = fixIosDateFormat(date)
  380. date = new Date(date)
  381. const hour = date.getHours()
  382. const minute = date.getMinutes()
  383. const second = date.getSeconds()
  384. return hideSecond ? `${addZero(hour)}:${addZero(minute)}` : `${addZero(hour)}:${addZero(minute)}:${addZero(second)}`
  385. }
  386. function addZero(num) {
  387. if(num < 10){
  388. num = `0${num}`
  389. }
  390. return num
  391. }
  392. function getDefaultSecond(hideSecond) {
  393. return hideSecond ? '00:00' : '00:00:00'
  394. }
  395. function dateCompare(startDate, endDate) {
  396. startDate = new Date(fixIosDateFormat(startDate))
  397. endDate = new Date(fixIosDateFormat(endDate))
  398. return startDate <= endDate
  399. }
  400. function checkDate(date){
  401. const dateReg = /((19|20)\d{2})(-|\/)\d{1,2}(-|\/)\d{1,2}/g
  402. return date.match(dateReg)
  403. }
  404. 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])?$/
  405. function fixIosDateFormat(value) {
  406. if (typeof value === 'string' && dateTimeReg.test(value)) {
  407. value = value.replace(/-/g, '/')
  408. }
  409. return value
  410. }
  411. export {Calendar, getDateTime, getDate, getTime, addZero, getDefaultSecond, dateCompare, checkDate, fixIosDateFormat}