123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384 |
- <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'
- export default {
- name: 'u-calendar',
- mixins: [uni.$u.mpMixin, uni.$u.mixin, props],
- components: {
- uHeader,
- uMonth
- },
- data() {
- return {
-
- months: [],
-
- monthIndex: 0,
-
- listHeight: 0,
-
- selected: [],
- scrollIntoView: '',
- scrollTop:0,
-
- innerFormatter: (value) => value
- }
- },
- watch: {
- selectedChange: {
- immediate: true,
- handler(n) {
- this.setMonth()
- }
- },
-
- show: {
- immediate: true,
- handler(n) {
- this.setMonth()
- }
- }
- },
- computed: {
-
- 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() {
-
- if (this.months.length) {
- return `${this.months[this.monthIndex].year}年${
- this.months[this.monthIndex].month
- }月`
- } else {
- return ''
- }
- },
- buttonDisabled() {
-
- 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: {
-
- setFormatter(e) {
- this.innerFormatter = e
- },
-
- monthSelected(e) {
- this.selected = e
- if (!this.showConfirm) {
-
- if (
- this.mode === 'multiple' ||
- this.mode === 'single' ||
- (this.mode === 'range' && this.selected.length >= 2)
- ) {
- this.$emit('confirm', this.selected)
- }
- }
- },
- init() {
-
- 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()
-
- 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) => {
-
- let day = index + 1
-
- 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:
- dayjs(date).isBefore(
- dayjs(minDate).format('YYYY-MM-DD')
- ) ||
- dayjs(date).isAfter(
- dayjs(maxDate).format('YYYY-MM-DD')
- ),
-
- 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) {
-
- this.$nextTick(() => {
- this.scrollIntoView = `month-${_index}`
- })
-
-
- this.scrollTop = this.months[_index].top || 0;
-
- }
- },
-
- onScroll(event) {
-
- 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
- }
- }
- },
-
- updateMonthTop(topArr = []) {
-
- 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");
-
- 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>
|