feat: 添加HR访问量弹窗和日历事项样式优化
- 新增HR访问详情弹窗组件,支持左右切换查看不同HR信息 - 优化日历事项样式系统,基于事件类型匹配样式配置 - 完善侧边栏HR访问量组件,添加重叠头像和点击交互 - 增加班级排名弹窗组件 - 更新专家支持页面布局和样式 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -1,127 +1,145 @@
|
||||
import { getMonthDays } from "@/data/mockData";
|
||||
|
||||
const MonthView = ({
|
||||
currentDate,
|
||||
events,
|
||||
onDateClick,
|
||||
onEventClick,
|
||||
selectedDate,
|
||||
}) => {
|
||||
const year = currentDate.getFullYear();
|
||||
const month = currentDate.getMonth();
|
||||
const days = getMonthDays(year, month);
|
||||
const weekDays = ["日", "一", "二", "三", "四", "五", "六"];
|
||||
|
||||
// 获取指定日期的事件
|
||||
const getEventsForDate = (date, month, year) => {
|
||||
if (!events || events.length === 0) return [];
|
||||
|
||||
const dateString = `${year}-${(month + 1)
|
||||
.toString()
|
||||
.padStart(2, "0")}-${date.toString().padStart(2, "0")}`;
|
||||
|
||||
return events.filter((event) => {
|
||||
const eventDate = event.startTime.split(" ")[0];
|
||||
return eventDate === dateString;
|
||||
});
|
||||
};
|
||||
|
||||
const handleDateClick = (day, dayEvents) => {
|
||||
// 所有日期都可以点击
|
||||
if (onDateClick) {
|
||||
const clickedDate = new Date(day.year, day.month, day.date);
|
||||
onDateClick(clickedDate, dayEvents || []);
|
||||
}
|
||||
};
|
||||
|
||||
const isSelected = (day) => {
|
||||
if (!selectedDate) return false;
|
||||
return (
|
||||
selectedDate.getFullYear() === day.year &&
|
||||
selectedDate.getMonth() === day.month &&
|
||||
selectedDate.getDate() === day.date
|
||||
);
|
||||
};
|
||||
|
||||
const renderEventItem = (event, index, dayEvents) => {
|
||||
const maxVisible = 3; // 每个日期最多显示3个事件
|
||||
|
||||
if (
|
||||
index >= maxVisible - 1 &&
|
||||
index === maxVisible - 1 &&
|
||||
dayEvents.length > maxVisible
|
||||
) {
|
||||
// 显示"更多"指示器
|
||||
const remainingCount = dayEvents.length - maxVisible + 1;
|
||||
return (
|
||||
<div key={`more-${index}`} className="event-more">
|
||||
+{remainingCount}更多
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
if (index >= maxVisible) return null;
|
||||
|
||||
return (
|
||||
<div
|
||||
key={event.id}
|
||||
className={`event-item ${event.type}`}
|
||||
title={`${event.title} (${event.startTime.split(" ")[1]} - ${
|
||||
event.endTime.split(" ")[1]
|
||||
})`}
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
if (onEventClick) {
|
||||
onEventClick(event);
|
||||
} else {
|
||||
}
|
||||
}}
|
||||
>
|
||||
{event.title}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="month-view">
|
||||
{/* 星期标题 */}
|
||||
<div className="month-header">
|
||||
{weekDays.map((day) => (
|
||||
<div key={day} className="weekday-header">
|
||||
{day}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
{/* 日期网格 */}
|
||||
<div className="month-grid">
|
||||
{days.map((day, index) => {
|
||||
const dayEvents = getEventsForDate(day.date, day.month, day.year);
|
||||
const isToday = day.isToday;
|
||||
const isCurrentMonth = day.isCurrentMonth;
|
||||
const isSelectedDate = isSelected(day);
|
||||
|
||||
return (
|
||||
<div
|
||||
key={index}
|
||||
className={`day-cell ${!isCurrentMonth ? "other-month" : ""} ${
|
||||
isToday ? "today" : ""
|
||||
} ${isSelectedDate ? "selected" : ""}`}
|
||||
onClick={() => handleDateClick(day, dayEvents)}
|
||||
>
|
||||
<div className="day-number">{day.date}</div>
|
||||
|
||||
<div className="event-list">
|
||||
{dayEvents.map((event, eventIndex) =>
|
||||
renderEventItem(event, eventIndex, dayEvents)
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default MonthView;
|
||||
import { getMonthDays } from "@/data/mockData";
|
||||
import { getEventStyleByType } from "@/utils/calendarEventStyles";
|
||||
|
||||
const MonthView = ({
|
||||
currentDate,
|
||||
events,
|
||||
onDateClick,
|
||||
onEventClick,
|
||||
selectedDate,
|
||||
}) => {
|
||||
const year = currentDate.getFullYear();
|
||||
const month = currentDate.getMonth();
|
||||
const days = getMonthDays(year, month);
|
||||
const weekDays = ["日", "一", "二", "三", "四", "五", "六"];
|
||||
|
||||
// 获取指定日期的事件
|
||||
const getEventsForDate = (date, month, year) => {
|
||||
if (!events || events.length === 0) return [];
|
||||
|
||||
const dateString = `${year}-${(month + 1)
|
||||
.toString()
|
||||
.padStart(2, "0")}-${date.toString().padStart(2, "0")}`;
|
||||
|
||||
return events.filter((event) => {
|
||||
const eventDate = event.startTime.split(" ")[0];
|
||||
return eventDate === dateString;
|
||||
});
|
||||
};
|
||||
|
||||
const handleDateClick = (day, dayEvents) => {
|
||||
// 所有日期都可以点击
|
||||
if (onDateClick) {
|
||||
const clickedDate = new Date(day.year, day.month, day.date);
|
||||
onDateClick(clickedDate, dayEvents || []);
|
||||
}
|
||||
};
|
||||
|
||||
const isSelected = (day) => {
|
||||
if (!selectedDate) return false;
|
||||
return (
|
||||
selectedDate.getFullYear() === day.year &&
|
||||
selectedDate.getMonth() === day.month &&
|
||||
selectedDate.getDate() === day.date
|
||||
);
|
||||
};
|
||||
|
||||
const renderEventItem = (event, index, dayEvents) => {
|
||||
const maxVisible = 3; // 每个日期最多显示3个事件
|
||||
|
||||
if (
|
||||
index >= maxVisible - 1 &&
|
||||
index === maxVisible - 1 &&
|
||||
dayEvents.length > maxVisible
|
||||
) {
|
||||
// 显示"更多"指示器
|
||||
const remainingCount = dayEvents.length - maxVisible + 1;
|
||||
return (
|
||||
<div key={`more-${index}`} className="event-more">
|
||||
+{remainingCount}更多
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
if (index >= maxVisible) return null;
|
||||
|
||||
// 获取事项样式
|
||||
const eventStyle = getEventStyleByType(event.type);
|
||||
|
||||
return (
|
||||
<div
|
||||
key={event.id}
|
||||
className="event-item-new"
|
||||
title={`${event.title} (${event.startTime.split(" ")[1]} - ${
|
||||
event.endTime.split(" ")[1]
|
||||
})`}
|
||||
style={{
|
||||
backgroundColor: eventStyle.backgroundColor,
|
||||
color: eventStyle.textColor,
|
||||
}}
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
if (onEventClick) {
|
||||
onEventClick(event);
|
||||
} else {
|
||||
}
|
||||
}}
|
||||
>
|
||||
<div className="event-content">
|
||||
{eventStyle.icon && (
|
||||
<img
|
||||
src={eventStyle.icon}
|
||||
alt=""
|
||||
className="event-icon"
|
||||
style={{ width: '16px', height: '16px', marginRight: '4px' }}
|
||||
/>
|
||||
)}
|
||||
<span className="event-title">{event.title}</span>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="month-view">
|
||||
{/* 星期标题 */}
|
||||
<div className="month-header">
|
||||
{weekDays.map((day) => (
|
||||
<div key={day} className="weekday-header">
|
||||
{day}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
{/* 日期网格 */}
|
||||
<div className="month-grid">
|
||||
{days.map((day, index) => {
|
||||
const dayEvents = getEventsForDate(day.date, day.month, day.year);
|
||||
const isToday = day.isToday;
|
||||
const isCurrentMonth = day.isCurrentMonth;
|
||||
const isSelectedDate = isSelected(day);
|
||||
|
||||
return (
|
||||
<div
|
||||
key={index}
|
||||
className={`day-cell ${!isCurrentMonth ? "other-month" : ""} ${
|
||||
isToday ? "today" : ""
|
||||
} ${isSelectedDate ? "selected" : ""}`}
|
||||
onClick={() => handleDateClick(day, dayEvents)}
|
||||
>
|
||||
<div className="day-number">{day.date}</div>
|
||||
|
||||
<div className="event-list">
|
||||
{dayEvents.map((event, eventIndex) =>
|
||||
renderEventItem(event, eventIndex, dayEvents)
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default MonthView;
|
||||
|
||||
@@ -1,165 +1,181 @@
|
||||
import { useEffect, useRef } from "react";
|
||||
import { getWeekDays } from "@/data/mockData";
|
||||
|
||||
const WeekView = ({ currentDate, events, onDateClick, onEventClick }) => {
|
||||
const containerRef = useRef(null);
|
||||
const weekDays = getWeekDays(currentDate);
|
||||
const timeSlots = Array.from(
|
||||
{ length: 24 },
|
||||
(_, i) => `${i.toString().padStart(2, "0")}:00`
|
||||
);
|
||||
const weekDayNames = ["周日", "周一", "周二", "周三", "周四", "周五", "周六"];
|
||||
|
||||
// 滚动到当前时间
|
||||
useEffect(() => {
|
||||
const now = new Date();
|
||||
const currentHour = now.getHours();
|
||||
const scrollTop = currentHour * 60; // 每小时60px
|
||||
|
||||
if (containerRef.current) {
|
||||
containerRef.current.scrollTop = Math.max(0, scrollTop - 120); // 提前2小时显示
|
||||
}
|
||||
}, []);
|
||||
|
||||
// 获取指定日期的事件
|
||||
const getEventsForDate = (date) => {
|
||||
if (!events || events.length === 0) return [];
|
||||
|
||||
const dateString = `${date.getFullYear()}-${(date.getMonth() + 1)
|
||||
.toString()
|
||||
.padStart(2, "0")}-${date.getDate().toString().padStart(2, "0")}`;
|
||||
|
||||
return events.filter((event) => {
|
||||
const eventDate = event.startTime.split(" ")[0];
|
||||
return eventDate === dateString;
|
||||
});
|
||||
};
|
||||
|
||||
// 计算事件在时间轴上的位置和高度
|
||||
const calculateEventStyle = (event) => {
|
||||
const startTime = event.startTime.split(" ")[1];
|
||||
const endTime = event.endTime.split(" ")[1];
|
||||
|
||||
const startHour = parseInt(startTime.split(":")[0]);
|
||||
const startMinute = parseInt(startTime.split(":")[1]);
|
||||
const endHour = parseInt(endTime.split(":")[0]);
|
||||
const endMinute = parseInt(endTime.split(":")[1]);
|
||||
|
||||
const startOffset = startHour * 60 + startMinute; // 转换为分钟
|
||||
const endOffset = endHour * 60 + endMinute;
|
||||
const duration = endOffset - startOffset;
|
||||
|
||||
const top = startOffset; // 1分钟 = 1px
|
||||
const height = Math.max(duration, 30); // 最小高度30px
|
||||
|
||||
return {
|
||||
top: `${top}px`,
|
||||
height: `${height}px`,
|
||||
};
|
||||
};
|
||||
|
||||
const handleDateClick = (date) => {
|
||||
if (onDateClick) {
|
||||
onDateClick(date);
|
||||
}
|
||||
};
|
||||
|
||||
const getCurrentTimeLine = () => {
|
||||
const now = new Date();
|
||||
const currentHour = now.getHours();
|
||||
const currentMinute = now.getMinutes();
|
||||
const totalMinutes = currentHour * 60 + currentMinute;
|
||||
|
||||
// 只在今天显示当前时间线
|
||||
const isToday = weekDays.some(
|
||||
(date) => date.toDateString() === now.toDateString()
|
||||
);
|
||||
|
||||
if (!isToday) return null;
|
||||
|
||||
return (
|
||||
<div className="current-time-line" style={{ top: `${totalMinutes}px` }} />
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="week-view">
|
||||
{/* 周标题 */}
|
||||
<div className="week-header">
|
||||
<div className="time-header">时间</div>
|
||||
{weekDays.map((date, index) => {
|
||||
const isToday = date.toDateString() === new Date().toDateString();
|
||||
|
||||
return (
|
||||
<div
|
||||
key={date.toISOString()}
|
||||
className={`day-header ${isToday ? "today" : ""}`}
|
||||
onClick={() => handleDateClick(date)}
|
||||
>
|
||||
<div className="day-name">{weekDayNames[index]}</div>
|
||||
<div className="day-date">{date.getDate()}</div>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
|
||||
{/* 周网格 */}
|
||||
<div className="week-grid" ref={containerRef}>
|
||||
{/* 时间列 */}
|
||||
<div className="time-column">
|
||||
{timeSlots.map((time) => (
|
||||
<div key={time} className="time-slot">
|
||||
{time}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
{/* 日期列 */}
|
||||
{weekDays.map((date) => {
|
||||
const dayEvents = getEventsForDate(date);
|
||||
|
||||
return (
|
||||
<div key={date.toISOString()} className="day-column">
|
||||
{/* 小时格子 */}
|
||||
{timeSlots.map((time) => (
|
||||
<div key={time} className="hour-slot" />
|
||||
))}
|
||||
|
||||
{/* 事件块 */}
|
||||
{dayEvents.map((event) => {
|
||||
const style = calculateEventStyle(event);
|
||||
|
||||
return (
|
||||
<div
|
||||
key={event.id}
|
||||
className={`event-block ${event.type}`}
|
||||
style={style}
|
||||
title={event.description}
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
if (onEventClick) {
|
||||
onEventClick(event);
|
||||
} else {
|
||||
}
|
||||
}}
|
||||
>
|
||||
<div className="event-title">{event.title}</div>
|
||||
<div className="event-time">
|
||||
{event.startTime.split(" ")[1]} -{" "}
|
||||
{event.endTime.split(" ")[1]}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
|
||||
{/* 当前时间线 */}
|
||||
{getCurrentTimeLine()}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default WeekView;
|
||||
import { useEffect, useRef } from "react";
|
||||
import { getWeekDays } from "@/data/mockData";
|
||||
import { getEventStyleByType } from "@/utils/calendarEventStyles";
|
||||
|
||||
const WeekView = ({ currentDate, events, onDateClick, onEventClick }) => {
|
||||
const containerRef = useRef(null);
|
||||
const weekDays = getWeekDays(currentDate);
|
||||
const timeSlots = Array.from(
|
||||
{ length: 24 },
|
||||
(_, i) => `${i.toString().padStart(2, "0")}:00`
|
||||
);
|
||||
const weekDayNames = ["周日", "周一", "周二", "周三", "周四", "周五", "周六"];
|
||||
|
||||
// 滚动到当前时间
|
||||
useEffect(() => {
|
||||
const now = new Date();
|
||||
const currentHour = now.getHours();
|
||||
const scrollTop = currentHour * 60; // 每小时60px
|
||||
|
||||
if (containerRef.current) {
|
||||
containerRef.current.scrollTop = Math.max(0, scrollTop - 120); // 提前2小时显示
|
||||
}
|
||||
}, []);
|
||||
|
||||
// 获取指定日期的事件
|
||||
const getEventsForDate = (date) => {
|
||||
if (!events || events.length === 0) return [];
|
||||
|
||||
const dateString = `${date.getFullYear()}-${(date.getMonth() + 1)
|
||||
.toString()
|
||||
.padStart(2, "0")}-${date.getDate().toString().padStart(2, "0")}`;
|
||||
|
||||
return events.filter((event) => {
|
||||
const eventDate = event.startTime.split(" ")[0];
|
||||
return eventDate === dateString;
|
||||
});
|
||||
};
|
||||
|
||||
// 计算事件在时间轴上的位置和高度
|
||||
const calculateEventStyle = (event) => {
|
||||
const startTime = event.startTime.split(" ")[1];
|
||||
const endTime = event.endTime.split(" ")[1];
|
||||
|
||||
const startHour = parseInt(startTime.split(":")[0]);
|
||||
const startMinute = parseInt(startTime.split(":")[1]);
|
||||
const endHour = parseInt(endTime.split(":")[0]);
|
||||
const endMinute = parseInt(endTime.split(":")[1]);
|
||||
|
||||
const startOffset = startHour * 60 + startMinute; // 转换为分钟
|
||||
const endOffset = endHour * 60 + endMinute;
|
||||
const duration = endOffset - startOffset;
|
||||
|
||||
const top = startOffset; // 1分钟 = 1px
|
||||
const height = Math.max(duration, 30); // 最小高度30px
|
||||
|
||||
return {
|
||||
top: `${top}px`,
|
||||
height: `${height}px`,
|
||||
};
|
||||
};
|
||||
|
||||
const handleDateClick = (date) => {
|
||||
if (onDateClick) {
|
||||
onDateClick(date);
|
||||
}
|
||||
};
|
||||
|
||||
const getCurrentTimeLine = () => {
|
||||
const now = new Date();
|
||||
const currentHour = now.getHours();
|
||||
const currentMinute = now.getMinutes();
|
||||
const totalMinutes = currentHour * 60 + currentMinute;
|
||||
|
||||
// 只在今天显示当前时间线
|
||||
const isToday = weekDays.some(
|
||||
(date) => date.toDateString() === now.toDateString()
|
||||
);
|
||||
|
||||
if (!isToday) return null;
|
||||
|
||||
return (
|
||||
<div className="current-time-line" style={{ top: `${totalMinutes}px` }} />
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="week-view">
|
||||
{/* 周标题 */}
|
||||
<div className="week-header">
|
||||
<div className="time-header">时间</div>
|
||||
{weekDays.map((date, index) => {
|
||||
const isToday = date.toDateString() === new Date().toDateString();
|
||||
|
||||
return (
|
||||
<div
|
||||
key={date.toISOString()}
|
||||
className={`day-header ${isToday ? "today" : ""}`}
|
||||
onClick={() => handleDateClick(date)}
|
||||
>
|
||||
<div className="day-name">{weekDayNames[index]}</div>
|
||||
<div className="day-date">{date.getDate()}</div>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
|
||||
{/* 周网格 */}
|
||||
<div className="week-grid" ref={containerRef}>
|
||||
{/* 时间列 */}
|
||||
<div className="time-column">
|
||||
{timeSlots.map((time) => (
|
||||
<div key={time} className="time-slot">
|
||||
{time}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
{/* 日期列 */}
|
||||
{weekDays.map((date) => {
|
||||
const dayEvents = getEventsForDate(date);
|
||||
|
||||
return (
|
||||
<div key={date.toISOString()} className="day-column">
|
||||
{/* 小时格子 */}
|
||||
{timeSlots.map((time) => (
|
||||
<div key={time} className="hour-slot" />
|
||||
))}
|
||||
|
||||
{/* 事件块 */}
|
||||
{dayEvents.map((event) => {
|
||||
const style = calculateEventStyle(event);
|
||||
const eventStyle = getEventStyleByType(event.type);
|
||||
|
||||
return (
|
||||
<div
|
||||
key={event.id}
|
||||
className="event-block-new"
|
||||
style={{
|
||||
...style,
|
||||
backgroundColor: eventStyle.backgroundColor,
|
||||
color: eventStyle.textColor,
|
||||
}}
|
||||
title={event.description}
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
if (onEventClick) {
|
||||
onEventClick(event);
|
||||
} else {
|
||||
}
|
||||
}}
|
||||
>
|
||||
<div className="event-header">
|
||||
{eventStyle.icon && (
|
||||
<img
|
||||
src={eventStyle.icon}
|
||||
alt=""
|
||||
className="event-icon"
|
||||
style={{ width: '18px', height: '18px', marginRight: '4px' }}
|
||||
/>
|
||||
)}
|
||||
<div className="event-title">{event.title}</div>
|
||||
</div>
|
||||
<div className="event-time">
|
||||
{event.startTime.split(" ")[1]} -{" "}
|
||||
{event.endTime.split(" ")[1]}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
|
||||
{/* 当前时间线 */}
|
||||
{getCurrentTimeLine()}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default WeekView;
|
||||
|
||||
@@ -217,6 +217,47 @@
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/* 新的事项样式 - 使用JSON配置 */
|
||||
.event-item-new {
|
||||
font-size: 11px;
|
||||
padding: 3px 6px;
|
||||
border-radius: 4px;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
font-weight: 500;
|
||||
max-width: 100%;
|
||||
display: block;
|
||||
margin: 1px 0;
|
||||
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1);
|
||||
border: 1px solid rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.event-item-new:hover {
|
||||
transform: translateX(2px);
|
||||
box-shadow: 0 3px 8px rgba(0, 0, 0, 0.15);
|
||||
opacity: 0.9;
|
||||
}
|
||||
|
||||
.event-item-new .event-content {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.event-item-new .event-icon {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.event-item-new .event-title {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
/* 保持原有样式作为备用 */
|
||||
.event-item {
|
||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||
color: white;
|
||||
@@ -397,6 +438,54 @@
|
||||
background: #fbfcfd;
|
||||
}
|
||||
|
||||
/* 新的周视图事件块样式 */
|
||||
.event-block-new {
|
||||
position: absolute;
|
||||
left: 4px;
|
||||
right: 4px;
|
||||
border-radius: 4px;
|
||||
padding: 4px 6px;
|
||||
font-size: 11px;
|
||||
z-index: 5;
|
||||
cursor: pointer;
|
||||
transition: all 0.15s ease;
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
|
||||
border: 1px solid rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.event-block-new:hover {
|
||||
transform: translateY(-1px);
|
||||
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.15);
|
||||
opacity: 0.9;
|
||||
}
|
||||
|
||||
.event-block-new .event-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 2px;
|
||||
}
|
||||
|
||||
.event-block-new .event-icon {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.event-block-new .event-title {
|
||||
font-weight: 600;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.event-block-new .event-time {
|
||||
font-size: 10px;
|
||||
opacity: 0.9;
|
||||
}
|
||||
|
||||
/* 保持原有样式作为备用 */
|
||||
.event-block {
|
||||
position: absolute;
|
||||
left: 4px;
|
||||
|
||||
Reference in New Issue
Block a user