main.js 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877
  1. import Day from './func/day'
  2. import Week from './func/week'
  3. import Todo from './func/todo'
  4. import WxData from './func/wxData'
  5. import Calendar from './func/render'
  6. import CalendarConfig from './func/config'
  7. import convertSolarLunar from './func/convertSolarLunar'
  8. import {
  9. Logger,
  10. GetDate,
  11. isComponent,
  12. initialTasks,
  13. getCurrentPage,
  14. getComponent,
  15. getDateTimeStamp
  16. } from './func/utils'
  17. let Component = {}
  18. let logger = new Logger()
  19. let getDate = new GetDate()
  20. let dataInstance = null
  21. /**
  22. * 全局赋值正在操作的组件实例,方便读/写各自的 data
  23. * @param {string} componentId 要操作的日历组件ID
  24. */
  25. function bindCurrentComponent(componentId) {
  26. if (componentId) {
  27. Component = getComponent(componentId)
  28. }
  29. return Component
  30. }
  31. /**
  32. * 获取日历内部数据
  33. * @param {string} key 获取值的键名
  34. * @param {string} componentId 要操作的日历组件ID
  35. */
  36. function getData(key, componentId) {
  37. bindCurrentComponent(componentId)
  38. dataInstance = new WxData(Component)
  39. return dataInstance.getData(key)
  40. }
  41. /**
  42. * 设置日历内部数据
  43. * @param {object}} data 待设置的数据
  44. * @param {function} callback 设置成功回调函数
  45. */
  46. function setData(data, callback = () => {}) {
  47. const dataInstance = new WxData(Component)
  48. return dataInstance.setData(data, callback)
  49. }
  50. const conf = {
  51. /**
  52. * 渲染日历
  53. * @param {number} curYear
  54. * @param {number} curMonth
  55. * @param {number} curDate
  56. */
  57. renderCalendar(curYear, curMonth, curDate) {
  58. if (isComponent(this)) Component = this
  59. return new Promise((resolve, reject) => {
  60. Calendar(Component)
  61. .renderCalendar(curYear, curMonth, curDate)
  62. .then((info = {}) => {
  63. if (!info.firstRender) {
  64. return resolve({
  65. year: curYear,
  66. month: curMonth,
  67. date: curDate
  68. })
  69. }
  70. mountEventsOnPage(getCurrentPage())
  71. Component.triggerEvent('afterCalendarRender', Component)
  72. Component.firstRender = true
  73. initialTasks.flag = 'finished'
  74. if (initialTasks.tasks.length) {
  75. initialTasks.tasks.shift()()
  76. }
  77. resolve({
  78. year: curYear,
  79. month: curMonth,
  80. date: curDate
  81. })
  82. })
  83. .catch(err => {
  84. reject(err)
  85. })
  86. })
  87. },
  88. /**
  89. * 当改变月份时触发
  90. * @param {object} param
  91. */
  92. whenChangeDate({ curYear, curMonth, newYear, newMonth }) {
  93. Component.triggerEvent('whenChangeMonth', {
  94. current: {
  95. year: curYear,
  96. month: curMonth
  97. },
  98. next: {
  99. year: newYear,
  100. month: newMonth
  101. }
  102. })
  103. },
  104. /**
  105. * 多选
  106. * @param {number} dateIdx 当前选中日期索引值
  107. */
  108. whenMulitSelect(dateIdx) {
  109. if (isComponent(this)) Component = this
  110. const { calendar = {} } = getData()
  111. const { days, todoLabels } = calendar
  112. const config = CalendarConfig(Component).getCalendarConfig()
  113. let { selectedDay: selectedDays = [] } = calendar
  114. const currentDay = days[dateIdx]
  115. if (!currentDay) return
  116. currentDay.choosed = !currentDay.choosed
  117. if (!currentDay.choosed) {
  118. currentDay.cancel = true // 该次点击是否为取消日期操作
  119. const currentDayStr = getDate.toTimeStr(currentDay)
  120. selectedDays = selectedDays.filter(
  121. item => currentDayStr !== getDate.toTimeStr(item)
  122. )
  123. if (todoLabels) {
  124. todoLabels.forEach(item => {
  125. if (currentDayStr === getDate.toTimeStr(item)) {
  126. currentDay.showTodoLabel = true
  127. }
  128. })
  129. }
  130. } else {
  131. currentDay.cancel = false
  132. const { showLabelAlways } = getData('calendar')
  133. if (showLabelAlways && currentDay.showTodoLabel) {
  134. currentDay.showTodoLabel = true
  135. } else {
  136. currentDay.showTodoLabel = false
  137. }
  138. if (!config.takeoverTap) {
  139. selectedDays.push(currentDay)
  140. }
  141. }
  142. if (config.takeoverTap) {
  143. return Component.triggerEvent('onTapDay', currentDay)
  144. }
  145. setData({
  146. 'calendar.days': days,
  147. 'calendar.selectedDay': selectedDays
  148. })
  149. conf.afterTapDay(currentDay, selectedDays)
  150. },
  151. /**
  152. * 单选
  153. * @param {number} dateIdx 当前选中日期索引值
  154. */
  155. whenSingleSelect(dateIdx) {
  156. if (isComponent(this)) Component = this
  157. const { calendar = {} } = getData()
  158. const { days, selectedDay: selectedDays = [], todoLabels } = calendar
  159. let shouldMarkerTodoDay = []
  160. const currentDay = days[dateIdx]
  161. if (!currentDay) return
  162. const preSelectedDate = [...selectedDays].pop() || {}
  163. const { month: dMonth, year: dYear } = days[0] || {}
  164. const config = CalendarConfig(Component).getCalendarConfig()
  165. if (config.takeoverTap) {
  166. return Component.triggerEvent('onTapDay', currentDay)
  167. }
  168. conf.afterTapDay(currentDay)
  169. if (!config.inverse && preSelectedDate.day === currentDay.day) return
  170. days.forEach((item, idx) => {
  171. if (+item.day === +preSelectedDate.day) days[idx].choosed = false
  172. })
  173. if (todoLabels) {
  174. // 筛选当月待办事项的日期
  175. shouldMarkerTodoDay = todoLabels.filter(
  176. item => +item.year === dYear && +item.month === dMonth
  177. )
  178. }
  179. Todo(Component).showTodoLabels(shouldMarkerTodoDay, days, selectedDays)
  180. const tmp = {
  181. 'calendar.days': days
  182. }
  183. if (preSelectedDate.day !== currentDay.day) {
  184. preSelectedDate.choosed = false
  185. currentDay.choosed = true
  186. if (!calendar.showLabelAlways || !currentDay.showTodoLabel) {
  187. currentDay.showTodoLabel = false
  188. }
  189. tmp['calendar.selectedDay'] = [currentDay]
  190. } else if (config.inverse) {
  191. if (currentDay.choosed) {
  192. if (currentDay.showTodoLabel && calendar.showLabelAlways) {
  193. currentDay.showTodoLabel = true
  194. } else {
  195. currentDay.showTodoLabel = false
  196. }
  197. }
  198. tmp['calendar.selectedDay'] = []
  199. }
  200. if (config.weekMode) {
  201. tmp['calendar.curYear'] = currentDay.year
  202. tmp['calendar.curMonth'] = currentDay.month
  203. }
  204. setData(tmp)
  205. },
  206. gotoSetContinuousDates(start, end) {
  207. return chooseDateArea([
  208. `${getDate.toTimeStr(start)}`,
  209. `${getDate.toTimeStr(end)}`
  210. ])
  211. },
  212. timeRangeHelper(currentDate, selectedDay) {
  213. const currentDateTimestamp = getDateTimeStamp(currentDate)
  214. const startDate = selectedDay[0]
  215. let endDate
  216. let endDateTimestamp
  217. let selectedLen = selectedDay.length
  218. if (selectedLen > 1) {
  219. endDate = selectedDay[selectedLen - 1]
  220. endDateTimestamp = getDateTimeStamp(endDate)
  221. }
  222. const startTimestamp = getDateTimeStamp(startDate)
  223. return {
  224. endDate,
  225. startDate,
  226. currentDateTimestamp,
  227. endDateTimestamp,
  228. startTimestamp
  229. }
  230. },
  231. /**
  232. * 计算连续日期选择的开始及结束日期
  233. * @param {object} currentDate 当前选择日期
  234. * @param {array} selectedDay 已选择的的日期
  235. */
  236. calculateDateRange(currentDate, selectedDay) {
  237. const {
  238. endDate,
  239. startDate,
  240. currentDateTimestamp,
  241. endDateTimestamp,
  242. startTimestamp
  243. } = this.timeRangeHelper(currentDate, selectedDay)
  244. let range = []
  245. let selectedLen = selectedDay.length
  246. const isWantToChooseOneDate = selectedDay.filter(
  247. item => getDate.toTimeStr(item) === getDate.toTimeStr(currentDate)
  248. )
  249. if (selectedLen === 2 && isWantToChooseOneDate.length) {
  250. range = [currentDate, currentDate]
  251. return range
  252. }
  253. if (
  254. currentDateTimestamp >= startTimestamp &&
  255. endDateTimestamp &&
  256. currentDateTimestamp <= endDateTimestamp
  257. ) {
  258. const currentDateIdxInChoosedDateArea = selectedDay.findIndex(
  259. item => getDate.toTimeStr(item) === getDate.toTimeStr(currentDate)
  260. )
  261. if (selectedLen / 2 > currentDateIdxInChoosedDateArea) {
  262. range = [currentDate, endDate]
  263. } else {
  264. range = [startDate, currentDate]
  265. }
  266. } else if (currentDateTimestamp < startTimestamp) {
  267. range = [currentDate, endDate]
  268. } else if (currentDateTimestamp > startTimestamp) {
  269. range = [startDate, currentDate]
  270. }
  271. return range
  272. },
  273. chooseAreaWhenExistArea(currentDate, selectedDay) {
  274. return new Promise((resolve, reject) => {
  275. const range = conf.calculateDateRange(
  276. currentDate,
  277. getDate.sortDates(selectedDay)
  278. )
  279. conf
  280. .gotoSetContinuousDates(...range)
  281. .then(data => {
  282. resolve(data)
  283. conf.afterTapDay(currentDate)
  284. })
  285. .catch(err => {
  286. reject(err)
  287. conf.afterTapDay(currentDate)
  288. })
  289. })
  290. },
  291. chooseAreaWhenHasOneDate(currentDate, selectedDay, lastChoosedDate) {
  292. return new Promise((resolve, reject) => {
  293. const startDate = lastChoosedDate || selectedDay[0]
  294. let range = [startDate, currentDate]
  295. const currentDateTimestamp = getDateTimeStamp(currentDate)
  296. const lastChoosedDateTimestamp = getDateTimeStamp(startDate)
  297. if (lastChoosedDateTimestamp > currentDateTimestamp) {
  298. range = [currentDate, startDate]
  299. }
  300. conf
  301. .gotoSetContinuousDates(...range)
  302. .then(data => {
  303. resolve(data)
  304. conf.afterTapDay(currentDate)
  305. })
  306. .catch(err => {
  307. reject(err)
  308. conf.afterTapDay(currentDate)
  309. })
  310. })
  311. },
  312. /**
  313. * 日期范围选择模式
  314. * @param {number} dateIdx 当前选中日期索引值
  315. */
  316. whenChooseArea(dateIdx) {
  317. return new Promise((resolve, reject) => {
  318. if (isComponent(this)) Component = this
  319. if (Component.weekMode) return
  320. const { days = [], selectedDay, lastChoosedDate } = getData('calendar')
  321. const currentDate = days[dateIdx]
  322. if (currentDate.disable) return
  323. const config = CalendarConfig(Component).getCalendarConfig()
  324. if (config.takeoverTap) {
  325. return Component.triggerEvent('onTapDay', currentDate)
  326. }
  327. if (selectedDay && selectedDay.length > 1) {
  328. conf
  329. .chooseAreaWhenExistArea(currentDate, selectedDay)
  330. .then(dates => {
  331. resolve(dates)
  332. })
  333. .catch(err => {
  334. reject(err)
  335. })
  336. } else if (lastChoosedDate || (selectedDay && selectedDay.length === 1)) {
  337. conf
  338. .chooseAreaWhenHasOneDate(currentDate, selectedDay, lastChoosedDate)
  339. .then(dates => {
  340. resolve(dates)
  341. })
  342. .catch(err => {
  343. reject(err)
  344. })
  345. } else {
  346. days.forEach(date => {
  347. if (+date.day === +currentDate.day) {
  348. date.choosed = true
  349. } else {
  350. date.choosed = false
  351. }
  352. })
  353. const dataInstance = new WxData(Component)
  354. dataInstance.setData({
  355. 'calendar.days': [...days],
  356. 'calendar.lastChoosedDate': currentDate
  357. })
  358. }
  359. })
  360. },
  361. /**
  362. * 点击日期后触发事件
  363. * @param {object} currentSelected 当前选择的日期
  364. * @param {array} selectedDates 多选状态下选中的日期
  365. */
  366. afterTapDay(currentSelected, selectedDates) {
  367. const config = CalendarConfig(Component).getCalendarConfig()
  368. const { multi } = config
  369. if (!multi) {
  370. Component.triggerEvent('afterTapDay', currentSelected)
  371. } else {
  372. Component.triggerEvent('afterTapDay', {
  373. currentSelected,
  374. selectedDates
  375. })
  376. }
  377. },
  378. /**
  379. * 跳转至今天
  380. */
  381. jumpToToday() {
  382. return new Promise((resolve, reject) => {
  383. const { year, month, date } = getDate.todayDate()
  384. const timestamp = getDate.todayTimestamp()
  385. const config = CalendarConfig(Component).getCalendarConfig()
  386. setData({
  387. 'calendar.curYear': year,
  388. 'calendar.curMonth': month,
  389. 'calendar.selectedDay': [
  390. {
  391. year: year,
  392. day: date,
  393. month: month,
  394. choosed: true,
  395. lunar: config.showLunar
  396. ? convertSolarLunar.solar2lunar(year, month, date)
  397. : null
  398. }
  399. ],
  400. 'calendar.todayTimestamp': timestamp
  401. })
  402. conf
  403. .renderCalendar(year, month, date)
  404. .then(() => {
  405. resolve({ year, month, date })
  406. })
  407. .catch(() => {
  408. reject('jump failed')
  409. })
  410. })
  411. }
  412. }
  413. export const whenChangeDate = conf.whenChangeDate
  414. export const renderCalendar = conf.renderCalendar
  415. export const whenSingleSelect = conf.whenSingleSelect
  416. export const whenChooseArea = conf.whenChooseArea
  417. export const whenMulitSelect = conf.whenMulitSelect
  418. export const calculatePrevWeekDays = conf.calculatePrevWeekDays
  419. export const calculateNextWeekDays = conf.calculateNextWeekDays
  420. /**
  421. * 获取当前年月
  422. * @param {string} componentId 要操作的日历组件ID
  423. */
  424. export function getCurrentYM(componentId) {
  425. bindCurrentComponent(componentId)
  426. return {
  427. year: getData('calendar.curYear'),
  428. month: getData('calendar.curMonth')
  429. }
  430. }
  431. /**
  432. * 获取已选择的日期
  433. * @param {object } options 日期配置选项 {lunar} 是否返回农历信息
  434. * @param {string} componentId 要操作的日历组件ID
  435. */
  436. export function getSelectedDay(options = {}, componentId) {
  437. bindCurrentComponent(componentId)
  438. const config = getCalendarConfig()
  439. const dates = getData('calendar.selectedDay') || []
  440. if (options.lunar && !config.showLunar) {
  441. const datesWithLunar = getDate.convertLunar(dates)
  442. return datesWithLunar
  443. } else {
  444. return dates
  445. }
  446. }
  447. /**
  448. * 取消选中日期
  449. * @param {array} dates 需要取消的日期,不传则取消所有已选择的日期
  450. * @param {string} componentId 要操作的日历组件ID
  451. */
  452. export function cancelSelectedDates(dates, componentId) {
  453. bindCurrentComponent(componentId)
  454. const { days = [], selectedDay = [] } = getData('calendar') || {}
  455. if (!dates || !dates.length) {
  456. days.forEach(item => {
  457. item.choosed = false
  458. })
  459. setData({
  460. 'calendar.days': days,
  461. 'calendar.selectedDay': []
  462. })
  463. } else {
  464. const cancelDatesStr = dates.map(
  465. date => `${+date.year}-${+date.month}-${+date.day}`
  466. )
  467. const filterSelectedDates = selectedDay.filter(
  468. date =>
  469. !cancelDatesStr.includes(`${+date.year}-${+date.month}-${+date.day}`)
  470. )
  471. days.forEach(date => {
  472. if (
  473. cancelDatesStr.includes(`${+date.year}-${+date.month}-${+date.day}`)
  474. ) {
  475. date.choosed = false
  476. }
  477. })
  478. setData({
  479. 'calendar.days': days,
  480. 'calendar.selectedDay': filterSelectedDates
  481. })
  482. }
  483. }
  484. /**
  485. * 周视图跳转
  486. * @param {object} date info
  487. * @param {boolean} disableSelected 跳转时是否需要选中,周视图切换调用该方法,如未选择日期时不选中日期
  488. */
  489. function jumpWhenWeekMode({ year, month, day }, disableSelected) {
  490. return new Promise((resolve, reject) => {
  491. Week(Component)
  492. .jump(
  493. {
  494. year: +year,
  495. month: +month,
  496. day: +day
  497. },
  498. disableSelected
  499. )
  500. .then(date => {
  501. resolve(date)
  502. Component.triggerEvent('afterCalendarRender', Component)
  503. })
  504. .catch(err => {
  505. reject(err)
  506. Component.triggerEvent('afterCalendarRender', Component)
  507. })
  508. })
  509. }
  510. /**
  511. * 月视图跳转
  512. * @param {object} date info
  513. */
  514. function jumpWhenNormalMode({ year, month, day }) {
  515. return new Promise((resolve, reject) => {
  516. if (typeof +year !== 'number' || typeof +month !== 'number') {
  517. return logger.warn('jump 函数年月日参数必须为数字')
  518. }
  519. const timestamp = getDate.todayTimestamp()
  520. let tmp = {
  521. 'calendar.curYear': +year,
  522. 'calendar.curMonth': +month,
  523. 'calendar.todayTimestamp': timestamp
  524. }
  525. setData(tmp, () => {
  526. conf
  527. .renderCalendar(+year, +month, +day)
  528. .then(date => {
  529. resolve(date)
  530. })
  531. .catch(err => {
  532. reject(err)
  533. })
  534. })
  535. })
  536. }
  537. /**
  538. * 跳转至指定日期
  539. * @param {number} year
  540. * @param {number} month
  541. * @param {number} day
  542. * @param {string} componentId 要操作的日历组件ID
  543. */
  544. export function jump(year, month, day, componentId) {
  545. return new Promise((resolve, reject) => {
  546. bindCurrentComponent(componentId)
  547. const { selectedDay = [] } = getData('calendar') || {}
  548. const { weekMode } = getData('calendarConfig') || {}
  549. const { year: y, month: m, day: d } = selectedDay[0] || {}
  550. if (+y === +year && +m === +month && +d === +day) {
  551. return
  552. }
  553. if (weekMode) {
  554. let disableSelected = false
  555. if (!year || !month || !day) {
  556. const today = getDate.todayDate()
  557. year = today.year
  558. month = today.month
  559. day = today.date
  560. disableSelected = true
  561. }
  562. jumpWhenWeekMode({ year, month, day }, disableSelected)
  563. .then(date => {
  564. resolve(date)
  565. })
  566. .catch(err => {
  567. reject(err)
  568. })
  569. mountEventsOnPage(getCurrentPage())
  570. return
  571. }
  572. if (year && month) {
  573. jumpWhenNormalMode({ year, month, day })
  574. .then(date => {
  575. resolve(date)
  576. })
  577. .catch(err => {
  578. reject(err)
  579. })
  580. } else {
  581. conf
  582. .jumpToToday()
  583. .then(date => {
  584. resolve(date)
  585. })
  586. .catch(err => {
  587. reject(err)
  588. })
  589. }
  590. })
  591. }
  592. /**
  593. * 设置待办事项日期标记
  594. * @param {object} todos 待办事项配置
  595. * @param {string} [todos.pos] 标记显示位置,默认值'bottom' ['bottom', 'top']
  596. * @param {string} [todos.dotColor] 标记点颜色,backgroundColor 支持的值都行
  597. * @param {object[]} [todos.days] 需要标记的所有日期,如:[{year: 2015, month: 5, day: 12}],其中年月日字段必填
  598. * @param {string} componentId 要操作的日历组件ID
  599. */
  600. export function setTodoLabels(todos, componentId) {
  601. bindCurrentComponent(componentId)
  602. Todo(Component).setTodoLabels(todos)
  603. }
  604. /**
  605. * 删除指定日期待办事项
  606. * @param {array} todos 需要删除的待办日期数组
  607. * @param {string} componentId 要操作的日历组件ID
  608. */
  609. export function deleteTodoLabels(todos, componentId) {
  610. bindCurrentComponent(componentId)
  611. Todo(Component).deleteTodoLabels(todos)
  612. }
  613. /**
  614. * 清空所有待办事项
  615. * @param {string} componentId 要操作的日历组件ID
  616. */
  617. export function clearTodoLabels(componentId) {
  618. bindCurrentComponent(componentId)
  619. Todo(Component).clearTodoLabels()
  620. }
  621. /**
  622. * 获取所有待办事项
  623. * @param {object } options 日期配置选项 {lunar} 是否返回农历信息
  624. * @param {string} componentId 要操作的日历组件ID
  625. */
  626. export function getTodoLabels(options = {}, componentId) {
  627. bindCurrentComponent(componentId)
  628. const config = getCalendarConfig()
  629. const todoDates = Todo(Component).getTodoLabels() || []
  630. if (options.lunar && !config.showLunar) {
  631. const todoDatesWithLunar = getDate.convertLunar(todoDates)
  632. return todoDatesWithLunar
  633. } else {
  634. return todoDates
  635. }
  636. }
  637. /**
  638. * 禁用指定日期
  639. * @param {array} days 日期
  640. * @param {number} [days.year]
  641. * @param {number} [days.month]
  642. * @param {number} [days.day]
  643. * @param {string} componentId 要操作的日历组件ID
  644. */
  645. export function disableDay(days = [], componentId) {
  646. bindCurrentComponent(componentId)
  647. Day(Component).disableDays(days)
  648. }
  649. /**
  650. * 指定可选日期范围
  651. * @param {array} area 日期访问数组
  652. * @param {string} componentId 要操作的日历组件ID
  653. */
  654. export function enableArea(area = [], componentId) {
  655. bindCurrentComponent(componentId)
  656. Day(Component).enableArea(area)
  657. }
  658. /**
  659. * 指定特定日期可选
  660. * @param {array} days 指定日期数组
  661. * @param {string} componentId 要操作的日历组件ID
  662. */
  663. export function enableDays(days = [], componentId) {
  664. bindCurrentComponent(componentId)
  665. Day(Component).enableDays(days)
  666. }
  667. /**
  668. * 设置选中日期(多选模式下)
  669. * @param {array} selected 需选中日期
  670. * @param {string} componentId 要操作的日历组件ID
  671. */
  672. export function setSelectedDays(selected, componentId) {
  673. bindCurrentComponent(componentId)
  674. Day(Component).setSelectedDays(selected)
  675. }
  676. /**
  677. * 获取当前日历配置
  678. * @param {string} componentId 要操作的日历组件ID
  679. */
  680. export function getCalendarConfig(componentId) {
  681. bindCurrentComponent(componentId)
  682. return CalendarConfig(Component).getCalendarConfig()
  683. }
  684. /**
  685. * 设置日历配置
  686. * @param {object} config
  687. * @param {string} componentId 要操作的日历组件ID
  688. */
  689. export function setCalendarConfig(config, componentId) {
  690. bindCurrentComponent(componentId)
  691. if (!config || Object.keys(config).length === 0) {
  692. return logger.warn('setCalendarConfig 参数必须为非空对象')
  693. }
  694. const existConfig = getCalendarConfig()
  695. return new Promise((resolve, reject) => {
  696. CalendarConfig(Component)
  697. .setCalendarConfig(config)
  698. .then(conf => {
  699. resolve(conf)
  700. const { date, type } = existConfig.disableMode || {}
  701. const { _date, _type } = config.disableMode || {}
  702. if (type !== _type || date !== _date) {
  703. const { year, month } = getCurrentYM()
  704. jump(year, month)
  705. }
  706. })
  707. .catch(err => {
  708. reject(err)
  709. })
  710. })
  711. }
  712. /**
  713. * 获取当前日历面板日期
  714. * @param {object } options 日期配置选项 {lunar} 是否返回农历信息
  715. * @param {string} componentId 要操作的日历组件ID
  716. */
  717. export function getCalendarDates(options = {}, componentId) {
  718. bindCurrentComponent(componentId)
  719. const config = getCalendarConfig()
  720. const dates = getData('calendar.days', componentId) || []
  721. if (options.lunar && !config.showLunar) {
  722. const datesWithLunar = getDate.convertLunar(dates)
  723. return datesWithLunar
  724. } else {
  725. return dates
  726. }
  727. }
  728. /**
  729. * 选择连续日期范围
  730. * @param {string} componentId 要操作的日历组件ID
  731. */
  732. export function chooseDateArea(dateArea, componentId) {
  733. bindCurrentComponent(componentId)
  734. return Day(Component).chooseArea(dateArea)
  735. }
  736. /**
  737. * 设置指定日期样式
  738. * @param {array} dates 待设置特殊样式的日期
  739. * @param {string} componentId 要操作的日历组件ID
  740. */
  741. export function setDateStyle(dates, componentId) {
  742. if (!dates) return
  743. bindCurrentComponent(componentId)
  744. Day(Component).setDateStyle(dates)
  745. }
  746. /**
  747. * 切换周月视图
  748. * 切换视图时可传入指定日期,如: {year: 2019, month: 1, day: 3}
  749. * args[0] view 视图模式[week, month]
  750. * args[1]|args[2]为day object或者 componentId
  751. */
  752. export function switchView(...args) {
  753. return new Promise((resolve, reject) => {
  754. const view = args[0]
  755. if (!args[1]) {
  756. return Week(Component)
  757. .switchWeek(view)
  758. .then(resolve)
  759. .catch(reject)
  760. }
  761. if (typeof args[1] === 'string') {
  762. bindCurrentComponent(args[1], this)
  763. Week(Component)
  764. .switchWeek(view, args[2])
  765. .then(resolve)
  766. .catch(reject)
  767. } else if (typeof args[1] === 'object') {
  768. if (typeof args[2] === 'string') {
  769. bindCurrentComponent(args[1], this)
  770. }
  771. Week(Component)
  772. .switchWeek(view, args[1])
  773. .then(resolve)
  774. .catch(reject)
  775. }
  776. })
  777. }
  778. /**
  779. * 绑定日历事件至当前页面实例
  780. * @param {object} page 当前页面实例
  781. */
  782. function mountEventsOnPage(page) {
  783. page.calendar = {
  784. jump,
  785. switchView,
  786. disableDay,
  787. enableArea,
  788. enableDays,
  789. chooseDateArea,
  790. getCurrentYM,
  791. getSelectedDay,
  792. cancelSelectedDates,
  793. setDateStyle,
  794. setTodoLabels,
  795. getTodoLabels,
  796. deleteTodoLabels,
  797. clearTodoLabels,
  798. setSelectedDays,
  799. getCalendarConfig,
  800. setCalendarConfig,
  801. getCalendarDates
  802. }
  803. }
  804. function setWeekHeader(firstDayOfWeek) {
  805. let weeksCh = ['日', '一', '二', '三', '四', '五', '六']
  806. if (firstDayOfWeek === 'Mon') {
  807. weeksCh = ['一', '二', '三', '四', '五', '六', '日']
  808. }
  809. setData({
  810. 'calendar.weeksCh': weeksCh
  811. })
  812. }
  813. function autoSelectDay(defaultDay) {
  814. Component.firstRenderWeekMode = true
  815. if (defaultDay && typeof defaultDay === 'string') {
  816. const day = defaultDay.split('-')
  817. if (day.length < 3) {
  818. return logger.warn('配置 jumpTo 格式应为: 2018-4-2 或 2018-04-02')
  819. }
  820. jump(+day[0], +day[1], +day[2])
  821. } else {
  822. if (!defaultDay) {
  823. Component.config.noDefault = true
  824. setData({
  825. 'config.noDefault': true
  826. })
  827. }
  828. jump()
  829. }
  830. }
  831. function init(component, config) {
  832. initialTasks.flag = 'process'
  833. Component = component
  834. Component.config = config
  835. setWeekHeader(config.firstDayOfWeek)
  836. autoSelectDay(config.defaultDay)
  837. logger.tips(
  838. '使用中若遇问题请反馈至 https://github.com/treadpit/wx_calendar/issues ✍️'
  839. )
  840. }
  841. export default (component, config = {}) => {
  842. if (initialTasks.flag === 'process') {
  843. return initialTasks.tasks.push(function() {
  844. init(component, config)
  845. })
  846. }
  847. init(component, config)
  848. }