From d8b41fff43a2cee6a8f714ffa807623b15803786 Mon Sep 17 00:00:00 2001 From: quanyawei <401863037@qq.com> Date: Fri, 20 Oct 2023 15:21:35 +0800 Subject: [PATCH] fix:立行立改Uniapp小程序新建项目 --- uni_modules/uview-ui/components/u-calendar/month.vue | 579 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 579 insertions(+), 0 deletions(-) diff --git a/uni_modules/uview-ui/components/u-calendar/month.vue b/uni_modules/uview-ui/components/u-calendar/month.vue new file mode 100644 index 0000000..c20937f --- /dev/null +++ b/uni_modules/uview-ui/components/u-calendar/month.vue @@ -0,0 +1,579 @@ +<template> + <view class="u-calendar-month-wrapper" ref="u-calendar-month-wrapper"> + <view v-for="(item, index) in months" :key="index" :class="[`u-calendar-month-${index}`]" + :ref="`u-calendar-month-${index}`" :id="`month-${index}`"> + <text v-if="index !== 0" class="u-calendar-month__title">{{ item.year }}���{{ item.month }}���</text> + <view class="u-calendar-month__days"> + <view v-if="showMark" class="u-calendar-month__days__month-mark-wrapper"> + <text class="u-calendar-month__days__month-mark-wrapper__text">{{ item.month }}</text> + </view> + <view class="u-calendar-month__days__day" v-for="(item1, index1) in item.date" :key="index1" + :style="[dayStyle(index, index1, item1)]" @tap="clickHandler(index, index1, item1)" + :class="[item1.selected && 'u-calendar-month__days__day__select--selected']"> + <view class="u-calendar-month__days__day__select" :style="[daySelectStyle(index, index1, item1)]"> + <text class="u-calendar-month__days__day__select__info" + :class="[item1.disabled && 'u-calendar-month__days__day__select__info--disabled']" + :style="[textStyle(item1)]">{{ item1.day }}</text> + <text v-if="getBottomInfo(index, index1, item1)" + class="u-calendar-month__days__day__select__buttom-info" + :class="[item1.disabled && 'u-calendar-month__days__day__select__buttom-info--disabled']" + :style="[textStyle(item1)]">{{ getBottomInfo(index, index1, item1) }}</text> + <text v-if="item1.dot" class="u-calendar-month__days__day__select__dot"></text> + </view> + </view> + </view> + </view> + </view> +</template> + +<script> + // #ifdef APP-NVUE + // ������nvue��������������������������������������������������������������������������� + const dom = uni.requireNativePlugin('dom') + // #endif + import dayjs from '../../libs/util/dayjs.js'; + export default { + name: 'u-calendar-month', + mixins: [uni.$u.mpMixin, uni.$u.mixin], + props: { + // ��������������������������� + showMark: { + type: Boolean, + default: true + }, + // ������������������������������������������������ + color: { + type: String, + default: '#3c9cff' + }, + // ������������ + months: { + type: Array, + default: () => [] + }, + // ������������������ + mode: { + type: String, + default: 'single' + }, + // ������������ + rowHeight: { + type: [String, Number], + default: 58 + }, + // mode=multiple��������������������������������� + maxCount: { + type: [String, Number], + default: Infinity + }, + // mode=range������������������������������������������ + startText: { + type: String, + default: '������' + }, + // mode=range��������������������������������������������� + endText: { + type: String, + default: '������' + }, + // ������������������������mode���multiple���range������������������������ + defaultDate: { + type: [Array, String, Date], + default: null + }, + // ��������������������� + minDate: { + type: [String, Number], + default: 0 + }, + // ������������������ + maxDate: { + type: [String, Number], + default: 0 + }, + // ������������������maxDate��������������������������� + maxMonth: { + type: [String, Number], + default: 2 + }, + // ��������������������������������������������������������� + readonly: { + type: Boolean, + default: uni.$u.props.calendar.readonly + }, + // ���������������������������������������������������mode = range��������� + maxRange: { + type: [Number, String], + default: Infinity + }, + // ���������������������������������������������������������mode = range��������� + rangePrompt: { + type: String, + default: '' + }, + // ���������������������������������������������������������������������mode = range��������� + showRangePrompt: { + type: Boolean, + default: true + }, + // ������������������������������������������������������mode = range��������� + allowSameDay: { + type: Boolean, + default: false + } + }, + data() { + return { + // ��������������������� + width: 0, + // ���������������������item + item: {}, + selected: [] + } + }, + watch: { + selectedChange: { + immediate: true, + handler(n) { + this.setDefaultDate() + } + } + }, + computed: { + // ��������������������������������������������������������������������������������� + selectedChange() { + return [this.minDate, this.maxDate, this.defaultDate] + }, + dayStyle(index1, index2, item) { + return (index1, index2, item) => { + const style = {} + let week = item.week + // ������������������������������������2��������� + const dayWidth = Number(parseFloat(this.width / 7).toFixed(3).slice(0, -1)) + // ��������������������������� + // #ifdef APP-NVUE + style.width = uni.$u.addUnit(dayWidth) + // #endif + style.height = uni.$u.addUnit(this.rowHeight) + if (index2 === 0) { + // ������������������������������������0������������������������������������������������������������������������item������ + week = (week === 0 ? 7 : week) - 1 + style.marginLeft = uni.$u.addUnit(week * dayWidth) + } + if (this.mode === 'range') { + // ������������������������������������DCloud���������iOS������������������������������������������bug + style.paddingLeft = 0 + style.paddingRight = 0 + style.paddingBottom = 0 + style.paddingTop = 0 + } + return style + } + }, + daySelectStyle() { + return (index1, index2, item) => { + let date = dayjs(item.date).format("YYYY-MM-DD"), + style = {} + // ������date���������selected������������������������������������������0���������������dateSame���������������������������includes������ + if (this.selected.some(item => this.dateSame(item, date))) { + style.backgroundColor = this.color + } + if (this.mode === 'single') { + if (date === this.selected[0]) { + // ���������������nvue������������������������������������������������������������������������������ + style.borderTopLeftRadius = '3px' + style.borderBottomLeftRadius = '3px' + style.borderTopRightRadius = '3px' + style.borderBottomRightRadius = '3px' + } + } else if (this.mode === 'range') { + if (this.selected.length >= 2) { + const len = this.selected.length - 1 + // ��������������������������������������������������� + if (this.dateSame(date, this.selected[0])) { + style.borderTopLeftRadius = '3px' + style.borderBottomLeftRadius = '3px' + } + // ������������������������������������������������������ + if (this.dateSame(date, this.selected[len])) { + style.borderTopRightRadius = '3px' + style.borderBottomRightRadius = '3px' + } + // ��������������������������������������������������������������������������������������������������������������������������������������� + if (dayjs(date).isAfter(dayjs(this.selected[0])) && dayjs(date).isBefore(dayjs(this + .selected[len]))) { + style.backgroundColor = uni.$u.colorGradient(this.color, '#ffffff', 100)[90] + // ������������������������������������������������������������������������mark������������ + style.opacity = 0.7 + } + } else if (this.selected.length === 1) { + // ������������������������������������DCloud���������iOS������������������������������������������bug + // ������������������������������nvue���iOS���uni-app���bug��������������������������� + style.borderTopLeftRadius = '3px' + style.borderBottomLeftRadius = '3px' + } + } else { + if (this.selected.some(item => this.dateSame(item, date))) { + style.borderTopLeftRadius = '3px' + style.borderBottomLeftRadius = '3px' + style.borderTopRightRadius = '3px' + style.borderBottomRightRadius = '3px' + } + } + return style + } + }, + // ��������������������������� + textStyle() { + return (item) => { + const date = dayjs(item.date).format("YYYY-MM-DD"), + style = {} + // ������������������������������������������ + if (this.selected.some(item => this.dateSame(item, date))) { + style.color = '#ffffff' + } + if (this.mode === 'range') { + const len = this.selected.length - 1 + // ��������������������������������������������������������������������������������������������������������������� + if (dayjs(date).isAfter(dayjs(this.selected[0])) && dayjs(date).isBefore(dayjs(this + .selected[len]))) { + style.color = this.color + } + } + return style + } + }, + // ��������������������������� + getBottomInfo() { + return (index1, index2, item) => { + const date = dayjs(item.date).format("YYYY-MM-DD") + const bottomInfo = item.bottomInfo + // ������������������������������������������������������������0��� + if (this.mode === 'range' && this.selected.length > 0) { + if (this.selected.length === 1) { + // ������������������������������������������������������������������������������������������������������������������ + if (this.dateSame(date, this.selected[0])) return this.startText + else return bottomInfo + } else { + const len = this.selected.length - 1 + // ������������������������������2��������������������������������������������������������������� + if (this.dateSame(date, this.selected[0]) && this.dateSame(date, this.selected[1]) && + len === 1) { + // ���������������2������������������������������������������������������������������item��� + return `${this.startText}/${this.endText}` + } else if (this.dateSame(date, this.selected[0])) { + return this.startText + } else if (this.dateSame(date, this.selected[len])) { + return this.endText + } else { + return bottomInfo + } + } + } else { + return bottomInfo + } + } + } + }, + mounted() { + this.init() + }, + methods: { + init() { + // ��������������������� + this.$emit('monthSelected', this.selected) + this.$nextTick(() => { + // ������������������������������������������������������������������������������������������������������������������������������������ + // ������nvue������$nextTick���������100%��������� + uni.$u.sleep(10).then(() => { + this.getWrapperWidth() + this.getMonthRect() + }) + }) + }, + // ������������������������������ + dateSame(date1, date2) { + return dayjs(date1).isSame(dayjs(date2)) + }, + // ������������������������������������������nvue���������������������������������������css������������������item��������� + getWrapperWidth() { + // #ifdef APP-NVUE + dom.getComponentRect(this.$refs['u-calendar-month-wrapper'], res => { + this.width = res.size.width + }) + // #endif + // #ifndef APP-NVUE + this.$uGetRect('.u-calendar-month-wrapper').then(size => { + this.width = size.width + }) + // #endif + }, + getMonthRect() { + // ������������������������������������������������������scroll-view��������������������������������������������������������� + const promiseAllArr = this.months.map((item, index) => this.getMonthRectByPromise( + `u-calendar-month-${index}`)) + // ��������������� + Promise.all(promiseAllArr).then( + sizes => { + let height = 1 + const topArr = [] + for (let i = 0; i < this.months.length; i++) { + // ���������months���������������scroll-view��������������������������������������������������� + topArr[i] = height + height += sizes[i].height + } + // ������������������������������this.months[i].top���������(������������)���������������������month���top������������������������������������������ + this.$emit('updateMonthTop', topArr) + }) + }, + // ��������������������������������� + getMonthRectByPromise(el) { + // #ifndef APP-NVUE + // $uGetRect���uView���������������������������������������������������������https://www.uviewui.com/js/getRect.html + // ���������������������this.$uGetRect���������������uni.$u.getRect������������������������������������ + return new Promise(resolve => { + this.$uGetRect(`.${el}`).then(size => { + resolve(size) + }) + }) + // #endif + + // #ifdef APP-NVUE + // nvue������������dom������������������������ + // ������������promise���������������������������������������then������ + return new Promise(resolve => { + dom.getComponentRect(this.$refs[el][0], res => { + resolve(res.size) + }) + }) + // #endif + }, + // ��������������������� + clickHandler(index1, index2, item) { + if (this.readonly) { + return; + } + this.item = item + const date = dayjs(item.date).format("YYYY-MM-DD") + if (item.disabled) return + // ��������������������������������������������������� + let selected = uni.$u.deepClone(this.selected) + if (this.mode === 'single') { + // ��������������������������������������������������������������� + selected = [date] + } else if (this.mode === 'multiple') { + if (selected.some(item => this.dateSame(item, date))) { + // ��������������������������������������������������������������������������������������������� + const itemIndex = selected.findIndex(item => item === date) + selected.splice(itemIndex, 1) + } else { + // ������������������������������������������������������������������������������������������������������������ + if (selected.length < this.maxCount) selected.push(date) + } + } else { + // ������������������ + if (selected.length === 0 || selected.length >= 2) { + // ������������������0������������2��������������������������������������������������������� + selected = [date] + } else if (selected.length === 1) { + // ��������������������������������� + const existsDate = selected[0] + // ������������������������������������������������������������������������������������������������ + if (dayjs(date).isBefore(existsDate)) { + selected = [date] + } else if (dayjs(date).isAfter(existsDate)) { + // ������������������������������������������������������������������������������������������ + if(dayjs(dayjs(date).subtract(this.maxRange, 'day')).isAfter(dayjs(selected[0])) && this.showRangePrompt) { + if(this.rangePrompt) { + uni.$u.toast(this.rangePrompt) + } else { + uni.$u.toast(`������������������������ ${this.maxRange} ���`) + } + return + } + // ������������������������������������������������������������������������ + selected.push(date) + const startDate = selected[0] + const endDate = selected[1] + const arr = [] + let i = 0 + do { + // ��������������������������������������������������������� + arr.push(dayjs(startDate).add(i, 'day').format("YYYY-MM-DD")) + i++ + // ��������������������������������������������������������������� + } while (dayjs(startDate).add(i, 'day').isBefore(dayjs(endDate))) + // ������������������������������������computed������������������������������arr������������������������������������������������������������������������ + arr.push(endDate) + selected = arr + } else { + // ��������������������������������������������������������������������������������������������������������������������� + if (selected[0] === date && !this.allowSameDay) return + selected.push(date) + } + } + } + this.setSelected(selected) + }, + // ������������������ + setDefaultDate() { + if (!this.defaultDate) { + // ��������������������������������������������������������������������������������� + const selected = [dayjs().format("YYYY-MM-DD")] + return this.setSelected(selected, false) + } + let defaultDate = [] + const minDate = this.minDate || dayjs().format("YYYY-MM-DD") + const maxDate = this.maxDate || dayjs(minDate).add(this.maxMonth - 1, 'month').format("YYYY-MM-DD") + if (this.mode === 'single') { + // ���������������������������������������������Date��������� + if (!uni.$u.test.array(this.defaultDate)) { + defaultDate = [dayjs(this.defaultDate).format("YYYY-MM-DD")] + } else { + defaultDate = [this.defaultDate[0]] + } + } else { + // ��������������������������������� + if (!uni.$u.test.array(this.defaultDate)) return + defaultDate = this.defaultDate + } + // ��������������������������������������������������������������������������������������������� + defaultDate = defaultDate.filter(item => { + return dayjs(item).isAfter(dayjs(minDate).subtract(1, 'day')) && dayjs(item).isBefore(dayjs( + maxDate).add(1, 'day')) + }) + this.setSelected(defaultDate, false) + }, + setSelected(selected, event = true) { + this.selected = selected + event && this.$emit('monthSelected', this.selected) + } + } + } +</script> + +<style lang="scss" scoped> + @import "../../libs/css/components.scss"; + + .u-calendar-month-wrapper { + margin-top: 4px; + } + + .u-calendar-month { + + &__title { + font-size: 14px; + line-height: 42px; + height: 42px; + color: $u-main-color; + text-align: center; + font-weight: bold; + } + + &__days { + position: relative; + @include flex; + flex-wrap: wrap; + + &__month-mark-wrapper { + position: absolute; + top: 0; + bottom: 0; + left: 0; + right: 0; + @include flex; + justify-content: center; + align-items: center; + + &__text { + font-size: 155px; + color: rgba(231, 232, 234, 0.83); + } + } + + &__day { + @include flex; + padding: 2px; + /* #ifndef APP-NVUE */ + // vue���������css���������������������������������������������������������js������������������������������������������������������ + width: calc(100% / 7); + box-sizing: border-box; + /* #endif */ + + &__select { + flex: 1; + @include flex; + align-items: center; + justify-content: center; + position: relative; + + &__dot { + width: 7px; + height: 7px; + border-radius: 100px; + background-color: $u-error; + position: absolute; + top: 12px; + right: 7px; + } + + &__buttom-info { + color: $u-content-color; + text-align: center; + position: absolute; + bottom: 5px; + font-size: 10px; + text-align: center; + left: 0; + right: 0; + + &--selected { + color: #ffffff; + } + + &--disabled { + color: #cacbcd; + } + } + + &__info { + text-align: center; + font-size: 16px; + + &--selected { + color: #ffffff; + } + + &--disabled { + color: #cacbcd; + } + } + + &--selected { + background-color: $u-primary; + @include flex; + justify-content: center; + align-items: center; + flex: 1; + border-radius: 3px; + } + + &--range-selected { + opacity: 0.3; + border-radius: 0; + } + + &--range-start-selected { + border-top-right-radius: 0; + border-bottom-right-radius: 0; + } + + &--range-end-selected { + border-top-left-radius: 0; + border-bottom-left-radius: 0; + } + } + } + } + } +</style> -- Gitblit v1.8.0