zxz-calendar.vue 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059
  1. <template>
  2. <view class="uni-calendar" @mouseleave="leaveCale">
  3. <view v-if="!insert && show" class="uni-calendar__mask" :class="{ 'uni-calendar--mask-show': aniMaskShow }" @click="maskClick"></view>
  4. <view
  5. v-if="insert || show"
  6. class="uni-calendar__content"
  7. :class="{ 'uni-calendar--fixed': !insert, 'uni-calendar--ani-show': aniMaskShow, 'uni-calendar__content-mobile': aniMaskShow }"
  8. >
  9. <view class="uni-calendar__header" :class="{ 'uni-calendar__header-mobile': !insert }">
  10. <view class="uni-calendar__header-btn-box" @click.stop="changeMonth('pre')">
  11. <view class="uni-calendar__header-btn uni-calendar--left"></view>
  12. </view>
  13. <picker mode="date" :value="date" fields="month" @change="bindDateChange">
  14. <text class="uni-calendar__header-text">{{ (nowDate.year || '') + yearText + (nowDate.month || '') + monthText }}</text>
  15. </picker>
  16. <view class="uni-calendar__header-btn-box" @click.stop="changeMonth('next')">
  17. <view class="uni-calendar__header-btn uni-calendar--right"></view>
  18. </view>
  19. <view v-if="!insert" class="dialog-close" @click="close">
  20. <view class="dialog-close-plus" data-id="close"></view>
  21. <view class="dialog-close-plus dialog-close-rotate" data-id="close"></view>
  22. </view>
  23. </view>
  24. <view class="uni-calendar__box">
  25. <view v-if="showMonth" class="uni-calendar__box-bg">
  26. <text class="uni-calendar__box-bg-text">{{ nowDate.month }}</text>
  27. </view>
  28. <view class="uni-calendar__weeks" style="padding-bottom: 7px">
  29. <view class="uni-calendar__weeks-day" v-if="!isMonday">
  30. <text class="uni-calendar__weeks-day-text">{{ SUNText }}</text>
  31. </view>
  32. <view class="uni-calendar__weeks-day">
  33. <text class="uni-calendar__weeks-day-text">{{ MONText }}</text>
  34. </view>
  35. <view class="uni-calendar__weeks-day">
  36. <text class="uni-calendar__weeks-day-text">{{ TUEText }}</text>
  37. </view>
  38. <view class="uni-calendar__weeks-day">
  39. <text class="uni-calendar__weeks-day-text">{{ WEDText }}</text>
  40. </view>
  41. <view class="uni-calendar__weeks-day">
  42. <text class="uni-calendar__weeks-day-text">{{ THUText }}</text>
  43. </view>
  44. <view class="uni-calendar__weeks-day">
  45. <text class="uni-calendar__weeks-day-text">{{ FRIText }}</text>
  46. </view>
  47. <view class="uni-calendar__weeks-day">
  48. <text class="uni-calendar__weeks-day-text">{{ SATText }}</text>
  49. </view>
  50. <view class="uni-calendar__weeks-day" v-if="isMonday">
  51. <text class="uni-calendar__weeks-day-text">{{ SUNText }}</text>
  52. </view>
  53. </view>
  54. <view class="uni-calendar__weeks" v-for="(item, weekIndex) in weeks" :key="weekIndex">
  55. <view class="uni-calendar__weeks-item" v-for="(weeks, weeksIndex) in item" :key="weeksIndex">
  56. <calendar-item
  57. class="uni-calendar-item--hook"
  58. :calendarList="calendarList"
  59. :weeks="weeks"
  60. :calendar="calendar"
  61. :selected="selected"
  62. :checkHover="range"
  63. @change="choiceDate"
  64. @handleMouse="handleMouse"
  65. ></calendar-item>
  66. </view>
  67. </view>
  68. </view>
  69. <view v-if="!insert && !range && hasTime" class="uni-date-changed uni-calendar--fixed-top" style="padding: 0 80px">
  70. <view class="uni-date-changed--time-date">{{ tempSingleDate ? tempSingleDate : selectDateText }}</view>
  71. <time-picker
  72. type="time"
  73. :start="timepickerStartTime"
  74. :end="timepickerEndTime"
  75. v-model="time"
  76. :disabled="!tempSingleDate"
  77. :border="false"
  78. :hide-second="hideSecond"
  79. class="time-picker-style"
  80. ></time-picker>
  81. </view>
  82. <view v-if="!insert && range && hasTime" class="uni-date-changed uni-calendar--fixed-top">
  83. <view class="uni-date-changed--time-start">
  84. <view class="uni-date-changed--time-date">{{ tempRange.before ? tempRange.before : startDateText }}</view>
  85. <time-picker
  86. type="time"
  87. :start="timepickerStartTime"
  88. v-model="timeRange.startTime"
  89. :border="false"
  90. :hide-second="hideSecond"
  91. :disabled="!tempRange.before"
  92. class="time-picker-style"
  93. ></time-picker>
  94. </view>
  95. <view style="line-height: 50px">
  96. <uni-icons type="arrowthinright" color="#999"></uni-icons>
  97. </view>
  98. <view class="uni-date-changed--time-end">
  99. <view class="uni-date-changed--time-date">{{ tempRange.after ? tempRange.after : endDateText }}</view>
  100. <time-picker
  101. type="time"
  102. :end="timepickerEndTime"
  103. v-model="timeRange.endTime"
  104. :border="false"
  105. :hide-second="hideSecond"
  106. :disabled="!tempRange.after"
  107. class="time-picker-style"
  108. ></time-picker>
  109. </view>
  110. </view>
  111. <view v-if="!insert" class="uni-date-changed uni-date-btn--ok">
  112. <view class="uni-datetime-picker--btn" @click="confirm">{{ confirmText }}</view>
  113. </view>
  114. </view>
  115. </view>
  116. </template>
  117. <script>
  118. import { Calendar, getDate, getTime, getYearWeek, week_date } from './zxz-util.js';
  119. import calendarItem from './zxz-calendar-item.vue';
  120. import timePicker from './zxz-time-picker.vue';
  121. import { initVueI18n } from '@dcloudio/uni-i18n';
  122. import i18nMessages from './i18n/index.js';
  123. const { t } = initVueI18n(i18nMessages);
  124. /**
  125. * Calendar 日历
  126. * @description 日历组件可以查看日期,选择任意范围内的日期,打点操作。常用场景如:酒店日期预订、火车机票选择购买日期、上下班打卡等
  127. * @tutorial https://ext.dcloud.net.cn/plugin?id=56
  128. * @property {String} date 自定义当前时间,默认为今天
  129. * @property {String} startDate 日期选择范围-开始日期
  130. * @property {String} endDate 日期选择范围-结束日期
  131. * @property {Boolean} range 范围选择
  132. * @property {Boolean} insert = [true|false] 插入模式,默认为false
  133. * @value true 弹窗模式
  134. * @value false 插入模式
  135. * @property {Boolean} clearDate = [true|false] 弹窗模式是否清空上次选择内容
  136. * @property {Array} selected 打点,期待格式[{date: '2019-06-27', info: '签到', data: { custom: '自定义信息', name: '自定义消息头',xxx:xxx... }}]
  137. * @property {Boolean} showMonth 是否选择月份为背景
  138. * @property {[String} defaultValue 选择器打开时默认显示的时间
  139. * @event {Function} change 日期改变,`insert :ture` 时生效
  140. * @event {Function} confirm 确认选择`insert :false` 时生效
  141. * @event {Function} monthSwitch 切换月份时触发
  142. * @example <uni-calendar :insert="true" :start-date="'2019-3-2'":end-date="'2019-5-20'"@change="change" />
  143. */
  144. export default {
  145. components: {
  146. calendarItem,
  147. timePicker
  148. },
  149. props: {
  150. type: {
  151. type: String,
  152. default: 'week'
  153. },
  154. isMonday: {
  155. type: [Boolean],
  156. default: false
  157. },
  158. date: {
  159. type: String,
  160. default: ''
  161. },
  162. defTime: {
  163. type: [String, Object],
  164. default: ''
  165. },
  166. selectableTimes: {
  167. type: [Object],
  168. default() {
  169. return {};
  170. }
  171. },
  172. selected: {
  173. type: Array,
  174. default() {
  175. return [];
  176. }
  177. },
  178. startDate: {
  179. type: String,
  180. default: ''
  181. },
  182. endDate: {
  183. type: String,
  184. default: ''
  185. },
  186. startPlaceholder: {
  187. type: String,
  188. default: ''
  189. },
  190. endPlaceholder: {
  191. type: String,
  192. default: ''
  193. },
  194. range: {
  195. type: Boolean,
  196. default: false
  197. },
  198. hasTime: {
  199. type: Boolean,
  200. default: false
  201. },
  202. insert: {
  203. type: Boolean,
  204. default: true
  205. },
  206. showMonth: {
  207. type: Boolean,
  208. default: true
  209. },
  210. clearDate: {
  211. type: Boolean,
  212. default: true
  213. },
  214. checkHover: {
  215. type: Boolean,
  216. default: true
  217. },
  218. hideSecond: {
  219. type: [Boolean],
  220. default: false
  221. },
  222. pleStatus: {
  223. type: Object,
  224. default() {
  225. return {
  226. before: '',
  227. after: '',
  228. data: [],
  229. fulldate: ''
  230. };
  231. }
  232. },
  233. defaultValue: {
  234. type: [String, Object, Array],
  235. default: ''
  236. }
  237. },
  238. data() {
  239. return {
  240. show: false,
  241. weeks: [],
  242. calendar: {},
  243. nowDate: {},
  244. aniMaskShow: false,
  245. firstEnter: true,
  246. calendarList: [], //多选日期
  247. time: '',
  248. timeRange: {
  249. startTime: '',
  250. endTime: ''
  251. },
  252. tempSingleDate: '',
  253. tempRange: {
  254. before: '',
  255. after: ''
  256. }
  257. };
  258. },
  259. watch: {
  260. date: {
  261. immediate: true,
  262. handler(newVal) {
  263. if (!this.range) {
  264. this.tempSingleDate = newVal;
  265. setTimeout(() => {
  266. this.init(newVal);
  267. }, 100);
  268. }
  269. }
  270. },
  271. defTime: {
  272. immediate: true,
  273. handler(newVal) {
  274. if (!this.range) {
  275. this.time = newVal;
  276. } else {
  277. this.timeRange.startTime = newVal.start;
  278. this.timeRange.endTime = newVal.end;
  279. }
  280. }
  281. },
  282. startDate(val) {
  283. // 字节小程序 watch 早于 created
  284. if (!this.cale) {
  285. return;
  286. }
  287. this.cale.setStartDate(val);
  288. this.cale.setDate(this.nowDate.fullDate);
  289. this.weeks = this.cale.weeks;
  290. },
  291. endDate(val) {
  292. // 字节小程序 watch 早于 created
  293. if (!this.cale) {
  294. return;
  295. }
  296. this.cale.setEndDate(val);
  297. this.cale.setDate(this.nowDate.fullDate);
  298. this.weeks = this.cale.weeks;
  299. },
  300. selected(newVal) {
  301. // 字节小程序 watch 早于 created
  302. if (!this.cale) {
  303. return;
  304. }
  305. this.cale.setSelectInfo(this.nowDate.fullDate, newVal);
  306. this.weeks = this.cale.weeks;
  307. },
  308. pleStatus: {
  309. immediate: true,
  310. handler(newVal) {
  311. const { before, after, fulldate, which } = newVal;
  312. this.tempRange.before = before;
  313. this.tempRange.after = after;
  314. setTimeout(() => {
  315. if (fulldate) {
  316. this.cale.setHoverMultiple(fulldate);
  317. if (before && after) {
  318. this.cale.lastHover = true;
  319. if (this.rangeWithinMonth(after, before)) return;
  320. this.setDate(before);
  321. } else {
  322. this.cale.setMultiple(fulldate);
  323. this.setDate(this.nowDate.fullDate);
  324. this.calendar.fullDate = '';
  325. this.cale.lastHover = false;
  326. }
  327. } else {
  328. // 字节小程序 watch 早于 created
  329. if (!this.cale) {
  330. return;
  331. }
  332. this.cale.setDefaultMultiple(before, after);
  333. if (which === 'left' && before) {
  334. this.setDate(before);
  335. this.weeks = this.cale.weeks;
  336. } else if (after) {
  337. this.setDate(after);
  338. this.weeks = this.cale.weeks;
  339. }
  340. this.cale.lastHover = true;
  341. }
  342. }, 16);
  343. }
  344. }
  345. },
  346. computed: {
  347. timepickerStartTime() {
  348. const activeDate = this.range ? this.tempRange.before : this.calendar.fullDate;
  349. return activeDate === this.startDate ? this.selectableTimes.start : '';
  350. },
  351. timepickerEndTime() {
  352. const activeDate = this.range ? this.tempRange.after : this.calendar.fullDate;
  353. return activeDate === this.endDate ? this.selectableTimes.end : '';
  354. },
  355. /**
  356. * for i18n
  357. */
  358. selectDateText() {
  359. return t('uni-datetime-picker.selectDate');
  360. },
  361. startDateText() {
  362. return this.startPlaceholder || t('uni-datetime-picker.startDate');
  363. },
  364. endDateText() {
  365. return this.endPlaceholder || t('uni-datetime-picker.endDate');
  366. },
  367. okText() {
  368. return t('uni-datetime-picker.ok');
  369. },
  370. yearText() {
  371. return t('uni-datetime-picker.year');
  372. },
  373. monthText() {
  374. return t('uni-datetime-picker.month');
  375. },
  376. MONText() {
  377. return t('uni-calender.MON');
  378. },
  379. TUEText() {
  380. return t('uni-calender.TUE');
  381. },
  382. WEDText() {
  383. return t('uni-calender.WED');
  384. },
  385. THUText() {
  386. return t('uni-calender.THU');
  387. },
  388. FRIText() {
  389. return t('uni-calender.FRI');
  390. },
  391. SATText() {
  392. return t('uni-calender.SAT');
  393. },
  394. SUNText() {
  395. return t('uni-calender.SUN');
  396. },
  397. confirmText() {
  398. return t('uni-calender.confirm');
  399. }
  400. },
  401. created() {
  402. // 获取日历方法实例
  403. this.cale = new Calendar({
  404. selected: this.selected,
  405. startDate: this.startDate,
  406. endDate: this.endDate,
  407. range: this.range,
  408. isMonday: this.isMonday
  409. });
  410. // 选中某一天
  411. this.init(this.date);
  412. },
  413. methods: {
  414. leaveCale() {
  415. this.firstEnter = true;
  416. },
  417. handleMouse(weeks) {
  418. if (weeks.disable) return;
  419. if (this.cale.lastHover) return;
  420. let { before, after } = this.cale.multipleStatus;
  421. if (!before) return;
  422. this.calendar = weeks;
  423. // 设置范围选
  424. this.cale.setHoverMultiple(this.calendar.fullDate);
  425. this.weeks = this.cale.weeks;
  426. // hover时,进入一个日历,更新另一个
  427. if (this.firstEnter) {
  428. this.$emit('firstEnterCale', this.cale.multipleStatus);
  429. this.firstEnter = false;
  430. }
  431. },
  432. rangeWithinMonth(A, B) {
  433. const [yearA, monthA] = A.split('-');
  434. const [yearB, monthB] = B.split('-');
  435. return yearA === yearB && monthA === monthB;
  436. },
  437. // 蒙版点击事件
  438. maskClick() {
  439. this.close();
  440. this.$emit('maskClose');
  441. },
  442. clearCalender() {
  443. this.calendarList = [];
  444. if (this.range) {
  445. this.timeRange.startTime = '';
  446. this.timeRange.endTime = '';
  447. this.tempRange.before = '';
  448. this.tempRange.after = '';
  449. this.cale.multipleStatus.before = '';
  450. this.cale.multipleStatus.after = '';
  451. this.cale.multipleStatus.data = [];
  452. this.cale.lastHover = false;
  453. } else {
  454. this.time = '';
  455. this.tempSingleDate = '';
  456. }
  457. this.calendar.fullDate = '';
  458. this.setDate(new Date());
  459. },
  460. bindDateChange(e) {
  461. const value = e.detail.value + '-1';
  462. this.setDate(value);
  463. },
  464. /**
  465. * 初始化日期显示
  466. * @param {Object} date
  467. */
  468. init(date) {
  469. // 字节小程序 watch 早于 created
  470. if (!this.cale) {
  471. return;
  472. }
  473. if (this.type == 'dates') {
  474. if (date && date.length > 0) {
  475. this.cale.setDate(new Date(date[0]));
  476. this.weeks = this.cale.weeks;
  477. this.nowDate = this.cale.getInfo(date[0]);
  478. this.calendarList = date;
  479. } else {
  480. this.cale.setDate(new Date());
  481. this.weeks = this.cale.weeks;
  482. this.nowDate = this.cale.getInfo('');
  483. this.calendarList = date;
  484. }
  485. this.calendar = {
  486. fullDate: ''
  487. };
  488. return;
  489. }
  490. if (this.type == 'week') {
  491. console.log(date);
  492. if (date && date.length > 0) {
  493. let dateRrr = week_date(date[0] + '-' + date[1]);
  494. console.log('date', date);
  495. this.cale.setDate(new Date(dateRrr[0]));
  496. this.weeks = this.cale.weeks;
  497. this.nowDate = this.cale.getInfo(dateRrr[0]);
  498. this.calendar = {
  499. ...this.nowDate,
  500. year: date[0]
  501. };
  502. this.week = date[1];
  503. } else {
  504. this.cale.setDate(new Date());
  505. this.weeks = this.cale.weeks;
  506. this.nowDate = this.cale.getInfo('');
  507. this.calendar = {
  508. ...this.nowDate,
  509. year: date[0]
  510. };
  511. }
  512. return;
  513. }
  514. this.cale.setDate(date || new Date());
  515. this.weeks = this.cale.weeks;
  516. this.nowDate = this.cale.getInfo(date);
  517. this.calendar = {
  518. ...this.nowDate
  519. };
  520. if (!date) {
  521. // 优化date为空默认不选中今天
  522. this.calendar.fullDate = '';
  523. if (this.defaultValue && !this.range) {
  524. // 暂时只支持移动端非范围选择
  525. const defaultDate = new Date(this.defaultValue);
  526. const fullDate = getDate(defaultDate);
  527. const year = defaultDate.getFullYear();
  528. const month = defaultDate.getMonth() + 1;
  529. const date = defaultDate.getDate();
  530. const day = defaultDate.getDay();
  531. (this.calendar = {
  532. fullDate,
  533. year,
  534. month,
  535. date,
  536. day
  537. }),
  538. (this.tempSingleDate = fullDate);
  539. this.time = getTime(defaultDate, this.hideSecond);
  540. }
  541. }
  542. },
  543. /**
  544. * 打开日历弹窗
  545. */
  546. open() {
  547. // 弹窗模式并且清理数据
  548. if (this.clearDate && !this.insert) {
  549. this.cale.cleanMultipleStatus();
  550. this.init(this.date);
  551. }
  552. this.show = true;
  553. this.$nextTick(() => {
  554. setTimeout(() => {
  555. this.aniMaskShow = true;
  556. }, 50);
  557. });
  558. },
  559. /**
  560. * 关闭日历弹窗
  561. */
  562. close() {
  563. this.aniMaskShow = false;
  564. this.$nextTick(() => {
  565. setTimeout(() => {
  566. this.show = false;
  567. this.$emit('close');
  568. }, 300);
  569. });
  570. },
  571. /**
  572. * 确认按钮
  573. */
  574. confirm() {
  575. this.setEmit('confirm');
  576. this.close();
  577. },
  578. /**
  579. * 变化触发
  580. */
  581. change() {
  582. if (!this.insert) return;
  583. this.setEmit('change');
  584. },
  585. /**
  586. * 选择月份触发
  587. */
  588. monthSwitch() {
  589. let { year, month } = this.nowDate;
  590. this.$emit('monthSwitch', {
  591. year,
  592. month: Number(month)
  593. });
  594. },
  595. /**
  596. * 派发事件
  597. * @param {Object} name
  598. */
  599. setEmit(name) {
  600. if (this.type == 'dates') {
  601. this.$emit(name, JSON.parse(JSON.stringify(this.calendarList)));
  602. return;
  603. }
  604. if (!this.range) {
  605. if (!this.calendar.fullDate) {
  606. this.calendar = this.cale.getInfo(new Date());
  607. this.tempSingleDate = this.calendar.fullDate;
  608. }
  609. if (this.hasTime && !this.time) {
  610. this.time = getTime(new Date(), this.hideSecond);
  611. }
  612. }
  613. let { year, month, date, fullDate, extraInfo } = this.calendar;
  614. this.$emit(name, {
  615. range: this.cale.multipleStatus,
  616. year,
  617. month,
  618. date,
  619. time: this.time,
  620. week: this.week,
  621. timeRange: this.timeRange,
  622. fulldate: fullDate,
  623. extraInfo: extraInfo || {}
  624. });
  625. },
  626. changeWeek(dateObj) {
  627. let { date, weeks, year, week } = dateObj;
  628. // 获取当前第几周
  629. let yearWeek = year && week ? year + '-' + week : date.getFullYear() + '-' + getYearWeek(date.getFullYear(), Number(date.getMonth()) + 1, date.getDate());
  630. this.week = date ? getYearWeek(date.getFullYear(), Number(date.getMonth()) + 1, date.getDate()) : '';
  631. let dateList = week_date(yearWeek);
  632. dateList.forEach((e, index) => {
  633. let newWeeks = {};
  634. let weekDate = new Date(e);
  635. let todayDate = new Date().setHours(0, 0, 0, 0); //把今天的日期时分秒设置为00:00:00,返回一个时间戳,
  636. // todayDate就是今天00:00:00时刻的时间戳
  637. let paramsDate = new Date(e).setHours(0, 0, 0, 0); //给new Date()传入时间,并返回传入时间的时间戳
  638. newWeeks.isToday = todayDate === paramsDate; //时间戳相同时 True 就为今天
  639. if (index) {
  640. newWeeks.beforeMultiple = true;
  641. newWeeks.afterMultiple = false;
  642. this.tempRange.before = e;
  643. } else {
  644. newWeeks.afterMultiple = true;
  645. newWeeks.beforeMultiple = false;
  646. this.tempRange.after = e;
  647. }
  648. newWeeks.fullDate = e;
  649. //console.log(e);
  650. newWeeks.multiple = true;
  651. newWeeks.date = weekDate.getDate();
  652. newWeeks.month = Number(weekDate.getMonth()) + 1 < 10 ? '0' + (Number(weekDate.getMonth()) + 1) : Number(weekDate.getMonth()) + 1;
  653. newWeeks.year = weekDate.getFullYear();
  654. // if (weeks.disable) return
  655. this.calendar = newWeeks;
  656. this.calendar.userChecked = true;
  657. // 设置多选
  658. this.cale.setMultiple(this.calendar.fullDate, true);
  659. this.weeks = this.cale.weeks;
  660. this.tempSingleDate = this.calendar.fullDate;
  661. this.change();
  662. });
  663. // if (date.getFullYear() == new Date(dateList[0]).getFullYear()) {
  664. // } else if (date.getFullYear() == new Date(dateList[1]).getFullYear()) {
  665. // this.setDate(dateList[1]);
  666. // } else {
  667. // this.setDate(dateList[0]);
  668. // }
  669. this.calendar = weeks;
  670. this.setDate(weeks.fullDate);
  671. this.change();
  672. },
  673. /**
  674. * 选择天触发
  675. * @param {Object} weeks
  676. */
  677. choiceDate(weeks) {
  678. if (weeks.disable) return;
  679. console.log('weeks', weeks);
  680. if (this.type == 'week') {
  681. let date = new Date(weeks.fullDate);
  682. this.changeWeek({
  683. date,
  684. weeks
  685. });
  686. return;
  687. }
  688. if (this.type == 'dates') {
  689. if (this.calendarList.includes(weeks.fullDate)) {
  690. let index = this.calendarList.findIndex((e) => e == weeks.fullDate);
  691. this.calendarList.splice(index, 1);
  692. } else {
  693. this.calendarList.push(weeks.fullDate);
  694. }
  695. return;
  696. }
  697. this.calendar = weeks;
  698. this.calendar.userChecked = true;
  699. // 设置多选
  700. this.cale.setMultiple(this.calendar.fullDate, true);
  701. this.weeks = this.cale.weeks;
  702. this.tempSingleDate = this.calendar.fullDate;
  703. const beforeDate = new Date(this.cale.multipleStatus.before).getTime();
  704. const afterDate = new Date(this.cale.multipleStatus.after).getTime();
  705. if (beforeDate > afterDate && afterDate) {
  706. this.tempRange.before = this.cale.multipleStatus.after;
  707. this.tempRange.after = this.cale.multipleStatus.before;
  708. } else {
  709. this.tempRange.before = this.cale.multipleStatus.before;
  710. this.tempRange.after = this.cale.multipleStatus.after;
  711. }
  712. this.change();
  713. },
  714. changeMonth(type) {
  715. let newDate;
  716. if (type === 'pre') {
  717. newDate = this.cale.getPreMonthObj(this.nowDate.fullDate).fullDate;
  718. } else if (type === 'next') {
  719. newDate = this.cale.getNextMonthObj(this.nowDate.fullDate).fullDate;
  720. }
  721. this.setDate(newDate);
  722. this.monthSwitch();
  723. },
  724. /**
  725. * 设置日期
  726. * @param {Object} date
  727. */
  728. setDate(date) {
  729. this.cale.setDate(date);
  730. this.weeks = this.cale.weeks;
  731. this.nowDate = this.cale.getInfo(date);
  732. }
  733. }
  734. };
  735. </script>
  736. <style lang="scss">
  737. $uni-primary: #007aff !default;
  738. .uni-calendar {
  739. /* #ifndef APP-NVUE */
  740. display: flex;
  741. /* #endif */
  742. flex-direction: column;
  743. }
  744. .uni-calendar__mask {
  745. position: fixed;
  746. bottom: 0;
  747. top: 0;
  748. left: 0;
  749. right: 0;
  750. background-color: rgba(0, 0, 0, 0.4);
  751. transition-property: opacity;
  752. transition-duration: 0.3s;
  753. opacity: 0;
  754. /* #ifndef APP-NVUE */
  755. z-index: 99;
  756. /* #endif */
  757. }
  758. .uni-calendar--mask-show {
  759. opacity: 1;
  760. }
  761. .uni-calendar--fixed {
  762. position: fixed;
  763. bottom: calc(var(--window-bottom));
  764. left: 0;
  765. right: 0;
  766. transition-property: transform;
  767. transition-duration: 0.3s;
  768. transform: translateY(460px);
  769. /* #ifndef APP-NVUE */
  770. z-index: 99;
  771. /* #endif */
  772. }
  773. .uni-calendar--ani-show {
  774. transform: translateY(0);
  775. }
  776. .uni-calendar__content {
  777. background-color: #fff;
  778. }
  779. .uni-calendar__content-mobile {
  780. border-top-left-radius: 10px;
  781. border-top-right-radius: 10px;
  782. box-shadow: 0px 0px 5px 3px rgba(0, 0, 0, 0.1);
  783. }
  784. .uni-calendar__header {
  785. position: relative;
  786. /* #ifndef APP-NVUE */
  787. display: flex;
  788. /* #endif */
  789. flex-direction: row;
  790. justify-content: center;
  791. align-items: center;
  792. height: 50px;
  793. }
  794. .uni-calendar__header-mobile {
  795. padding: 10px;
  796. padding-bottom: 0;
  797. }
  798. .uni-calendar--fixed-top {
  799. /* #ifndef APP-NVUE */
  800. display: flex;
  801. /* #endif */
  802. flex-direction: row;
  803. justify-content: space-between;
  804. border-top-color: rgba(0, 0, 0, 0.4);
  805. border-top-style: solid;
  806. border-top-width: 1px;
  807. }
  808. .uni-calendar--fixed-width {
  809. width: 50px;
  810. }
  811. .uni-calendar__backtoday {
  812. position: absolute;
  813. right: 0;
  814. top: 25rpx;
  815. padding: 0 5px;
  816. padding-left: 10px;
  817. height: 25px;
  818. line-height: 25px;
  819. font-size: 12px;
  820. border-top-left-radius: 25px;
  821. border-bottom-left-radius: 25px;
  822. color: #fff;
  823. background-color: #f1f1f1;
  824. }
  825. .uni-calendar__header-text {
  826. text-align: center;
  827. width: 100px;
  828. font-size: 15px;
  829. color: #666;
  830. }
  831. .uni-calendar__button-text {
  832. text-align: center;
  833. width: 100px;
  834. font-size: 14px;
  835. color: $uni-primary;
  836. /* #ifndef APP-NVUE */
  837. letter-spacing: 3px;
  838. /* #endif */
  839. }
  840. .uni-calendar__header-btn-box {
  841. /* #ifndef APP-NVUE */
  842. display: flex;
  843. /* #endif */
  844. flex-direction: row;
  845. align-items: center;
  846. justify-content: center;
  847. width: 50px;
  848. height: 50px;
  849. }
  850. .uni-calendar__header-btn {
  851. width: 9px;
  852. height: 9px;
  853. border-left-color: #808080;
  854. border-left-style: solid;
  855. border-left-width: 1px;
  856. border-top-color: #555555;
  857. border-top-style: solid;
  858. border-top-width: 1px;
  859. }
  860. .uni-calendar--left {
  861. transform: rotate(-45deg);
  862. }
  863. .uni-calendar--right {
  864. transform: rotate(135deg);
  865. }
  866. .uni-calendar__weeks {
  867. position: relative;
  868. /* #ifndef APP-NVUE */
  869. display: flex;
  870. /* #endif */
  871. flex-direction: row;
  872. }
  873. .uni-calendar__weeks-item {
  874. flex: 1;
  875. }
  876. .uni-calendar__weeks-day {
  877. flex: 1;
  878. /* #ifndef APP-NVUE */
  879. display: flex;
  880. /* #endif */
  881. flex-direction: column;
  882. justify-content: center;
  883. align-items: center;
  884. height: 40px;
  885. border-bottom-color: #f5f5f5;
  886. border-bottom-style: solid;
  887. border-bottom-width: 1px;
  888. }
  889. .uni-calendar__weeks-day-text {
  890. font-size: 12px;
  891. color: #b2b2b2;
  892. }
  893. .uni-calendar__box {
  894. position: relative;
  895. // padding: 0 10px;
  896. padding-bottom: 7px;
  897. }
  898. .uni-calendar__box-bg {
  899. /* #ifndef APP-NVUE */
  900. display: flex;
  901. /* #endif */
  902. justify-content: center;
  903. align-items: center;
  904. position: absolute;
  905. top: 0;
  906. left: 0;
  907. right: 0;
  908. bottom: 0;
  909. }
  910. .uni-calendar__box-bg-text {
  911. font-size: 200px;
  912. font-weight: bold;
  913. color: #999;
  914. opacity: 0.1;
  915. text-align: center;
  916. /* #ifndef APP-NVUE */
  917. line-height: 1;
  918. /* #endif */
  919. }
  920. .uni-date-changed {
  921. padding: 0 10px;
  922. // line-height: 50px;
  923. text-align: center;
  924. color: #333;
  925. border-top-color: #dcdcdc;
  926. border-top-style: solid;
  927. border-top-width: 1px;
  928. flex: 1;
  929. }
  930. .uni-date-btn--ok {
  931. padding: 20px 15px;
  932. }
  933. .uni-date-changed--time-start {
  934. /* #ifndef APP-NVUE */
  935. display: flex;
  936. /* #endif */
  937. align-items: center;
  938. }
  939. .uni-date-changed--time-end {
  940. /* #ifndef APP-NVUE */
  941. display: flex;
  942. /* #endif */
  943. align-items: center;
  944. }
  945. .uni-date-changed--time-date {
  946. color: #999;
  947. line-height: 50px;
  948. /* #ifdef MP-TOUTIAO */
  949. font-size: 16px;
  950. /* #endif */
  951. margin-right: 5px;
  952. // opacity: 0.6;
  953. }
  954. .time-picker-style {
  955. // width: 62px;
  956. /* #ifndef APP-NVUE */
  957. display: flex;
  958. /* #endif */
  959. justify-content: center;
  960. align-items: center;
  961. }
  962. .mr-10 {
  963. margin-right: 10px;
  964. }
  965. .dialog-close {
  966. position: absolute;
  967. top: 0;
  968. right: 0;
  969. bottom: 0;
  970. /* #ifndef APP-NVUE */
  971. display: flex;
  972. /* #endif */
  973. flex-direction: row;
  974. align-items: center;
  975. padding: 0 25px;
  976. margin-top: 10px;
  977. }
  978. .dialog-close-plus {
  979. width: 16px;
  980. height: 2px;
  981. background-color: #737987;
  982. border-radius: 2px;
  983. transform: rotate(45deg);
  984. }
  985. .dialog-close-rotate {
  986. position: absolute;
  987. transform: rotate(-45deg);
  988. }
  989. .uni-datetime-picker--btn {
  990. border-radius: 100px;
  991. height: 40px;
  992. line-height: 40px;
  993. background-color: $uni-primary;
  994. color: #fff;
  995. font-size: 16px;
  996. letter-spacing: 2px;
  997. }
  998. /* #ifndef APP-NVUE */
  999. .uni-datetime-picker--btn:active {
  1000. opacity: 0.7;
  1001. }
  1002. /* #endif */
  1003. </style>