|
|
|
|
@ -17,7 +17,33 @@
|
|
|
|
|
<view class="cell" v-for="cell in row" :key="cell.fullDate" :style="'height:'+cellHeight+'rpx'" @tap="onDayClick(cell.fullDate)">
|
|
|
|
|
<text class="date-num" :class="{ dim: !cell.inMonth }">{{ cell.date }}</text>
|
|
|
|
|
<view class="cell-events" :style="'padding-top:'+getCellPadding(cell.fullDate)+'rpx'">
|
|
|
|
|
<view v-for="ev in eventsForDate(cell.fullDate)" :key="ev.id" class="event-chip" :class="['event-type-' + (ev.type || 'default'), { 'single-line-open': isSingleEvent(cell.fullDate), 'conflict': hasSpanConflict(cell.fullDate), 'has-multi-day': hasSpanConflict(cell.fullDate) }]" :style="'background:' + ((ev && ev.color) ? ev.color : '#ddba99') + ';' + (hasSpanConflict(cell.fullDate) ? 'transform: translateY(10px) !important; padding-top: 10px !important;' : '')" @tap="onEventClick(ev)">
|
|
|
|
|
<view
|
|
|
|
|
v-for="ev in eventsForDate(cell.fullDate)"
|
|
|
|
|
:key="ev.id"
|
|
|
|
|
class="event-chip"
|
|
|
|
|
:class="[
|
|
|
|
|
'event-type-' + (ev.type || 'default'),
|
|
|
|
|
{
|
|
|
|
|
'single-line-open': isSingleEvent(cell.fullDate) && !hasOtherEvents(cell.fullDate),
|
|
|
|
|
'has-other-events': hasOtherEvents(cell.fullDate),
|
|
|
|
|
'conflict': hasSpanConflict(cell.fullDate),
|
|
|
|
|
// 当采用底部定位布局时,禁用 has-multi-day 以避免 padding-top:10px !important 干扰
|
|
|
|
|
'has-multi-day': hasSpanConflict(cell.fullDate) && !hasMultiDayCover(cell.fullDate)
|
|
|
|
|
}
|
|
|
|
|
]"
|
|
|
|
|
:style="[
|
|
|
|
|
{ background: (ev && ev.color) ? ev.color : '#ddba99' },
|
|
|
|
|
// 冲突下移(较低优先级)
|
|
|
|
|
hasSpanConflict(cell.fullDate)
|
|
|
|
|
? { transform: 'translateY(10px)', paddingTop: '10px' }
|
|
|
|
|
: {},
|
|
|
|
|
// 有跨天覆盖或其他事件:固定到底部,单行,清除上内边距与位移
|
|
|
|
|
hasMultiDayCover(cell.fullDate)
|
|
|
|
|
? { position: 'absolute', bottom: '10px', left: 0, right: 0, paddingTop: '0px', transform: 'none', '-webkit-line-clamp': 1, 'line-clamp': 1 }
|
|
|
|
|
: {}
|
|
|
|
|
]"
|
|
|
|
|
@tap.stop="onEventClick(ev)"
|
|
|
|
|
>
|
|
|
|
|
{{ formatTitle(ev.title) }}
|
|
|
|
|
</view>
|
|
|
|
|
</view>
|
|
|
|
|
@ -26,7 +52,7 @@
|
|
|
|
|
|
|
|
|
|
<!-- 跨天覆盖层 -->
|
|
|
|
|
<view class="overlay">
|
|
|
|
|
<view v-for="(seg, si) in continuousSegments" :key="si" class="continuous-bar" :style="'left:'+seg._style.left+';width:'+seg._style.width+';top:'+seg._style.top+';height:'+seg._style.height+';'+(seg._isOnlyOne ? '' : ('line-height:'+seg._style.height+';'))+(seg.color?('background:'+seg.color+';'):'background:#ddba99;')" :class="['event-type-' + (seg.type || 'default'), { 'nobreak': seg._isOnlyOne } ]" @tap="onSegmentClick(seg)">
|
|
|
|
|
<view v-for="(seg, si) in continuousSegments" :key="si" class="continuous-bar" :style="'left:'+seg._style.left+';width:'+seg._style.width+';top:'+seg._style.top+';height:'+seg._style.height+';'+(seg._isOnlyOne ? '' : ('line-height:'+seg._style.height+';'))+(seg.color?('background:'+seg.color+';'):'background:#ddba99;')" :class="['event-type-' + (seg.type || 'default'), { 'nobreak': seg._isOnlyOne } ]" @tap.stop="onSegmentClick(seg)">
|
|
|
|
|
{{ formatTitle(seg.title) }}
|
|
|
|
|
</view>
|
|
|
|
|
</view>
|
|
|
|
|
@ -349,6 +375,15 @@ export default {
|
|
|
|
|
this.laneCountByDate = laneCountByDate
|
|
|
|
|
this.segCountByDate = segCountByDate
|
|
|
|
|
|
|
|
|
|
// 调试信息
|
|
|
|
|
console.log('segCountByDate 统计结果:', segCountByDate)
|
|
|
|
|
console.log('所有跨天分段:', segs.map(seg => ({
|
|
|
|
|
id: seg.id,
|
|
|
|
|
title: seg.title,
|
|
|
|
|
start: new Date(seg.segStartMs).toISOString().split('T')[0],
|
|
|
|
|
end: new Date(seg.segEndMs).toISOString().split('T')[0]
|
|
|
|
|
})))
|
|
|
|
|
|
|
|
|
|
return segs
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
@ -381,6 +416,40 @@ export default {
|
|
|
|
|
|
|
|
|
|
return result
|
|
|
|
|
},
|
|
|
|
|
hasMultiDayCover(fullDate) {
|
|
|
|
|
// 直接基于当前计算出的连续分段判断该日期是否被任意跨天分段覆盖
|
|
|
|
|
try {
|
|
|
|
|
const target = new Date(fullDate)
|
|
|
|
|
target.setHours(0,0,0,0)
|
|
|
|
|
const tMs = target.getTime()
|
|
|
|
|
const segs = this.continuousSegments || []
|
|
|
|
|
for (let i = 0; i < segs.length; i += 1) {
|
|
|
|
|
const s = segs[i]
|
|
|
|
|
if (tMs >= s.segStartMs && tMs <= s.segEndMs) return true
|
|
|
|
|
}
|
|
|
|
|
return false
|
|
|
|
|
} catch (_) {
|
|
|
|
|
return false
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
hasOtherEvents(fullDate) {
|
|
|
|
|
// 判断该日期是否有其他事件(包括跨天事件)
|
|
|
|
|
const singleEvents = this.eventsForDate(fullDate) || []
|
|
|
|
|
const hasMultiDay = !!(this.segCountByDate && this.segCountByDate[fullDate] > 0)
|
|
|
|
|
const result = singleEvents.length > 1 || hasMultiDay
|
|
|
|
|
|
|
|
|
|
// 调试信息
|
|
|
|
|
if (fullDate.includes('25')) {
|
|
|
|
|
console.log(`日期 ${fullDate} 检查其他事件:`, {
|
|
|
|
|
singleEvents: singleEvents.length,
|
|
|
|
|
hasMultiDay,
|
|
|
|
|
segCount: this.segCountByDate ? this.segCountByDate[fullDate] : 'undefined',
|
|
|
|
|
result
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return result
|
|
|
|
|
},
|
|
|
|
|
onEventClick(ev) {
|
|
|
|
|
this.$emit('eventClick', ev)
|
|
|
|
|
},
|
|
|
|
|
@ -471,12 +540,6 @@ export default {
|
|
|
|
|
if (isMulti) return false
|
|
|
|
|
return d0.getTime() === s.getTime()
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
// 调试信息
|
|
|
|
|
if (result.length > 0) {
|
|
|
|
|
console.log(`日期 ${fullDate} 的单天事件:`, result)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return result
|
|
|
|
|
},
|
|
|
|
|
pad2(n) {
|
|
|
|
|
@ -583,7 +646,6 @@ export default {
|
|
|
|
|
font-weight: 600;
|
|
|
|
|
color: #333;
|
|
|
|
|
position: relative;
|
|
|
|
|
z-index: 3;
|
|
|
|
|
text-align: center;
|
|
|
|
|
width: 100%;
|
|
|
|
|
margin-bottom: 4px;
|
|
|
|
|
@ -593,7 +655,6 @@ export default {
|
|
|
|
|
}
|
|
|
|
|
.cell-events {
|
|
|
|
|
position: relative;
|
|
|
|
|
z-index: 2; /* 让跨天条位于其上方 */
|
|
|
|
|
width: 100%;
|
|
|
|
|
overflow: hidden;
|
|
|
|
|
}
|
|
|
|
|
@ -605,10 +666,11 @@ export default {
|
|
|
|
|
color: #fff;
|
|
|
|
|
border-radius: 16rpx;
|
|
|
|
|
overflow: hidden;
|
|
|
|
|
white-space: nowrap;
|
|
|
|
|
text-overflow: ellipsis;
|
|
|
|
|
max-width: 100%;
|
|
|
|
|
box-sizing: border-box;
|
|
|
|
|
display: -webkit-box;
|
|
|
|
|
-webkit-line-clamp: 1;
|
|
|
|
|
-webkit-box-orient: vertical;
|
|
|
|
|
}
|
|
|
|
|
.event-chip.event-type-1 { background: #67C23A; }
|
|
|
|
|
.event-chip.event-type-2 { background: #409EFF; }
|
|
|
|
|
@ -618,19 +680,20 @@ export default {
|
|
|
|
|
.event-chip.event-type-default { background: #ddba99; }
|
|
|
|
|
/* 当天只有一条单天事件时,允许换行不省略 */
|
|
|
|
|
.event-chip.single-line-open {
|
|
|
|
|
white-space: normal;
|
|
|
|
|
word-break: break-all;
|
|
|
|
|
text-overflow: ellipsis;
|
|
|
|
|
display: -webkit-box;
|
|
|
|
|
-webkit-line-clamp: 3; /* 最多三行 */
|
|
|
|
|
-webkit-box-orient: vertical;
|
|
|
|
|
overflow: hidden;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* 当天有其他事件时(多条单天事件或跨天事件),单条数据定位在底部 */
|
|
|
|
|
.event-chip.single-line-open.has-other-events {
|
|
|
|
|
-webkit-line-clamp: 1; /* 强制一行 */
|
|
|
|
|
position: absolute;
|
|
|
|
|
bottom: 0;
|
|
|
|
|
left: 0;
|
|
|
|
|
right: 0;
|
|
|
|
|
}
|
|
|
|
|
/* 与跨天冲突时,单日事件强制一行省略 */
|
|
|
|
|
.event-chip.conflict {
|
|
|
|
|
white-space: nowrap !important;
|
|
|
|
|
overflow: hidden !important;
|
|
|
|
|
text-overflow: ellipsis !important;
|
|
|
|
|
-webkit-line-clamp: 1 !important;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* 当有跨天事件时,单天事件需要更多上边距 */
|
|
|
|
|
@ -645,12 +708,10 @@ export default {
|
|
|
|
|
right: 0;
|
|
|
|
|
bottom: 0;
|
|
|
|
|
pointer-events: none;
|
|
|
|
|
z-index: 4; /* 置于单日事件之上,避免被遮挡 */
|
|
|
|
|
}
|
|
|
|
|
.continuous-bar {
|
|
|
|
|
position: absolute;
|
|
|
|
|
pointer-events: auto;
|
|
|
|
|
z-index: 2;
|
|
|
|
|
color: #fff;
|
|
|
|
|
font-size: 11px;
|
|
|
|
|
line-height: 18px;
|
|
|
|
|
|