element-plus/packages/calendar/src/date-table.vue

205 lines
5.0 KiB
Vue
Raw Normal View History

<template>
<table
:class="{
'el-calendar-table': true,
'is-range': isInRange
}"
cellspacing="0"
cellpadding="0"
>
<thead v-if="!hideHeader">
<th v-for="day in weekDays" :key="day">{{ day }}</th>
</thead>
<tbody>
<tr
v-for="(row, index) in rows"
:key="index"
:class="{
'el-calendar-table__row': true,
'el-calendar-table__row--hide-border': index === 0 && hideHeader
}"
>
<td
v-for="(cell, key) in row"
:key="key"
:class="getCellClass(cell)"
@click="pickDay(cell)"
>
<div class="el-calendar-day">
<slot
name="dateCell"
:data="getSlotData(cell)"
>
<span>{{ cell.text }}</span>
</slot>
</div>
</td>
</tr>
</tbody>
</table>
</template>
<script lang="ts">
import {
computed,
defineComponent,
ref,
PropType,
} from 'vue'
import dayjs, { Dayjs } from 'dayjs'
import localeData from 'dayjs/plugin/localeData'
Feat/datepicker && datetimepicker (#326) * chore: update * chore: update * chore: update * chore: update * chore: update * chore: update * chore: update * chore: update * chore: update * chore: update * chore: update * chore: update * chore: update * chore: update * chore: update * chore: update * chore: update * chore: update * chore: update * chore: update * chore: update * chore: update * chore: update * chore: update * chore: update * chore: update * chore: update * chore: update * chore: update * chore: update * chore: update * chore: update * Feat/form (#342) * feat(form): add form component fix #125 * test(form): add test code * docs(form): add form doc * feat: add uitls merge * fix(form): fix style * test(form): add form test code * refactor(form): review changes * test(form): use idiomatic vue-test-util methods * feat(core): bump vue version * feat(form): rewrite label wrap * feat(form): fix tons of bugs * fix(form): reuse ts extension * refactor(form): move out label width computation * fix(form): fix tons of bugs * fix(form): test Co-authored-by: 286506460 <286506460@qq.com> * Feat/select (#381) * fix: resove conflict * feat: select basic usage * feat: select basic usage * feat: select feature create item * fix: fix option data insert * refactor: select * fix: fix parse error * feat: select test * fix: select add popper * fix: update select option * fix: add select dependency * fix: add index.ts file * fix(select): clean up * fix(select): some refactor * fix(select): some update * fix(select): fix all test cases Co-authored-by: helen <yinhelen.hlj@qq.com> Co-authored-by: Herrington Darkholme <2883231+HerringtonDarkholme@users.noreply.github.com> Co-authored-by: 286506460 <286506460@qq.com> Co-authored-by: helen <yinhelen.hlj@qq.com>
2020-10-03 20:13:19 +08:00
import { rangeArr } from '@element-plus/time-picker/src/common/date-utils'
dayjs.extend(localeData)
export const getPrevMonthLastDays = (date: Dayjs, amount) => {
const lastDay = date.subtract(1, 'month').endOf('month').date()
return rangeArr(amount).map((_, index) => lastDay - (amount - index - 1))
}
export const getMonthDays = (date: Dayjs) => {
const days = date.daysInMonth()
return rangeArr(days).map((_, index) => index + 1)
}
export default defineComponent({
props: {
selectedDay: {
type: Dayjs,
},
range: {
type: Array as PropType<Array<Dayjs>>,
},
date: {
type: Dayjs,
},
hideHeader: {
type: Boolean,
},
},
emits: ['pick'],
setup(props, ctx) {
const WEEK_DAYS = ref(dayjs().localeData().weekdaysShort())
const now = dayjs()
// todo better way to get Day.js locale object
const firstDayOfWeek = (now as any).$locale().weekStart || 0
const toNestedArr = days => {
return rangeArr(days.length / 7).map((_, index) => {
const start = index * 7
return days.slice(start, start + 7)
})
}
const getFormateDate = (day, type): Dayjs => {
let result
if (type === 'prev') {
result = props.date.startOf('month').subtract(1, 'month').date(day)
} else if (type === 'next') {
result = props.date.startOf('month').add(1, 'month').date(day)
} else {
result = props.date.date(day)
}
return result
}
const getCellClass = ({ text, type }) => {
const classes = [type]
if (type === 'current') {
const date_ = getFormateDate(text, type)
if (date_.isSame(props.selectedDay, 'day')) {
classes.push('is-selected')
}
if (date_.isSame(now, 'day')) {
classes.push('is-today')
}
}
return classes
}
const pickDay = ({ text, type }) => {
const date = getFormateDate(text, type)
ctx.emit('pick', date)
}
const getSlotData = ({ text, type }) => {
const day = getFormateDate(text, type)
return {
isSelected: day.isSame(props.selectedDay),
type: `${type}-month`,
day: day.format('YYYY-MM-DD'),
date: day.toDate(),
}
}
const isInRange = computed(() => {
return props.range && props.range.length
})
const rows = computed(() => {
let days = []
if (isInRange.value) {
const [start, end] = props.range
const currentMonthRange = rangeArr(
end.date() - start.date() + 1,
).map((_, index) => ({
text: start.date() + index,
type: 'current',
}))
let remaining = currentMonthRange.length % 7
remaining = remaining === 0 ? 0 : 7 - remaining
const nextMonthRange = rangeArr(remaining).map((_, index) => ({
text: index + 1,
type: 'next',
}))
days = currentMonthRange.concat(nextMonthRange)
} else {
const firstDay = props.date.startOf('month').day() || 7
const prevMonthDays = getPrevMonthLastDays(
props.date,
firstDay - firstDayOfWeek,
).map(day => ({
text: day,
type: 'prev',
}))
const currentMonthDays = getMonthDays(props.date).map(day => ({
text: day,
type: 'current',
}))
days = [...prevMonthDays, ...currentMonthDays]
const nextMonthDays = rangeArr(42 - days.length).map((_, index) => ({
text: index + 1,
type: 'next',
}))
days = days.concat(nextMonthDays)
}
return toNestedArr(days)
})
const weekDays = computed(() => {
const start = firstDayOfWeek
if (start === 0) {
return WEEK_DAYS.value
} else {
return WEEK_DAYS.value
.slice(start)
.concat(WEEK_DAYS.value.slice(0, start))
}
})
return {
isInRange,
weekDays,
rows,
getCellClass,
pickDay,
getSlotData,
}
},
})
</script>