¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <u-popup |
| | | :show="show" |
| | | mode="bottom" |
| | | closeable |
| | | @close="close" |
| | | :round="round" |
| | | :closeOnClickOverlay="closeOnClickOverlay" |
| | | > |
| | | <view class="u-calendar"> |
| | | <uHeader |
| | | :title="title" |
| | | :subtitle="subtitle" |
| | | :showSubtitle="showSubtitle" |
| | | :showTitle="showTitle" |
| | | ></uHeader> |
| | | <scroll-view |
| | | :style="{ |
| | | height: $u.addUnit(listHeight) |
| | | }" |
| | | scroll-y |
| | | @scroll="onScroll" |
| | | :scroll-top="scrollTop" |
| | | :scrollIntoView="scrollIntoView" |
| | | > |
| | | <uMonth |
| | | :color="color" |
| | | :rowHeight="rowHeight" |
| | | :showMark="showMark" |
| | | :months="months" |
| | | :mode="mode" |
| | | :maxCount="maxCount" |
| | | :startText="startText" |
| | | :endText="endText" |
| | | :defaultDate="defaultDate" |
| | | :minDate="innerMinDate" |
| | | :maxDate="innerMaxDate" |
| | | :maxMonth="monthNum" |
| | | :readonly="readonly" |
| | | :maxRange="maxRange" |
| | | :rangePrompt="rangePrompt" |
| | | :showRangePrompt="showRangePrompt" |
| | | :allowSameDay="allowSameDay" |
| | | ref="month" |
| | | @monthSelected="monthSelected" |
| | | @updateMonthTop="updateMonthTop" |
| | | ></uMonth> |
| | | </scroll-view> |
| | | <slot name="footer" v-if="showConfirm"> |
| | | <view class="u-calendar__confirm"> |
| | | <u-button |
| | | shape="circle" |
| | | :text=" |
| | | buttonDisabled ? confirmDisabledText : confirmText |
| | | " |
| | | :color="color" |
| | | @click="confirm" |
| | | :disabled="buttonDisabled" |
| | | ></u-button> |
| | | </view> |
| | | </slot> |
| | | </view> |
| | | </u-popup> |
| | | </template> |
| | | |
| | | <script> |
| | | import uHeader from './header.vue' |
| | | import uMonth from './month.vue' |
| | | import props from './props.js' |
| | | import util from './util.js' |
| | | import dayjs from '../../libs/util/dayjs.js' |
| | | import Calendar from '../../libs/util/calendar.js' |
| | | /** |
| | | * Calendar æ¥å |
| | | * @description æ¤ç»ä»¶ç¨äºåä¸ªéæ©æ¥æï¼èå´éæ©æ¥æçï¼æ¥å被å
裹å¨åºé¨å¼¹èµ·ç容å¨ä¸. |
| | | * @tutorial https://www.uviewui.com/components/calendar.html |
| | | * |
| | | * @property {String} title æ é¢å
容 (é»è®¤ æ¥æéæ© ) |
| | | * @property {Boolean} showTitle æ¯å¦æ¾ç¤ºæ é¢ (é»è®¤ true ) |
| | | * @property {Boolean} showSubtitle æ¯å¦æ¾ç¤ºå¯æ é¢ (é»è®¤ true ) |
| | | * @property {String} mode æ¥æç±»åéæ© single-éæ©åä¸ªæ¥æï¼multiple-å¯ä»¥éæ©å¤ä¸ªæ¥æï¼range-éæ©æ¥æèå´ ï¼ é»è®¤ 'single' ) |
| | | * @property {String} startText mode=rangeæ¶ï¼ç¬¬ä¸ä¸ªæ¥æåºé¨çæç¤ºæå (é»è®¤ 'å¼å§' ) |
| | | * @property {String} endText mode=rangeæ¶ï¼æåä¸ä¸ªæ¥æåºé¨çæç¤ºæå (é»è®¤ 'ç»æ' ) |
| | | * @property {Array} customList èªå®ä¹å表 |
| | | * @property {String} color 主é¢è²ï¼å¯¹åºé¨æé®åé䏿¥æææ (é»è®¤ â#3c9cff' ) |
| | | * @property {String | Number} minDate æå°çå¯éæ¥æ (é»è®¤ 0 ) |
| | | * @property {String | Number} maxDate æå¤§å¯éæ¥æ (é»è®¤ 0 ) |
| | | * @property {Array | String| Date} defaultDate é»è®¤éä¸çæ¥æï¼mode为multipleærangeæ¯å¿
须为æ°ç»æ ¼å¼ |
| | | * @property {String | Number} maxCount mode=multipleæ¶ï¼æå¤å¯éå¤å°ä¸ªæ¥æ (é»è®¤ Number.MAX_SAFE_INTEGER ) |
| | | * @property {String | Number} rowHeight æ¥æè¡é« (é»è®¤ 56 ) |
| | | * @property {Function} formatter æ¥ææ ¼å¼å彿° |
| | | * @property {Boolean} showLunar æ¯å¦æ¾ç¤ºåå (é»è®¤ false ) |
| | | * @property {Boolean} showMark æ¯å¦æ¾ç¤ºæä»½èæ¯è² (é»è®¤ true ) |
| | | * @property {String} confirmText ç¡®å®æé®çæå (é»è®¤ 'ç¡®å®' ) |
| | | * @property {String} confirmDisabledText 确认æé®å¤äºç¦ç¨ç¶ææ¶çæå (é»è®¤ 'ç¡®å®' ) |
| | | * @property {Boolean} show æ¯å¦æ¾ç¤ºæ¥åå¼¹çª (é»è®¤ false ) |
| | | * @property {Boolean} closeOnClickOverlay æ¯å¦å
许ç¹å»é®ç½©å
³éæ¥å (é»è®¤ false ) |
| | | * @property {Boolean} readonly æ¯å¦ä¸ºåªè¯»ç¶æï¼åªè¯»ç¶æä¸ç¦æ¢éæ©æ¥æ (é»è®¤ false ) |
| | | * @property {String | Number} maxRange æ¥æåºé´æå¤å¯é天æ°ï¼é»è®¤æ éå¶ï¼mode = rangeæ¶ææ |
| | | * @property {String} rangePrompt èå´éæ©è¶
è¿æå¤å¯éå¤©æ°æ¶çæç¤ºææ¡ï¼mode = rangeæ¶ææ |
| | | * @property {Boolean} showRangePrompt èå´éæ©è¶
è¿æå¤å¯éå¤©æ°æ¶ï¼æ¯å¦å±ç¤ºæç¤ºææ¡ï¼mode = rangeæ¶ææ (é»è®¤ true ) |
| | | * @property {Boolean} allowSameDay æ¯å¦å
è®¸æ¥æèå´çèµ·æ¢æ¶é´ä¸ºåä¸å¤©ï¼mode = rangeæ¶ææ (é»è®¤ false ) |
| | | * @property {Number|String} round åè§å¼ï¼é»è®¤æ åè§ (é»è®¤ 0 ) |
| | | * @property {Number|String} monthNum æå¤å±ç¤ºçæä»½æ°é (é»è®¤ 3 ) |
| | | * |
| | | * @event {Function()} confirm ç¹å»ç¡®å®æé®æ¶è§¦å éæ©æ¥æç¸å
³çè¿ååæ° |
| | | * @event {Function()} close æ¥åå
³éæ¶è§¦å å¯å®ä¹é¡µé¢å
³éæ¶çåè°äºä»¶ |
| | | * @example <u-calendar :defaultDate="defaultDateMultiple" :show="show" mode="multiple" @confirm="confirm"> |
| | | </u-calendar> |
| | | * */ |
| | | export default { |
| | | name: 'u-calendar', |
| | | mixins: [uni.$u.mpMixin, uni.$u.mixin, props], |
| | | components: { |
| | | uHeader, |
| | | uMonth |
| | | }, |
| | | data() { |
| | | return { |
| | | // éè¦æ¾ç¤ºçæä»½çæ°ç» |
| | | months: [], |
| | | // 卿份æ»å¨åºåä¸ï¼å½åè§å¾ä¸æä»½çindexç´¢å¼ |
| | | monthIndex: 0, |
| | | // æä»½æ»å¨åºåçé«åº¦ |
| | | listHeight: 0, |
| | | // monthç»ä»¶ä¸éæ©çæ¥ææ°ç» |
| | | selected: [], |
| | | scrollIntoView: '', |
| | | scrollTop:0, |
| | | // è¿æ»¤å¤çæ¹æ³ |
| | | innerFormatter: (value) => value |
| | | } |
| | | }, |
| | | watch: { |
| | | selectedChange: { |
| | | immediate: true, |
| | | handler(n) { |
| | | this.setMonth() |
| | | } |
| | | }, |
| | | // æå¼å¼¹çªæ¶ï¼è®¾ç½®æä»½æ°æ® |
| | | show: { |
| | | immediate: true, |
| | | handler(n) { |
| | | this.setMonth() |
| | | } |
| | | } |
| | | }, |
| | | computed: { |
| | | // ç±äºmaxDateåminDateå¯ä»¥ä¸ºå符串(2021-10-10)ï¼æè
æ°å¼(æ¶é´æ³)ï¼ä½æ¯dayjs妿æ¥åå符串形å¼çæ¶é´æ³ä¼æé®é¢ï¼è¿éè¿è¡å¤ç |
| | | innerMaxDate() { |
| | | return uni.$u.test.number(this.maxDate) |
| | | ? Number(this.maxDate) |
| | | : this.maxDate |
| | | }, |
| | | innerMinDate() { |
| | | return uni.$u.test.number(this.minDate) |
| | | ? Number(this.minDate) |
| | | : this.minDate |
| | | }, |
| | | // å¤ä¸ªæ¡ä»¶çååï¼ä¼å¼èµ·é䏿¥æçååï¼è¿éç»ä¸ç®¡ççå¬ |
| | | selectedChange() { |
| | | return [this.innerMinDate, this.innerMaxDate, this.defaultDate] |
| | | }, |
| | | subtitle() { |
| | | // åå§åæ¶ï¼this.months为空æ°ç»ï¼æä»¥éè¦ç¹å«å¤æå¤ç |
| | | if (this.months.length) { |
| | | return `${this.months[this.monthIndex].year}å¹´${ |
| | | this.months[this.monthIndex].month |
| | | }æ` |
| | | } else { |
| | | return '' |
| | | } |
| | | }, |
| | | buttonDisabled() { |
| | | // å¦æä¸ºrangeç±»åï¼ä¸éæ©çæ¥æä¸ªæ°ä¸è¶³1个æ¶ï¼è®©åºé¨çæé®åºäºdisabledç¶æ |
| | | if (this.mode === 'range') { |
| | | if (this.selected.length <= 1) { |
| | | return true |
| | | } else { |
| | | return false |
| | | } |
| | | } else { |
| | | return false |
| | | } |
| | | } |
| | | }, |
| | | mounted() { |
| | | this.start = Date.now() |
| | | this.init() |
| | | }, |
| | | methods: { |
| | | // å¨å¾®ä¿¡å°ç¨åºä¸ï¼ä¸æ¯æå°å½æ°å½åpropsåæ°ï¼æ
åªè½éè¿refå½¢å¼è°ç¨ |
| | | setFormatter(e) { |
| | | this.innerFormatter = e |
| | | }, |
| | | // monthç»ä»¶å
é¨éæ©æ¥æåï¼éè¿äºä»¶éç¥ç»ç¶ç»ä»¶ |
| | | monthSelected(e) { |
| | | this.selected = e |
| | | if (!this.showConfirm) { |
| | | // å¨ä¸éè¦ç¡®è®¤æé®çæ
åµä¸ï¼å¦æä¸ºåéï¼æè
èå´å¤éä¸å·²éé¿åº¦å¤§äº2ï¼åç´æ¥è¿è¡è¿è¿ |
| | | if ( |
| | | this.mode === 'multiple' || |
| | | this.mode === 'single' || |
| | | (this.mode === 'range' && this.selected.length >= 2) |
| | | ) { |
| | | this.$emit('confirm', this.selected) |
| | | } |
| | | } |
| | | }, |
| | | init() { |
| | | // æ ¡éªmaxDateï¼ä¸è½å°äºminDate |
| | | if ( |
| | | this.innerMaxDate && |
| | | this.innerMinDate && |
| | | new Date(this.innerMaxDate).getTime() < new Date(this.innerMinDate).getTime() |
| | | ) { |
| | | return uni.$u.error('maxDateä¸è½å°äºminDate') |
| | | } |
| | | // æ»å¨åºåçé«åº¦ |
| | | this.listHeight = this.rowHeight * 5 + 30 |
| | | this.setMonth() |
| | | }, |
| | | close() { |
| | | this.$emit('close') |
| | | }, |
| | | // ç¹å»ç¡®å®æé® |
| | | confirm() { |
| | | if (!this.buttonDisabled) { |
| | | this.$emit('confirm', this.selected) |
| | | } |
| | | }, |
| | | // è·å¾ä¸¤ä¸ªæ¥æä¹é´çæä»½æ° |
| | | getMonths(minDate, maxDate) { |
| | | const minYear = dayjs(minDate).year() |
| | | const minMonth = dayjs(minDate).month() + 1 |
| | | const maxYear = dayjs(maxDate).year() |
| | | const maxMonth = dayjs(maxDate).month() + 1 |
| | | return (maxYear - minYear) * 12 + (maxMonth - minMonth) + 1 |
| | | }, |
| | | // 设置æä»½æ°æ® |
| | | setMonth() { |
| | | // æå°æ¥æçæ¯«ç§æ° |
| | | const minDate = this.innerMinDate || dayjs().valueOf() |
| | | // å¦ææ²¡ææå®æå¤§æ¥æï¼åå¾åæ¨3个æ |
| | | const maxDate = |
| | | this.innerMaxDate || |
| | | dayjs(minDate) |
| | | .add(this.monthNum - 1, 'month') |
| | | .valueOf() |
| | | // æå¤§æå°æä»½ä¹é´çå
±æå¤å°ä¸ªæä»½ï¼ |
| | | const months = uni.$u.range( |
| | | 1, |
| | | this.monthNum, |
| | | this.getMonths(minDate, maxDate) |
| | | ) |
| | | // å
æ¸
空æ°ç» |
| | | this.months = [] |
| | | for (let i = 0; i < months; i++) { |
| | | this.months.push({ |
| | | date: new Array( |
| | | dayjs(minDate).add(i, 'month').daysInMonth() |
| | | ) |
| | | .fill(1) |
| | | .map((item, index) => { |
| | | // æ¥æï¼åå¼1-31 |
| | | let day = index + 1 |
| | | // ææï¼0-6ï¼0ä¸ºå¨æ¥ |
| | | const week = dayjs(minDate) |
| | | .add(i, 'month') |
| | | .date(day) |
| | | .day() |
| | | const date = dayjs(minDate) |
| | | .add(i, 'month') |
| | | .date(day) |
| | | .format('YYYY-MM-DD') |
| | | let bottomInfo = '' |
| | | if (this.showLunar) { |
| | | // å°æ¥æè½¬ä¸ºååæ ¼å¼ |
| | | const lunar = Calendar.solar2lunar( |
| | | dayjs(date).year(), |
| | | dayjs(date).month() + 1, |
| | | dayjs(date).date() |
| | | ) |
| | | bottomInfo = lunar.IDayCn |
| | | } |
| | | let config = { |
| | | day, |
| | | week, |
| | | // å°äºæå°å
è®¸çæ¥æï¼æè
å¤§äºæå¤§çæ¥æï¼å设置为disabledç¶æ |
| | | disabled: |
| | | dayjs(date).isBefore( |
| | | dayjs(minDate).format('YYYY-MM-DD') |
| | | ) || |
| | | dayjs(date).isAfter( |
| | | dayjs(maxDate).format('YYYY-MM-DD') |
| | | ), |
| | | // è¿åä¸ä¸ªæ¥æå¯¹è±¡ï¼ä¾å¤é¨çformatterè·åå½åæ¥æçå¹´ææ¥çä¿¡æ¯ï¼è¿è¡å å·¥å¤ç |
| | | date: new Date(date), |
| | | bottomInfo, |
| | | dot: false, |
| | | month: |
| | | dayjs(minDate).add(i, 'month').month() + 1 |
| | | } |
| | | const formatter = |
| | | this.formatter || this.innerFormatter |
| | | return formatter(config) |
| | | }), |
| | | // å½åæå±çæä»½ |
| | | month: dayjs(minDate).add(i, 'month').month() + 1, |
| | | // å½å年份 |
| | | year: dayjs(minDate).add(i, 'month').year() |
| | | }) |
| | | } |
| | | |
| | | }, |
| | | // æ»å¨å°é»è®¤è®¾ç½®çæä»½ |
| | | scrollIntoDefaultMonth(selected) { |
| | | // æ¥è¯¢é»è®¤æ¥æå¨å¯éå表ç䏿 |
| | | const _index = this.months.findIndex(({ |
| | | year, |
| | | month |
| | | }) => { |
| | | month = uni.$u.padZero(month) |
| | | return `${year}-${month}` === selected |
| | | }) |
| | | if (_index !== -1) { |
| | | // #ifndef MP-WEIXIN |
| | | this.$nextTick(() => { |
| | | this.scrollIntoView = `month-${_index}` |
| | | }) |
| | | // #endif |
| | | // #ifdef MP-WEIXIN |
| | | this.scrollTop = this.months[_index].top || 0; |
| | | // #endif |
| | | } |
| | | }, |
| | | // scroll-viewæ»å¨çå¬ |
| | | onScroll(event) { |
| | | // ä¸å
许å°äº0çæ»å¨å¼ï¼å¦æscroll-viewå°é¡¶äºï¼ç»§ç»ä¸æï¼ä¼åºç°è´æ°å¼ |
| | | const scrollTop = Math.max(0, event.detail.scrollTop) |
| | | // å°å½åæ»å¨æ¡æ°å¼ï¼é¤ä»¥æ»å¨åºåçé«åº¦ï¼å¯ä»¥å¾åºå½åæ»å¨å°äºåªä¸ä¸ªæä»½çç´¢å¼ |
| | | for (let i = 0; i < this.months.length; i++) { |
| | | if (scrollTop >= (this.months[i].top || this.listHeight)) { |
| | | this.monthIndex = i |
| | | } |
| | | } |
| | | }, |
| | | // æ´æ°æä»½çtopå¼ |
| | | updateMonthTop(topArr = []) { |
| | | // è®¾ç½®å¯¹åºæä»½çtopå¼ï¼ç¨äºonScrollæ¹æ³æ´æ°æä»½ |
| | | topArr.map((item, index) => { |
| | | this.months[index].top = item |
| | | }) |
| | | |
| | | // è·åé»è®¤æ¥æç䏿 |
| | | if (!this.defaultDate) { |
| | | // å¦ææ²¡æè®¾ç½®é»è®¤æ¥æï¼åå°å½å¤©æ¥æè®¾ç½®ä¸ºé»è®¤éä¸çæ¥æ |
| | | const selected = dayjs().format("YYYY-MM") |
| | | this.scrollIntoDefaultMonth(selected) |
| | | return |
| | | } |
| | | let selected = dayjs().format("YYYY-MM"); |
| | | // å鿍¡å¼ï¼å¯ä»¥æ¯åç¬¦ä¸²ææ°ç»ï¼Date对象ç |
| | | if (!uni.$u.test.array(this.defaultDate)) { |
| | | selected = dayjs(this.defaultDate).format("YYYY-MM") |
| | | } else { |
| | | selected = dayjs(this.defaultDate[0]).format("YYYY-MM"); |
| | | } |
| | | this.scrollIntoDefaultMonth(selected) |
| | | } |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | @import '../../libs/css/components.scss'; |
| | | |
| | | .u-calendar { |
| | | &__confirm { |
| | | padding: 7px 18px; |
| | | } |
| | | } |
| | | </style> |