refactor(event): 三个下拉抽屉改为自筛选栏下缘自绘展开

- 移除 up-popup 模板:场所/状态/时间三个抽屉统一改为自绘 .drop-panel,
  锚定在筛选栏下缘展开(不再占全屏)
- 抽出 .content-area 作为抽屉定位锚点与统一遮罩容器,
  三个抽屉共享 .content-mask 关闭交互
- 时间抽屉去重 time-mask/time-drawer 旧样式,面板高度改为 66vh 并受
  max-height: 100% 约束,避免遮罩下方露白
This commit is contained in:
ozh 2026-08-19 17:02:33 +08:00
parent f5fe717d7d
commit 054f05af70
1 changed files with 135 additions and 112 deletions

View File

@ -24,16 +24,22 @@
</view>
</view>
<view class="empty-area">
<up-empty mode="message" text="暂无事件数据" />
</view>
<view class="empty-hint">
<text>调整筛选条件后的事件列表将在此展示</text>
</view>
<!-- 数据层筛选栏以下区域三个下拉抽屉都锚定在这层顶部筛选栏下缘展开 -->
<view class="content-area">
<view class="content-body">
<view class="empty-area">
<up-empty mode="message" text="暂无事件数据" />
</view>
<view class="empty-hint">
<text>调整筛选条件后的事件列表将在此展示</text>
</view>
</view>
<!-- 场所抽屉顶部下拉选项列表 -->
<up-popup :show="drawer === 'scene'" mode="top" round="24" :overlay-opacity="0.35" :safe-area-inset-bottom="false" :custom-style="{ width: '100vw' }" @close="closeDrawer">
<view class="option-drawer">
<!-- 遮罩盖住筛选栏以下全部内容 -->
<view v-if="drawer" class="content-mask" @click="closeDrawer" @touchmove.stop.prevent="noop" />
<!-- 场所抽屉从筛选栏下缘展开 -->
<view v-if="drawer === 'scene'" class="drop-panel drop-panel--options">
<view class="option-drawer-header">
<text class="option-drawer-title">选择场所</text>
<view class="option-drawer-close" @click="closeDrawer">
@ -53,11 +59,9 @@
</view>
</view>
</view>
</up-popup>
<!-- 状态抽屉顶部下拉选项列表 -->
<up-popup :show="drawer === 'status'" mode="top" round="24" :overlay-opacity="0.35" :safe-area-inset-bottom="false" :custom-style="{ width: '100vw' }" @close="closeDrawer">
<view class="option-drawer">
<!-- 状态抽屉从筛选栏下缘展开 -->
<view v-if="drawer === 'status'" class="drop-panel drop-panel--options">
<view class="option-drawer-header">
<text class="option-drawer-title">选择状态</text>
<view class="option-drawer-close" @click="closeDrawer">
@ -77,83 +81,82 @@
</view>
</view>
</view>
</up-popup>
<!-- 时间抽屉自绘遮罩 + 顶部面板滚动式日历懒渲染窗口外月份占位 -->
<view v-if="drawer === 'time'" class="time-mask" @click="closeDrawer" @touchmove.stop.prevent="noop" />
<view v-if="drawer === 'time'" class="time-drawer">
<view class="time-drawer-header">
<text class="time-drawer-title">选择时间范围</text>
<view class="time-drawer-close" @click="closeDrawer">
<up-icon name="close" size="20" color="#909399" />
<!-- 时间抽屉从筛选栏下缘展开滚动式日历懒渲染窗口外月份占位 -->
<view v-if="drawer === 'time'" class="drop-panel drop-panel--calendar">
<view class="time-drawer-header">
<text class="time-drawer-title">选择时间范围</text>
<view class="time-drawer-close" @click="closeDrawer">
<up-icon name="close" size="20" color="#909399" />
</view>
</view>
</view>
<!-- 快捷范围点选直接填满起止 -->
<view class="quick-row">
<view
v-for="q in quickRanges"
:key="q.label"
class="quick-chip"
:class="{ 'quick-chip--active': activeQuick === q.label }"
@click="applyQuick(q)"
>
<text>{{ q.label }}</text>
</view>
</view>
<!-- 星期行钉在滚动区上方 -->
<view class="cal-weekdays">
<text v-for="w in weekdayLabels" :key="w" class="cal-weekday">{{ w }}</text>
</view>
<!-- 滚动日历scroll-view 纵向滚月懒渲染窗口外月份只渲染占位高度 -->
<view class="cal-scroll-wrap">
<scroll-view
class="cal-scroll"
scroll-y
:scroll-into-view="calAnchorId"
scroll-anchoring
@scroll="onCalScroll"
>
<!-- 快捷范围点选直接填满起止 -->
<view class="quick-row">
<view
v-for="m in renderedMonths"
:key="m.key"
:id="m.key"
class="cal-month"
:style="m.placeholder ? { height: m.height + 'rpx' } : {}"
v-for="q in quickRanges"
:key="q.label"
class="quick-chip"
:class="{ 'quick-chip--active': activeQuick === q.label }"
@click="applyQuick(q)"
>
<template v-if="!m.placeholder">
<view class="cal-month-title">
<text>{{ m.title }}</text>
</view>
<view class="cal-grid">
<view
v-for="(cell, i) in m.cells"
:key="i"
class="cal-cell"
:class="cell.cls"
@click="pickDate(cell)"
>
<view v-if="cell.day" class="cal-day" :class="cell.dayCls">
<text class="cal-day-num">{{ cell.day }}</text>
<text v-if="cell.tag" class="cal-day-tag">{{ cell.tag }}</text>
<text>{{ q.label }}</text>
</view>
</view>
<!-- 星期行钉在滚动区上方 -->
<view class="cal-weekdays">
<text v-for="w in weekdayLabels" :key="w" class="cal-weekday">{{ w }}</text>
</view>
<!-- 滚动日历scroll-view 纵向滚月懒渲染窗口外月份只渲染占位高度 -->
<view class="cal-scroll-wrap">
<scroll-view
class="cal-scroll"
scroll-y
:scroll-into-view="calAnchorId"
scroll-anchoring
@scroll="onCalScroll"
>
<view
v-for="m in renderedMonths"
:key="m.key"
:id="m.key"
class="cal-month"
:style="m.placeholder ? { height: m.height + 'rpx' } : {}"
>
<template v-if="!m.placeholder">
<view class="cal-month-title">
<text>{{ m.title }}</text>
</view>
<view class="cal-grid">
<view
v-for="(cell, i) in m.cells"
:key="i"
class="cal-cell"
:class="cell.cls"
@click="pickDate(cell)"
>
<view v-if="cell.day" class="cal-day" :class="cell.dayCls">
<text class="cal-day-num">{{ cell.day }}</text>
<text v-if="cell.tag" class="cal-day-tag">{{ cell.tag }}</text>
</view>
</view>
</view>
</view>
</template>
</view>
</scroll-view>
</view>
</template>
</view>
</scroll-view>
</view>
<view class="time-drawer-footer">
<up-button
shape="circle"
:text="rangeReady ? '确定' : '请选择起止日期'"
color="#2CCB98"
:disabled="!rangeReady"
@click="onConfirmClick"
/>
<view class="time-drawer-footer">
<up-button
shape="circle"
:text="rangeReady ? '确定' : '请选择起止日期'"
color="#2CCB98"
:disabled="!rangeReady"
@click="onConfirmClick"
/>
</view>
</view>
</view>
</view>
@ -441,7 +444,14 @@ export default {
<style lang="scss" scoped>
@import '@/styles/common.css';
/* 页面容器:纵向 flex让数据层撑满筛选栏以下的全部剩余视口 */
.page {
display: flex;
flex-direction: column;
}
.filters {
flex-shrink: 0;
display: flex;
align-items: stretch;
min-height: 96rpx;
@ -501,11 +511,49 @@ export default {
color: #b5b9c0;
}
/* 场所/状态选项抽屉 */
.option-drawer {
/* 数据层:撑满筛选栏以下全部视口,是三个下拉抽屉的定位锚点 */
.content-area {
position: relative;
flex: 1;
min-height: 0;
}
/* 遮罩:盖住筛选栏以下内容,点击关闭 */
.content-mask {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.35);
z-index: 10;
}
/* 下拉面板:从数据层顶部(筛选栏下缘)展开 */
.drop-panel {
position: absolute;
top: 0;
left: 0;
width: 100%;
background: #ffffff;
padding-bottom: 24rpx;
box-shadow: 0 12rpx 40rpx rgba(0, 0, 0, 0.08);
z-index: 11;
display: flex;
flex-direction: column;
border-bottom-left-radius: 24rpx;
border-bottom-right-radius: 24rpx;
overflow: hidden;
}
/* 场所/状态选项面板:内容自适应高度 */
.drop-panel--options {
max-height: 60vh;
}
/* 时间面板:日历占剩余空间,但不超过数据层高度(时间抽屉时遮罩仍完整盖住剩余空间) */
.drop-panel--calendar {
height: 66vh;
max-height: 100%;
}
.option-drawer-header {
@ -531,7 +579,7 @@ export default {
}
.option-drawer-list {
padding: 12rpx 24rpx;
padding: 12rpx 24rpx 24rpx;
}
.option-drawer-item {
@ -561,32 +609,7 @@ export default {
font-weight: 600;
}
/* 时间抽屉:自绘遮罩 + 顶部面板(不经过 up-popup避免其 touchmove 拦截吞掉日历滚动手势) */
.time-mask {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.35);
z-index: 10075;
}
.time-drawer {
position: fixed;
top: 0;
left: 0;
width: 100vw;
height: 66vh; /* 固定高度:日历窗口+按钮填满,按钮钉底 */
z-index: 10076;
background: #ffffff;
border-bottom-left-radius: 32rpx;
border-bottom-right-radius: 32rpx;
display: flex;
flex-direction: column;
overflow: hidden;
}
/* 时间面板头/底部(面板已锚定在筛选栏下方,不再 fixed */
.time-drawer-header {
padding: 20rpx 32rpx;
display: flex;