This commit is contained in:
2025-06-10 22:04:23 +08:00
parent c0b62dfa0f
commit df13a5b6c3
11 changed files with 652 additions and 516 deletions

View File

@@ -1,7 +1,7 @@
<template>
<div class="bg-white rounded-2xl shadow-soft p-6">
<div class="bg-gradient-to-br from-white to-gray-50 rounded-2xl shadow-soft p-6">
<!-- 月视图 -->
<div v-if="view === 'month'" class="month-view">
<div v-if="view === 'month'" class="month-view" data-aos="fade-up" data-aos-duration="500">
<div class="grid grid-cols-7 gap-1">
<div
v-for="day in ['日', '一', '二', '三', '四', '五', '六']"
@@ -20,8 +20,11 @@
@dragover.prevent="handleDragOver($event, day.date)"
@dragleave="handleDragLeave"
@drop="handleDropEvent($event, day.date)"
:class="{'bg-primary-50': selectedDate === day.date}"
class="calendar-cell dropzone rounded-xl border border-gray-100 p-3 cursor-pointer transition-all relative min-h-[120px]"
:class="{
'bg-primary-50': selectedDate === day.date,
'drag-over': isDragOverCell === day.date
}"
class="calendar-cell dropzone rounded-xl border border-gray-100 p-3 cursor-pointer transition-all relative min-h-[120px] hover:shadow-md"
>
<!-- 日期和工作状态 -->
<div class="flex justify-between items-start">
@@ -59,25 +62,28 @@
</div>
<!-- 事件展示 -->
<div v-if="hasEvent(day.date)" class="mt-2 text-xs truncate max-w-full">
{{ getFirstEventTitle(day.date) }}
</div>
<!-- 事件指示器 -->
<div v-if="hasEvent(day.date)" class="absolute bottom-3 right-3 flex">
<span
v-for="(color, index) in getEventColorsForDay(day.date)"
:key="index"
class="event-dot"
:style="{backgroundColor: color}"
></span>
<div v-if="hasEvent(day.date)" class="mt-2 text-xs max-w-full overflow-hidden">
<div
v-for="(event, idx) in getEventsForDate(day.date).slice(0, 2)"
:key="idx"
class="truncate mb-1 flex items-center"
>
<span
class="event-dot mr-1"
:style="{ backgroundColor: event.color }"
></span>
{{ event.title }}
</div>
<div v-if="getEventsForDate(day.date).length > 2" class="text-gray-500">
+{{ getEventsForDate(day.date).length - 2 }}个日程
</div>
</div>
</div>
</div>
</div>
<!-- 周视图 -->
<div v-else-if="view === 'week'" class="week-view">
<div v-else-if="view === 'week'" class="week-view" data-aos="fade-up" data-aos-duration="500">
<div class="flex mb-3 bg-gray-50 rounded-lg">
<div class="w-20"></div>
<div
@@ -85,7 +91,7 @@
:key="index"
@click="selectDate(day.format('YYYY-MM-DD'))"
:class="{'bg-primary-100': selectedDate === day.format('YYYY-MM-DD')}"
class="flex-1 text-center py-3 rounded-lg transition-colors cursor-pointer"
class="flex-1 text-center py-3 rounded-lg transition-colors cursor-pointer hover:bg-gray-100"
>
<p class="font-medium text-gray-700">{{ day.format('ddd') }}</p>
<p
@@ -120,7 +126,8 @@
@drop="handleDropEvent($event, day.format('YYYY-MM-DD'), (hour + 8) + ':00')"
:class="{
'bg-gray-50': index % 2 === 0,
'border-l border-gray-200': index > 0
'border-l border-gray-200': index > 0,
'drag-over': isDragOverCell === day.format('YYYY-MM-DD') + '-' + (hour + 8)
}"
class="flex-1 min-h-16 p-2 dropzone"
>
@@ -128,7 +135,7 @@
v-for="event in getEventsForDate(day.format('YYYY-MM-DD'), (hour + 8) + ':00')"
:key="event.id"
@click="showEventDetail(event)"
class="text-xs p-2 rounded-lg mb-1 truncate"
class="text-xs p-2 rounded-lg mb-1 truncate cursor-pointer hover:shadow-sm"
:style="{
backgroundColor: `${event.color}10`,
borderLeft: `3px solid ${event.color}`
@@ -142,7 +149,7 @@
</div>
<!-- 日视图 -->
<div v-else class="day-view">
<div v-else class="day-view" data-aos="fade-up" data-aos-duration="500">
<div
class="flex items-center justify-center py-3 mb-4 rounded-xl day-header"
@click="selectDate(currentDate)"
@@ -175,6 +182,9 @@
@dragover.prevent="handleDragOver($event, currentDay.format('YYYY-MM-DD'), (hour + 7) + ':00')"
@dragleave="handleDragLeave"
@drop="handleDropEvent($event, currentDay.format('YYYY-MM-DD'), (hour + 7) + ':00')"
:class="{
'drag-over': isDragOverCell === currentDay.format('YYYY-MM-DD') + '-' + (hour + 7)
}"
class="flex-1 min-h-16 p-3 dropzone"
>
<div
@@ -183,7 +193,7 @@
draggable="true"
@dragstart="handleDragStart($event, event, 'event')"
@dragend="handleDragEnd"
class="schedule-item mb-2 p-3 rounded-lg shadow-sm cursor-pointer border-l-4"
class="schedule-item mb-2 p-3 rounded-lg shadow-sm cursor-pointer border-l-4 hover:shadow-md"
:style="{
backgroundColor: `${event.color}10`,
borderLeftColor: event.color
@@ -205,7 +215,7 @@
</template>
<script setup>
import { computed, defineProps, defineEmits } from 'vue';
import { computed, defineProps, defineEmits, ref } from 'vue';
import dayjs from 'dayjs';
import { getLunarDate, getFestival, getSolarTerm, isHoliday } from '@/utils/calendarUtils';
@@ -219,6 +229,9 @@ const props = defineProps({
const emit = defineEmits(['select-date', 'show-event-detail', 'drop-event', 'drag-start', 'drag-end']);
// 拖拽状态
const isDragOverCell = ref(null);
// 计算月视图日期
const monthDays = computed(() => {
const startDay = dayjs(props.currentDate).startOf('month').startOf('week');
@@ -257,16 +270,15 @@ const hasEvent = (date) => {
return props.events.some(e => e.date === date);
};
// 获取当天第一个事件的标题
const getFirstEventTitle = (date) => {
const events = props.events.filter(e => e.date === date);
return events.length > 0 ? events[0].title : '';
};
// 获取当天的所有事件
const getEventsForDate = (date, time = null) => {
let filteredEvents = props.events.filter(e => e.date === date);
// 获取当天所有事件颜色
const getEventColorsForDay = (date) => {
const events = props.events.filter(e => e.date === date);
return [...new Set(events.map(e => e.color))];
if (time) {
filteredEvents = filteredEvents.filter(e => e.startTime === time);
}
return filteredEvents;
};
// 检查是否是今天
@@ -279,17 +291,6 @@ const isWorkDayOnWeekend = (date) => {
return false;
};
// 获取指定时间的日程
const getEventsForDate = (date, time = null) => {
let filteredEvents = props.events.filter(e => e.date === date);
if (time) {
filteredEvents = filteredEvents.filter(e => e.startTime === time);
}
return filteredEvents;
};
const selectDate = (date) => {
emit('select-date', date);
};
@@ -310,17 +311,23 @@ const handleDragEnd = () => {
// 处理拖拽悬停
const handleDragOver = (event, date, time = null) => {
event.currentTarget.classList.add('drag-over');
// 生成唯一标识,用于标记当前拖拽悬停的单元格
if (time) {
isDragOverCell.value = `${date}-${time}`;
} else {
isDragOverCell.value = date;
}
event.preventDefault();
};
// 处理拖拽离开
const handleDragLeave = (event) => {
event.currentTarget.classList.remove('drag-over');
isDragOverCell.value = null;
};
// 处理放置事件
const handleDropEvent = (event, date, time = null) => {
event.currentTarget.classList.remove('drag-over');
isDragOverCell.value = null;
emit('drop-event', event, date, time);
};
</script>
@@ -400,4 +407,4 @@ const handleDropEvent = (event, date, time = null) => {
.day-header {
background: linear-gradient(to right, #f0f4ff, #e0e7ff);
}
</style>
</style>