feat:日历视图支持点击事件 (#3279)

This commit is contained in:
liukun 2025-04-11 11:36:09 +08:00 committed by GitHub
parent bec9bbdf77
commit 1eb420845f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
18 changed files with 120 additions and 19 deletions

View File

@ -252,6 +252,19 @@ export default {
pcDemo: 'multi-select',
mfDemo: 'multi-select'
},
{
name: 'date-click',
desc: {
'zh-CN': '日期点击事件,回调参数为当前点击日期和日程事件',
'en-US': 'Date click event, The callback parameters are the current click date and schedule event'
},
mode: ['pc', 'mobile-first'],
pcDemo: 'calendar-event',
mfDemo: 'calendar-event',
meta: {
stable: '3.23.0'
}
},
{
name: 'week-change',
desc: {

View File

@ -3,6 +3,7 @@
:events="eventslist"
:year="2023"
:month="5"
@date-click="dateClick"
@prev-week-click="prevWeekClick"
@next-week-click="nextWeekClick"
@week-change="weekChange"
@ -25,6 +26,9 @@ export default {
}
},
methods: {
dateClick(date, events) {
TinyModal.message({ message: `点击日期: ${date};日程事件:${JSON.stringify(events)}`, status: 'info' })
},
prevWeekClick(date) {
TinyModal.message({ message: `上一周按钮点击事件: ${date[0].value}`, status: 'info' })
},

View File

@ -3,6 +3,7 @@
:events="eventslist"
:year="2023"
:month="5"
@date-click="dateClick"
@prev-week-click="prevWeekClick"
@next-week-click="nextWeekClick"
@week-change="weekChange"
@ -19,6 +20,10 @@ import { TinyCalendarView, TinyModal } from '@opentiny/vue'
const eventslist = ref([])
const dateClick = (date, events) => {
TinyModal.message({ message: `点击日期: ${date};日程事件:${JSON.stringify(events)}`, status: 'info' })
}
const prevWeekClick = (date) => {
TinyModal.message({ message: `上一周按钮点击事件: ${date[0].value}`, status: 'info' })
}

View File

@ -11,6 +11,9 @@ test('事件', async ({ page }) => {
const rightSvg = page.locator('.header-right > .tiny-svg')
const mode = page.locator('label').nth(2)
const modalVal = page.getByText('模式切换事件schedule')
const date = page.getByText('30周一')
const dateVal = page.locator('div').filter({ hasText: '点击日期: 2022-5-30日程事件[]' }).nth(1)
await timeBtn.click()
await page.waitForTimeout(100)
await leftYear.click()
@ -27,4 +30,7 @@ test('事件', async ({ page }) => {
await mode.click()
await page.waitForTimeout(100)
await expect(modalVal).toBeVisible()
await date.click()
await page.waitForTimeout(100)
await expect(dateVal).toBeVisible()
})

View File

@ -3,6 +3,7 @@
:events="eventslist"
:year="2023"
:month="5"
@date-click="dateClick"
@prev-week-click="prevWeekClick"
@next-week-click="nextWeekClick"
@week-change="weekChange"
@ -26,6 +27,9 @@ export default {
}
},
methods: {
dateClick(date, events) {
TinyModal.message({ message: `点击日期: ${date};日程事件:${JSON.stringify(events)}`, status: 'info' })
},
prevWeekClick(date) {
TinyModal.message({ message: `上一周按钮点击事件: ${date[0].value}`, status: 'info' })
},

View File

@ -167,6 +167,7 @@ export default {
desc: {
'zh-CN':
'<p>日历抛出的事件有以下这些:</p>\n' +
'<p>date-click日期点击事件</p>\n' +
'<p>new-schedule新增日程按钮点击事件</p>\n' +
'<p>selected-date-change选中日期改变事件</p>\n' +
'<p>prev-week-click上一周按钮点击事件</p>\n' +
@ -177,6 +178,7 @@ export default {
'<p>mode-change模式切换事件</p>',
'en-US':
'<p>Calendar throws the following events:</p>\n' +
'<p>date-click日期点击事件: Date click event</p>\n' +
'<p>new-schedule: Add a schedule button click event</p>\n' +
'<p>selected-date-change: selected date change event</p>\n' +
'<p>prev-week-click: button click event of the last week</p>\n' +
@ -371,11 +373,12 @@ export default {
value: true
},
description:
'日历抛出的事件包括:new-schedule、selected-date-change、prev-week-click、next-week-click、week-change、year-change、month-change、mode-change。',
'日历抛出的事件包括:date-click、new-schedule、selected-date-change、prev-week-click、next-week-click、week-change、year-change、month-change、mode-change。',
cloud: {
value: false
},
apis: [
'date-click',
'new-schedule',
'selected-date-change',
'prev-week-click',

View File

@ -307,8 +307,19 @@ function splitEvent(props, event) {
return result
}
export const computedSelectDay = ({ state }) =>
(day) => {
if (!day || !day.value || day.disabled) return false
if (state.multiSelect) {
return state.selectedDates.includes(day.value)
} else{
return state.selectedDate === day.value
}
}
export const selectDay =
({ state, emit }) =>
({ props, state, emit, api }) =>
(day, i) => {
if (!day || !day.value || day.disabled) return
@ -323,9 +334,11 @@ export const selectDay =
state.selectedDates.push(date)
}
const dateEvent = dealEvents(props, api, state.selectedDates)
emit('update:modelValue', state.selectedDates)
emit('selected-date-change', state.selectedDates)
emit('date-click', date)
emit('date-click', state.selectedDates, dateEvent)
} else {
if (day.isNext) {
const { year, month } = nextMonth(state.activeYear, state.activeMonth)
@ -342,12 +355,26 @@ export const selectDay =
state.selectedDate =
day.value.toString().length > 2 ? day.value : `${state.activeYear}-${state.activeMonth}-${day.value}`
state.showSelectedDateEvents = true
const dateEvent = dealEvents(props, api, [state.selectedDate])
emit('update:modelValue', state.selectedDate)
emit('date-click', state.selectedDate)
emit('date-click', state.selectedDate, dateEvent[0])
}
}
const dealEvents = (props, api, date) => {
return date.map(item => {
let event = api.getEventByTime(item, props._constants.DAY_START_TIME, props._constants.DAY_END_TIME)
event.forEach(e => {
delete e.dayArr;
delete e.dayNumber;
});
return event
})
}
export const getEventByMonth =
({ state }) =>
(year, month) => {

View File

@ -1,6 +1,7 @@
import {
computedCalendar,
handleEvents,
computedSelectDay,
selectDay,
getEventByTime,
isToday,
@ -47,6 +48,7 @@ export const api = [
'isToday',
'dateIsToday',
'getEventByTime',
'computedSelectDay',
'selectDay',
'toToday',
'getPrevWeek',
@ -270,7 +272,8 @@ const initApi = ({ vm, api, state, t, props, emit, nextTick }) => {
computeCascaderOptions: computeCascaderOptions(t),
isToday: isToday(state),
dateIsToday: dateIsToday(),
selectDay: selectDay({ state, emit }),
selectDay: selectDay({ props, state, emit, api }),
computedSelectDay: computedSelectDay({ state }),
getEventByTime: getEventByTime({ props, state }),
toToday: toToday({ state, api, nextTick }),
getAllWednesdaysInYear: getAllWednesdaysInYear({ state }),

View File

@ -62,6 +62,7 @@
>li{
@apply leading-10;
@apply cursor-pointer;
>span{
@apply text-sm;
@ -351,6 +352,7 @@
>li{
@apply leading-10;
@apply cursor-pointer;
.date{
@apply relative;
@ -358,7 +360,11 @@
@apply text-base;
@apply text-color-text-primary;
&.is-today{
&.is-today {
@apply text-color-brand;
}
&.current {
@apply text-color-brand;
}
}
@ -407,7 +413,11 @@
.week-day{
@apply text-sm;
@apply text-color-text-placeholder;
&.is-today{
&.is-today {
@apply text-color-brand;
}
&.current {
@apply text-color-brand;
}
}

View File

@ -159,12 +159,12 @@
// x 和 y 滚动条交汇处
::-webkit-scrollbar-corner {
background: var(--tv-color-bg-scrollbar-track);
background: transparent;
}
// 滚动条轨道
::-webkit-scrollbar-track {
background: var(--tv-color-bg-scrollbar-track);
background: transparent;
}
// 滚动滑块

View File

@ -360,6 +360,7 @@
> li {
line-height: 40px;
cursor: pointer;
.date {
position: relative;
@ -370,6 +371,10 @@
&.is-today {
color: var(--tv-CalendarView-week-date-today-text-color);
}
&.current {
color: var(--tv-CalendarView-week-date-today-text-color);
}
}
.mark {
@ -418,7 +423,11 @@
color: #8d959e;
&.is-today {
color: #1890ff;
color: var(--tv-CalendarView-week-date-today-text-color);
}
&.current {
color: var(--tv-CalendarView-week-date-today-text-color);
}
}
}

View File

@ -24,6 +24,7 @@
}
.month-table() {
width: 100%;
font-size: var(--tv-MonthTable-font-size);
margin: -1px;
border-collapse: collapse;

View File

@ -0,0 +1,15 @@
import { mountPcMode } from '@opentiny-internal/vue-test-utils'
import { describe, expect, test } from 'vitest'
import CalendarView from '@opentiny/vue-calendar-view'
import { nextTick } from 'vue'
describe('PC Mode', () => {
const mount = mountPcMode
test('value', async () => {
const wrapper = mount(() => <CalendarView year={2023} month={5}></CalendarView>)
await nextTick()
expect(wrapper.find('.tiny-calendar-view').exists()).toBe(true)
})
})

View File

@ -159,7 +159,8 @@
data-tag="tiny-calendar-view-weekitem"
v-for="(date, index) in state.weekDates"
:key="date.value"
class="leading-10"
class="leading-10 cursor-pointer"
@click="selectDay(date)"
>
<slot
name="header"
@ -170,7 +171,7 @@
>
<span
class="relative mr-2.5 text-base"
:class="[dateIsToday(date.value) ? 'text-color-brand' : 'text-color-text-primary']"
:class="[dateIsToday(date.value) || computedSelectDay(date) ? 'text-color-brand' : 'text-color-text-primary']"
>
<span>{{ date.value.split('-')[2] }}</span>
<span
@ -181,7 +182,7 @@
</span>
<span
class="text-sm"
:class="[dateIsToday(date.value) ? 'text-color-brand' : 'text-color-text-placeholder']"
:class="[dateIsToday(date.value) || computedSelectDay(date) ? 'text-color-brand' : 'text-color-text-placeholder']"
>{{ dateIsToday(date.value) ? t('ui.datepicker.today') : t(`ui.calendarView.weekDays.${index}`) }}</span
>
</slot>

View File

@ -107,7 +107,7 @@
<icon-chevron-left></icon-chevron-left>
</div>
<ul class="header-main">
<li v-for="(date, index) in state.weekDates" :key="date.value">
<li v-for="(date, index) in state.weekDates" :key="date.value" @click="selectDay(date)">
<slot
name="header"
:slot-scope="{
@ -115,7 +115,7 @@
weekDay: t(`ui.calendarView.weekDays.${index}`)
}"
>
<span class="date" :class="dateIsToday(date.value) && 'is-today'">
<span class="date" :class="[dateIsToday(date.value) && 'is-today', { current: computedSelectDay(date) }]">
<span>{{ date.value.split('-')[2] }}</span>
<span
v-if="isShowMark(date.value)"
@ -123,7 +123,7 @@
:class="[date.value.split('-')[2] > 9 ? 'is-two-digit' : '', markColor ? `mark-${markColor}` : '']"
></span>
</span>
<span class="week-day" :class="dateIsToday(date.value) && 'is-today'">{{
<span class="week-day" :class="[dateIsToday(date.value) && 'is-today', { current: computedSelectDay(date) }]">{{
dateIsToday(date.value) ? t('ui.datepicker.today') : t(`ui.calendarView.weekDays.${index}`)
}}</span>
</slot>

View File

@ -15,7 +15,7 @@
class="tiny-picker-panel tiny-date-picker tiny-popper"
:class="[
{
'has-sidebar': slots.sidebar || state.shortcuts,
'has-sidebar': slots.sidebar || state.shortcuts?.length,
'has-time': state.showTime
},
state.popperClass

View File

@ -15,7 +15,7 @@
class="tiny-picker-panel tiny-date-range-picker tiny-popper"
:class="[
{
'has-sidebar': slots.sidebar || state.shortcuts,
'has-sidebar': slots.sidebar || state.shortcuts?.length,
'has-time': state.showTime
},
state.popperClass

View File

@ -4,7 +4,7 @@
class="tiny-picker-panel tiny-date-range-picker tiny-popper"
:class="[
{
'has-sidebar': slots.sidebar || state.shortcuts
'has-sidebar': slots.sidebar || state.shortcuts?.length,
},
state.popperClass
]"