|
|
|
|
@ -17,6 +17,7 @@
|
|
|
|
|
v-for="ev in eventsForDate(date)"
|
|
|
|
|
:key="ev._id"
|
|
|
|
|
:class="['event-item', getEventClass(ev, date)]"
|
|
|
|
|
:style="getEventInlineStyle(ev)"
|
|
|
|
|
:title="getEventTooltip(ev, date)"
|
|
|
|
|
@click.stop="openCreateModal('editor', ev.id)"
|
|
|
|
|
>
|
|
|
|
|
@ -30,10 +31,10 @@
|
|
|
|
|
<div class="continuous-events-overlay">
|
|
|
|
|
<div
|
|
|
|
|
v-for="event in getContinuousEvents()"
|
|
|
|
|
:key="`continuous-${event.id}-${event.weekStart}`"
|
|
|
|
|
:key="`continuous-${event.id}-${event.weekStartISO}-${event.startCol}`"
|
|
|
|
|
:class="['continuous-event', `event-type-${event.type || 'default'}`]"
|
|
|
|
|
:style="getContinuousEventStyle(event)"
|
|
|
|
|
:title="getEventTooltip(event, new Date(event.weekStart))"
|
|
|
|
|
:title="getEventTooltip(event, new Date(event.segStartISO))"
|
|
|
|
|
@click.stop="openCreateModal('editor', event.id)"
|
|
|
|
|
>
|
|
|
|
|
{{ event.title }}
|
|
|
|
|
@ -179,6 +180,20 @@ import addCalendar from './components/addCalendar.vue'
|
|
|
|
|
return `${event.title}\n时间:${this.formatDateTime(event.start_time)} ~ ${this.formatDateTime(event.end_time)}`
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
getEventInlineStyle(event) {
|
|
|
|
|
// 单天事件或在格子中显示的事件,若有自定义颜色则覆盖背景
|
|
|
|
|
if (event) {
|
|
|
|
|
const custom = event.color
|
|
|
|
|
if (custom) {
|
|
|
|
|
try { console.log('[Calendar] Single-day color applied:', event.id || event._id, custom) } catch (e) {}
|
|
|
|
|
return { background: custom }
|
|
|
|
|
}
|
|
|
|
|
// 无自定义颜色时,显式使用类型默认色,避免出现无背景的情况
|
|
|
|
|
const fallback = this.getEventTypeColor(event.type)
|
|
|
|
|
return { background: fallback }
|
|
|
|
|
}
|
|
|
|
|
return {}
|
|
|
|
|
},
|
|
|
|
|
getContinuousEvents() {
|
|
|
|
|
const FIRST_DOW = 0 // 0=Sunday to match :first-day-of-week="7" on el-calendar
|
|
|
|
|
const continuousEvents = []
|
|
|
|
|
@ -278,35 +293,38 @@ import addCalendar from './components/addCalendar.vue'
|
|
|
|
|
const currentYear = this.calendarDate.getFullYear()
|
|
|
|
|
const firstDay = new Date(currentYear, currentMonth, 1)
|
|
|
|
|
|
|
|
|
|
// 可控的视觉偏移:将分段起始向后顺延 7 天
|
|
|
|
|
const adjStart = new Date(event.segStartISO)
|
|
|
|
|
adjStart.setDate(adjStart.getDate() + 7)
|
|
|
|
|
// 使用实际分段起点,不做额外周偏移
|
|
|
|
|
const segStart = new Date(event.segStartISO)
|
|
|
|
|
|
|
|
|
|
const msPerDay = 1000 * 60 * 60 * 24
|
|
|
|
|
const daysFromFirstOfMonth = Math.floor((adjStart - firstDay) / msPerDay)
|
|
|
|
|
const daysFromFirstOfMonth = Math.floor((segStart - firstDay) / msPerDay)
|
|
|
|
|
const firstDayOffset = (firstDay.getDay() - FIRST_DOW + 7) % 7
|
|
|
|
|
const totalDaysFromCalendarStart = daysFromFirstOfMonth + firstDayOffset
|
|
|
|
|
const weekRow = Math.floor(totalDaysFromCalendarStart / 7)
|
|
|
|
|
|
|
|
|
|
// 起始列使用偏移后的日期重新计算
|
|
|
|
|
const startColAdjusted = (adjStart.getDay() - FIRST_DOW + 7) % 7
|
|
|
|
|
// 起始列使用预计算的列(相对于该周)
|
|
|
|
|
const startColAdjusted = event.startCol
|
|
|
|
|
|
|
|
|
|
const cellWidth = 100 / 7
|
|
|
|
|
const cellHeight = 100
|
|
|
|
|
const headerHeight = 50
|
|
|
|
|
const headerHeight = 0
|
|
|
|
|
const cellPadding = 6 // td 与内部容器的总上内边距(约值)
|
|
|
|
|
const dateNumberHeight = 25
|
|
|
|
|
const eventHeight = 16
|
|
|
|
|
const eventSpacing = 2
|
|
|
|
|
const verticalOffset = (event.laneIndex || 0) * (eventHeight + eventSpacing)
|
|
|
|
|
|
|
|
|
|
const custom = event.color || event.bg_color || event.background
|
|
|
|
|
if (custom) { try { console.log('[Calendar] Continuous color applied:', event.id, custom) } catch (e) {} }
|
|
|
|
|
return {
|
|
|
|
|
position: 'absolute',
|
|
|
|
|
left: `calc(${startColAdjusted * cellWidth}% + 2px)`,
|
|
|
|
|
top: `${headerHeight + weekRow * cellHeight + dateNumberHeight + verticalOffset}px`,
|
|
|
|
|
top: `${headerHeight + weekRow * cellHeight + cellPadding + dateNumberHeight + verticalOffset}px`,
|
|
|
|
|
width: `calc(${event.spanCols * cellWidth}% - 4px)`,
|
|
|
|
|
height: `${eventHeight}px`,
|
|
|
|
|
zIndex: 1000,
|
|
|
|
|
background: `linear-gradient(90deg, ${this.getEventTypeColor(event.type)} 0%, ${this.darkenColor(this.getEventTypeColor(event.type))} 100%)`,
|
|
|
|
|
background: custom ? custom : `linear-gradient(90deg, ${this.getEventTypeColor(event.type)} 0%, ${this.darkenColor(this.getEventTypeColor(event.type))} 100%)`,
|
|
|
|
|
backgroundColor: custom ? custom : undefined,
|
|
|
|
|
borderRadius: '3px',
|
|
|
|
|
fontSize: '11px',
|
|
|
|
|
lineHeight: `${eventHeight}px`,
|
|
|
|
|
@ -498,22 +516,22 @@ import addCalendar from './components/addCalendar.vue'
|
|
|
|
|
|
|
|
|
|
.admin-header {
|
|
|
|
|
background: transparent;
|
|
|
|
|
padding: 20px 30px 10px 30px;
|
|
|
|
|
padding: 20rpx 30rpx 10rpx 30rpx;
|
|
|
|
|
border-bottom: none;
|
|
|
|
|
box-shadow: none;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.admin-main {
|
|
|
|
|
flex: 1;
|
|
|
|
|
padding: 20px 30px;
|
|
|
|
|
padding: 20rpx 30rpx;
|
|
|
|
|
overflow: hidden;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.calendar-panel {
|
|
|
|
|
background: #fff;
|
|
|
|
|
border-radius: 12px;
|
|
|
|
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
|
|
|
|
|
padding: 24px;
|
|
|
|
|
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.06);
|
|
|
|
|
padding: 24rpx;
|
|
|
|
|
height: 100%;
|
|
|
|
|
overflow: auto;
|
|
|
|
|
}
|
|
|
|
|
@ -538,7 +556,7 @@ import addCalendar from './components/addCalendar.vue'
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.continuous-event:hover {
|
|
|
|
|
transform: translateY(-1px);
|
|
|
|
|
transform: translateY(-1rpx);
|
|
|
|
|
filter: brightness(1.1);
|
|
|
|
|
z-index: 101;
|
|
|
|
|
}
|
|
|
|
|
@ -552,14 +570,14 @@ import addCalendar from './components/addCalendar.vue'
|
|
|
|
|
position: relative;
|
|
|
|
|
overflow: visible;
|
|
|
|
|
height: auto;
|
|
|
|
|
min-height: 100px;
|
|
|
|
|
padding: 4px;
|
|
|
|
|
min-height: 100rpx;
|
|
|
|
|
padding: 4rpx;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.calendar-panel ::v-deep .el-calendar-table td {
|
|
|
|
|
position: relative;
|
|
|
|
|
overflow: visible;
|
|
|
|
|
border: 1px solid #ebeef5;
|
|
|
|
|
border: 1rpx solid #ebeef5;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.calendar-panel ::v-deep .el-calendar-table tbody tr {
|
|
|
|
|
@ -572,17 +590,17 @@ import addCalendar from './components/addCalendar.vue'
|
|
|
|
|
|
|
|
|
|
.cell-content {
|
|
|
|
|
position: relative;
|
|
|
|
|
min-height: 100px;
|
|
|
|
|
min-height: 100rpx;
|
|
|
|
|
display: flex;
|
|
|
|
|
flex-direction: column;
|
|
|
|
|
padding: 2px;
|
|
|
|
|
padding: 2rpx;
|
|
|
|
|
overflow: visible;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.date-number {
|
|
|
|
|
font-weight: bold;
|
|
|
|
|
color: #333;
|
|
|
|
|
margin-bottom: 2px;
|
|
|
|
|
margin-bottom: 2rpx;
|
|
|
|
|
position: relative;
|
|
|
|
|
z-index: 1;
|
|
|
|
|
}
|
|
|
|
|
@ -595,10 +613,10 @@ import addCalendar from './components/addCalendar.vue'
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.event-item {
|
|
|
|
|
font-size: 11px;
|
|
|
|
|
line-height: 14px;
|
|
|
|
|
padding: 1px 3px;
|
|
|
|
|
margin: 1px 0;
|
|
|
|
|
font-size: 11rpx;
|
|
|
|
|
line-height: 14rpx;
|
|
|
|
|
padding: 1rpx 3rpx;
|
|
|
|
|
margin: 1rpx 0;
|
|
|
|
|
background: #409EFF;
|
|
|
|
|
color: white;
|
|
|
|
|
border-radius: 3px;
|
|
|
|
|
@ -681,29 +699,29 @@ import addCalendar from './components/addCalendar.vue'
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.event-item[style*="position: absolute"]:hover {
|
|
|
|
|
transform: translateY(-1px);
|
|
|
|
|
transform: translateY(-1rpx);
|
|
|
|
|
filter: brightness(1.1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.mt-4 {
|
|
|
|
|
margin-top: 24px;
|
|
|
|
|
margin-top: 24rpx;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.mb-2 {
|
|
|
|
|
margin-bottom: 8px;
|
|
|
|
|
margin-bottom: 8rpx;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@media (max-width: 1200px) {
|
|
|
|
|
.admin-header {
|
|
|
|
|
padding: 15px 20px;
|
|
|
|
|
padding: 15rpx 20rpx;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.admin-main {
|
|
|
|
|
padding: 15px 20px;
|
|
|
|
|
padding: 15rpx 20rpx;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.calendar-panel {
|
|
|
|
|
padding: 16px;
|
|
|
|
|
padding: 16rpx;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
</style>
|
|
|
|
|
|