123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369 |
- import { Button, Calendar, Icon, Image, Popup, Tag } from 'vant'
- import 'vant/es/calendar/style'
- import { defineComponent } from 'vue'
- import dayjs from 'dayjs'
- import styles from './index.module.less'
- import IconArrow from '@/common/images/icon_arrow.png'
- import IconClock from '@/common/images/icon_clock.png'
- import { ElButton, ElDialog, ElMessage } from 'element-plus'
- export default defineComponent({
- name: 'calendar',
- props: {
- calendarDate: {
- type: Date,
- default: () => new Date()
- },
- // 选中的数据
- selectList: {
- type: Array,
- default: []
- },
- // 接口数据
- list: {
- type: Object,
- default: {}
- },
- /**
- * 每天选择课程最大数
- */
- maxDays: {
- type: [Number, String],
- default: 0
- },
- /**
- * 点击并选中任意日期时触发
- */
- onSelect: {
- type: Function,
- default: (date: Date) => {}
- },
- /**
- * 上一月,不能小于当月
- */
- prevMonth: {
- type: Function,
- default: (date: Date) => {}
- },
- /**
- * 下一月,暂无限制
- */
- nextMonth: {
- type: Function,
- default: (date: Date) => {}
- },
- /**
- * 日期选择结束时触发
- */
- selectDay: {
- type: Function,
- default: (obj: any) => {}
- },
- isSkipHolidays: {
- // 是否跳过节假日
- type: Boolean,
- default: false
- }
- },
- data() {
- return {
- minDate: new Date(),
- maxDate: new Date(),
- currentDate: new Date(), // 当前日历日期
- subtitle: '',
- show: false,
- dayList: [],
- selectDays: [] as any
- }
- },
- computed: {
- arrowStatus() {
- // 上月箭头状态
- return !dayjs().isBefore(dayjs(this.currentDate), 'month')
- },
- selectDayTitle() {
- // 选中日期标题
- return dayjs(this.currentDate).format('YYYY-MM-DD')
- },
- isPrevDay() {
- // 是否可以点击上一天
- return dayjs(this.currentDate)
- .subtract(1, 'day')
- .isBefore(dayjs(this.minDate), 'day')
- },
- isNextDay() {
- // 是否可以点击下一天
- return dayjs(this.currentDate)
- .add(1, 'day')
- .isAfter(dayjs(this.maxDate), 'day')
- }
- },
- mounted() {
- // 初始化标题和最大显示日期
- this.subtitle = dayjs().format('YYYY年MM月')
- this.maxDate = dayjs().endOf('month').toDate()
- this.minDate = dayjs().add(1, 'day').toDate()
- // 初始化日历
- // console.log(this.list, 323, this.maxDays)
- },
- methods: {
- formatter(date: any) {
- const dateStr = dayjs(date.date).format('YYYY-MM-DD')
- const dateObj = this.list[dateStr]
- // 判断是否有课程 并且 时间在当前时间之后
- if (dateObj && dayjs().isBefore(dayjs(date.date))) {
- if (
- dateObj &&
- (dateObj.fullCourse ||
- !dateObj?.courseTime ||
- dateObj?.courseTime?.length <= 0)
- ) {
- date.bottomInfo = '满'
- date.className = 'full'
- date.type = 'disabled'
- }
- } else {
- date.type = 'disabled'
- }
- if (dateObj && this.isSkipHolidays && dateObj.holiday) {
- // date.bottomInfo = '节假日'
- date.type = 'disabled'
- }
- date.type = date.type === 'selected' ? '' : date.type
- return date
- },
- onPrevMonth() {
- // 上一月
- if (this.arrowStatus) return
- const tempDate = dayjs(this.currentDate).subtract(1, 'month')
- this._monthChange(tempDate)
- this.prevMonth && this.prevMonth(this.minDate)
- },
- onNextMonth() {
- // 下一月
- const tempDate = dayjs(this.currentDate).add(1, 'month')
- this._monthChange(tempDate)
- this.nextMonth && this.nextMonth(this.minDate)
- },
- _monthChange(date: any) {
- // 月份改变
- // 需要判断是否是当月,需要单独处理最小时间
- const currentMinDate = dayjs().add(1, 'day').toDate()
- const monthMinDate = date.startOf('month').toDate()
- this.minDate = dayjs(currentMinDate).isAfter(monthMinDate)
- ? currentMinDate
- : monthMinDate
- // this.minDate = date.startOf('month').toDate()
- this.maxDate = date.endOf('month').toDate()
- this.currentDate = date.toDate()
- this.$emit('update:calendarDate', date.toDate())
- this.subtitle = date.format('YYYY年MM月')
- },
- onSelectDay(item: any) {
- // 选择某个时间段
- const index = this.selectDays.findIndex((days: any) => {
- return days.startTime === item.startTime
- })
- if (this.selectDays.length < this.maxDays || index !== -1) {
- const index = this.selectDays.findIndex(
- (days: any) => days.startTime === item.startTime
- )
- item.checked = !item.checked
- if (index === -1) {
- this.selectDays.push({ ...item })
- } else {
- this.selectDays.splice(index, 1)
- }
- } else {
- ElMessage.info('最多选择' + this.maxDays + '个时间段')
- }
- },
- onPrevDay() {
- // 获取上一天的数据
- const tempDate = dayjs(this.currentDate).subtract(1, 'day')
- this._dayChange(tempDate.toDate())
- },
- onNextDay() {
- // 获取下一天的数据
- const tempDate = dayjs(this.currentDate).add(1, 'day')
- this._dayChange(tempDate.toDate())
- },
- onDateSelect(date: any) {
- // 选择日历上某一个日期
- this.selectDays = [...this.selectList] // 初始化用户选中的值
- this._dayChange(date)
- this.onSelect && this.onSelect(date)
- },
- _dayChange(date: Date) {
- const dateStr = dayjs(date).format('YYYY-MM-DD')
- let dataList = (this.list[dateStr] && this.list[dateStr].courseTime) || []
- dataList.forEach((item: any) => {
- item.start = dayjs(item.startTime).format('HH:mm')
- item.end = dayjs(item.endTime).format('HH:mm')
- const isExist = this.selectDays?.some(
- (course: any) => course.startTime === item.startTime
- )
- item.checked = isExist
- })
- this.dayList = dataList
- this.currentDate = date // 更新当前日期
- this.$emit('update:calendarDate', date)
- this.show = true
- }
- },
- render() {
- return (
- <>
- <Calendar
- class={styles.calendar}
- showTitle={false}
- poppable={false}
- showConfirm={false}
- showMark={false}
- firstDayOfWeek={1}
- rowHeight={56}
- minDate={this.minDate}
- maxDate={this.maxDate}
- color="var(--van-primary)"
- formatter={this.formatter}
- onSelect={this.onDateSelect}
- v-slots={{
- subtitle: () => (
- <div class={styles.subtitle}>
- <Icon
- name={IconArrow}
- size={22}
- class={this.arrowStatus && styles.disabled}
- onClick={this.onPrevMonth}
- />
- <span>{this.subtitle}</span>
- <Icon
- name={IconArrow}
- size={22}
- class={styles.right}
- onClick={this.onNextMonth}
- />
- </div>
- )
- // 'bottom-info': (date: any) => <span>{date.type}</span>
- }}
- />
- <ElDialog
- modelValue={this.show}
- onUpdate:modelValue={e => (this.show = e)}
- class={styles.calenderPopup}
- >
- <div class={styles.popup}>
- <div class={styles.title}>
- <span>{this.selectDayTitle}</span>
- </div>
- <div class={styles.container}>
- {this.dayList.map((item: any) => (
- <div>
- <Tag
- round
- class={[styles.tag, item.checked ? styles.active : '']}
- size="large"
- plain
- onClick={() => this.onSelectDay(item)}
- >
- {item.start}~{item.end}
- </Tag>
- </div>
- ))}
- {this.dayList.length <= 0 && (
- <div class={styles.noDay}>
- <Image src={IconClock} class={styles.clock} fit="cover" />
- <span>今日已约满</span>
- </div>
- )}
- </div>
- <div class={[styles.dayBtn, 'flex']}>
- <ElButton
- round
- plain
- style={{ width: '33.33%', marginRight: '10px' }}
- onClick={() => {
- this.show = false
- this.selectDays = []
- }}
- >
- 取消
- </ElButton>
- <ElButton
- type="primary"
- round
- disabled={!(this.selectDays.length > 0)}
- onClick={() => {
- this.selectDay && this.selectDay(this.selectDays)
- this.show = false
- }}
- >
- 确认
- </ElButton>
- </div>
- </div>
- </ElDialog>
- {/* <Popup show={this.show} class={styles.calenderPopup}>
- <div class={styles.popup}>
- <div class={styles.title}>
- <span>{this.selectDayTitle}</span>
- </div>
- <div class={styles.container}>
- {this.dayList.map((item: any) => (
- <div>
- <Tag
- round
- class={[styles.tag, item.checked ? styles.active : '']}
- size="large"
- plain
- onClick={() => this.onSelectDay(item)}
- >
- {item.start}~{item.end}
- </Tag>
- </div>
- ))}
- {this.dayList.length <= 0 && (
- <div class={styles.noDay}>
- <Image src={IconClock} class={styles.clock} fit="cover" />
- <span>今日已约满</span>
- </div>
- )}
- </div>
- <div class={styles.dayBtn}>
- <Button
- round
- plain
- style={{ width: '33.33%', marginRight: '10px' }}
- onClick={() => {
- this.show = false
- this.selectDays = []
- }}
- >
- 取消
- </Button>
- <Button
- type="primary"
- block
- round
- disabled={!(this.selectDays.length > 0)}
- onClick={() => {
- this.selectDay && this.selectDay(this.selectDays)
- this.show = false
- }}
- >
- 确认
- </Button>
- </div>
- </div>
- </Popup> */}
- </>
- )
- }
- })
|