lion 3 weeks ago
parent 76cabe795e
commit 2ff8b73777

@ -83,7 +83,7 @@
:value="item.id"
>
<div style="display: flex; justify-content: space-between;padding: 0 10px;">
<span style="color: #999; font-size: 12px;">{{item.type_detail.name}} | {{ item.name }}</span>
<span style="color: #999; font-size: 12px;">{{item.type_detail?item.type_detail.name:''}} | {{ item.name }}</span>
<span style="color: #999; font-size: 12px;">{{ item.is_arrange?'需排课':'无需排课' }}</span>
</div>
</el-option>
@ -516,7 +516,7 @@ export default {
: "";
this.form.date = item.start_date;
this.form.url = item.url;
this.form.color = item.type_detail.color?item.type_detail.color:''
this.form.color = item.type_detail?(item.type_detail.color?item.type_detail.color:''):''
}
});
}
@ -595,6 +595,7 @@ export default {
id: this.id,
}).then((res) => {
this.form = this.base.requestToForm(res, this.form);
this.form.is_publish = res.is_publish?res.is_publish:0
this.showTinymce = true;
});
},

@ -13,10 +13,11 @@
<div class="cell-content">
<span class="date-number">{{ date.getDate() }}</span>
<div class="event-list">
<div
v-for="ev in eventsForDate(date)"
:key="ev._id"
<div
v-for="ev in eventsForDate(date)"
:key="ev._id"
:class="['event-item', getEventClass(ev, date)]"
:style="getEventItemStyle(ev)"
:title="getEventTooltip(ev, date)"
@click.stop="openCreateModal('editor', ev.id)"
>
@ -28,8 +29,8 @@
</el-calendar>
<!-- 连续事件覆盖层 -->
<div class="continuous-events-overlay">
<div
v-for="event in getContinuousEvents()"
<div
v-for="event in getContinuousEvents()"
:key="`continuous-${event.id}-${event.segStartISO}`"
:class="['continuous-event', getContinuousEventClass(event)]"
:style="getContinuousEventStyle(event)"
@ -101,7 +102,7 @@ import addCalendar from './components/addCalendar.vue'
eventsForDate(date) {
const d = new Date(date)
return this.list.filter(ev => {
const events = this.list.filter(ev => {
const startDate = this.parseDateTime(ev.start_time)
// end_timestart_time
@ -128,6 +129,111 @@ import addCalendar from './components/addCalendar.vue'
const eventStartDate = new Date(startDate.getFullYear(), startDate.getMonth(), startDate.getDate())
return currentDate.getTime() === eventStartDate.getTime()
})
//
return this.arrangeEventsVertically(events)
},
//
arrangeEventsVertically(events) {
if (!events || events.length === 0) return events
//
const sortedEvents = events.sort((a, b) => {
const timeA = this.parseDateTime(a.start_time)
const timeB = this.parseDateTime(b.start_time)
return timeA.getTime() - timeB.getTime()
})
//
const lanes = [] //
const eventHeight = 16 //
const eventSpacing = 2 //
sortedEvents.forEach(event => {
const startTime = this.parseDateTime(event.start_time)
const endTime = event.end_time ? this.parseDateTime(event.end_time) : startTime
//
const startHour = startTime.getHours() + startTime.getMinutes() / 60
const endHour = endTime.getHours() + endTime.getMinutes() / 60
//
let laneIndex = 0
let foundLane = false
for (let i = 0; i < lanes.length; i++) {
const lane = lanes[i]
//
const hasConflict = lane.some(occupied => {
return !(endHour <= occupied.start || startHour >= occupied.end)
})
if (!hasConflict) {
laneIndex = i
foundLane = true
break
}
}
//
if (!foundLane) {
laneIndex = lanes.length
lanes.push([])
}
//
lanes[laneIndex].push({
start: startHour,
end: endHour
})
//
event.verticalPosition = laneIndex
// 使bottom
event.topOffset = (lanes.length - 1 - laneIndex) * (eventHeight + eventSpacing)
})
return sortedEvents
},
//
getDayEventsWithPositions(date) {
const d = new Date(date)
const currentDateStr = d.toDateString()
//
const singleDayEvents = this.list.filter(ev => {
const startDate = this.parseDateTime(ev.start_time)
const currentDate = new Date(d.getFullYear(), d.getMonth(), d.getDate())
const eventStartDate = new Date(startDate.getFullYear(), startDate.getMonth(), startDate.getDate())
return currentDate.getTime() === eventStartDate.getTime()
})
//
const multiDayEvents = this.getContinuousEvents().filter(ev => {
const eventStart = new Date(ev.segStartISO)
const eventEnd = new Date(ev.segEndISO)
return eventStart <= d && d <= eventEnd
})
//
const allEvents = [
...singleDayEvents.map(ev => ({ ...ev, isMultiDay: false })),
...multiDayEvents.map(ev => ({ ...ev, isMultiDay: true }))
]
//
return this.arrangeEventsVertically(allEvents)
},
//
getEventItemStyle(event) {
if (event.topOffset !== undefined) {
return {
position: 'relative',
bottom: `${event.topOffset}px`,
zIndex: 70 + (event.verticalPosition || 0) //
}
}
return {}
},
getEventClass(event, date) {
const startDate = new Date(event.start_time)
@ -205,6 +311,14 @@ import addCalendar from './components/addCalendar.vue'
return s.toDateString() !== e.toDateString()
})
//
const singleDayEvents = this.list.filter(ev => {
if (!ev.end_time) return true
const s = this.parseDateTime(ev.start_time)
const e = this.parseDateTime(ev.end_time)
return s.toDateString() === e.toDateString()
})
const currentMonth = this.calendarDate.getMonth()
const currentYear = this.calendarDate.getFullYear()
const monthStart = new Date(currentYear, currentMonth, 1)
@ -238,6 +352,15 @@ import addCalendar from './components/addCalendar.vue'
const clampedStart = eventStart < monthStart ? monthStart : eventStart
const clampedEnd = eventEnd > monthEnd ? monthEnd : eventEnd
//
const hasSingleDayConflict = (date) => {
const dateStr = date.toDateString()
return singleDayEvents.some(singleEv => {
const singleStart = this.parseDateTime(singleEv.start_time)
return singleStart.toDateString() === dateStr
})
}
let cursor = getWeekStart(clampedStart)
while (cursor <= clampedEnd) {
const weekStart = new Date(cursor)
@ -272,7 +395,9 @@ import addCalendar from './components/addCalendar.vue'
displayWeekStartISO: displayWeekStart.toISOString(),
displayStartCol,
displayEndCol,
laneIndex: 0
laneIndex: 0,
//
hasSingleDayConflict: hasSingleDayConflict
})
}
cursor.setDate(cursor.getDate() + 7)
@ -360,7 +485,11 @@ import addCalendar from './components/addCalendar.vue'
const dateNumberHeight = 40 //
const eventHeight = 16
const eventSpacing = 2
const verticalOffset = (event.laneIndex || 0) * (eventHeight + eventSpacing)
//
const dayEvents = this.getDayEventsWithPositions(adjStart)
const currentEvent = dayEvents.find(ev => ev.id === event.id)
const verticalOffset = currentEvent ? currentEvent.topOffset : 0
return {
position: 'absolute',
@ -368,7 +497,7 @@ import addCalendar from './components/addCalendar.vue'
top: `${headerHeight + weekRow * cellHeight + dateNumberHeight + 25 + verticalOffset}px`, // 25px
width: `calc(${event.spanCols * cellWidth}% - 4px)`,
height: `${eventHeight}px`,
zIndex: 1000,
zIndex: 50, //
background: `linear-gradient(90deg, ${this.getEventTypeColor(event.type)} 0%, ${this.darkenColor(this.getEventTypeColor(event.type))} 100%)`,
borderRadius: '3px',
fontSize: '11px',
@ -639,7 +768,7 @@ import addCalendar from './components/addCalendar.vue'
right: 0;
bottom: 0;
pointer-events: none;
z-index: 100;
z-index: 50; /* 降低跨天事件的层级 */
}
.continuous-event {
@ -650,7 +779,7 @@ import addCalendar from './components/addCalendar.vue'
.continuous-event:hover {
transform: translateY(-1px);
filter: brightness(1.1);
z-index: 101;
z-index: 51; /* 调整悬停时的层级 */
}
/* Element UI 日历样式覆盖 */
@ -701,7 +830,8 @@ import addCalendar from './components/addCalendar.vue'
flex: 1;
overflow: visible;
position: relative;
z-index: 5;
z-index: 60; /* 提高单天事件的层级,确保在跨天事件之上 */
min-height: 60px; /* 确保有足够空间显示多个事件 */
}
.event-item {
@ -718,6 +848,9 @@ import addCalendar from './components/addCalendar.vue'
text-overflow: ellipsis;
transition: background-color 0.2s;
position: relative;
height: 16px; /* 固定高度 */
display: flex;
align-items: center;
}
.event-title {

@ -27,8 +27,8 @@ module.exports = {
*
*/
publicPath: process.env.ENV === 'staging' ? '/admin' : '/admin',
outputDir: '/Users/mac/Documents/朗业/2025/s-苏州科技商学院/wx.sstbc.com/public/admin',
// outputDir: '/Users/mac/Documents/朗业/2024/s-苏州科技商学院/wx.sstbc.com/public/admin',
// outputDir: '/Users/mac/Documents/朗业/2025/s-苏州科技商学院/wx.sstbc.com/public/admin',
outputDir: '/Users/mac/Documents/朗业/2024/s-苏州科技商学院/wx.sstbc.com/public/admin',
assetsDir: 'static',
css: {
loaderOptions: { // 向 CSS 相关的 loader 传递选项

Loading…
Cancel
Save