refactor(页面布局): 重构打卡页面布局为固定日历和可滚动内容区域
将日历组件改为固定定位,内容区域改为可滚动布局 动态计算日历高度并设置内容区域margin-top 移除日历背景样式以保持整体设计一致
Showing
2 changed files
with
185 additions
and
180 deletions
| 1 | <!-- | 1 | <!-- |
| 2 | * @Date: 2025-01-25 15:34:17 | 2 | * @Date: 2025-01-25 15:34:17 |
| 3 | * @LastEditors: hookehuyr hookehuyr@gmail.com | 3 | * @LastEditors: hookehuyr hookehuyr@gmail.com |
| 4 | - * @LastEditTime: 2025-09-24 22:41:07 | 4 | + * @LastEditTime: 2025-09-25 09:37:57 |
| 5 | * @FilePath: /mlaj/src/components/ui/CollapsibleCalendar.vue | 5 | * @FilePath: /mlaj/src/components/ui/CollapsibleCalendar.vue |
| 6 | * @Description: 可折叠日历组件 | 6 | * @Description: 可折叠日历组件 |
| 7 | --> | 7 | --> |
| 8 | <template> | 8 | <template> |
| 9 | - <div class="collapsible-calendar"> | 9 | + <div class="collapsible-calendar "> |
| 10 | <!-- 折叠状态显示 --> | 10 | <!-- 折叠状态显示 --> |
| 11 | <div v-if="!isExpanded" class="calendar-collapsed" @click="expandCalendar"> | 11 | <div v-if="!isExpanded" class="calendar-collapsed" @click="expandCalendar"> |
| 12 | <div class="calendar-header"> | 12 | <div class="calendar-header"> |
| ... | @@ -165,8 +165,8 @@ defineExpose({ | ... | @@ -165,8 +165,8 @@ defineExpose({ |
| 165 | } | 165 | } |
| 166 | 166 | ||
| 167 | .calendar-collapsed { | 167 | .calendar-collapsed { |
| 168 | - background: linear-gradient(135deg, #ffffff 0%, #f8fffe 100%); | 168 | + // background: linear-gradient(135deg, #ffffff 0%, #f8fffe 100%); |
| 169 | - border-radius: 16px; | 169 | + // border-radius: 16px; |
| 170 | padding: 20px; | 170 | padding: 20px; |
| 171 | box-shadow: 0 4px 20px rgba(76, 175, 80, 0.08), 0 2px 8px rgba(0, 0, 0, 0.06); | 171 | box-shadow: 0 4px 20px rgba(76, 175, 80, 0.08), 0 2px 8px rgba(0, 0, 0, 0.06); |
| 172 | cursor: pointer; | 172 | cursor: pointer; | ... | ... |
| 1 | <!-- | 1 | <!-- |
| 2 | * @Date: 2025-05-29 15:34:17 | 2 | * @Date: 2025-05-29 15:34:17 |
| 3 | * @LastEditors: hookehuyr hookehuyr@gmail.com | 3 | * @LastEditors: hookehuyr hookehuyr@gmail.com |
| 4 | - * @LastEditTime: 2025-09-24 21:56:56 | 4 | + * @LastEditTime: 2025-09-25 09:30:55 |
| 5 | * @FilePath: /mlaj/src/views/checkin/IndexCheckInPage.vue | 5 | * @FilePath: /mlaj/src/views/checkin/IndexCheckInPage.vue |
| 6 | * @Description: 文件描述 | 6 | * @Description: 文件描述 |
| 7 | --> | 7 | --> |
| 8 | <template> | 8 | <template> |
| 9 | <AppLayout :hasTitle="false"> | 9 | <AppLayout :hasTitle="false"> |
| 10 | <van-config-provider :theme-vars="themeVars"> | 10 | <van-config-provider :theme-vars="themeVars"> |
| 11 | - <CollapsibleCalendar | 11 | + <!-- 固定的日历组件 --> |
| 12 | - ref="myRefCalendar" | 12 | + <div class="fixed-calendar"> |
| 13 | - :title="taskDetail.title" | 13 | + <CollapsibleCalendar |
| 14 | - :formatter="formatter" | 14 | + ref="calendarRef" |
| 15 | - v-model="selectedDate" | 15 | + :title="taskDetail.title" |
| 16 | - @select="onSelectDay" | 16 | + :formatter="formatter" |
| 17 | - @click-subtitle="onClickSubtitle" | 17 | + v-model="selectedDate" |
| 18 | - /> | 18 | + @select="onSelectDay" |
| 19 | - | 19 | + @click-subtitle="onClickSubtitle" |
| 20 | - <div v-if="showProgress" class="text-wrapper"> | 20 | + /> |
| 21 | - <div class="text-header">目标进度</div> | ||
| 22 | - <div style="background-color: #FFF; margin-top: 1rem;"> | ||
| 23 | - <div class="grade-percentage-main"> | ||
| 24 | - <van-row justify="space-between" style="margin: 0.5rem 0; font-size: 0.9rem;"> | ||
| 25 | - <van-col span="12"> | ||
| 26 | - <span>作业目标</span> | ||
| 27 | - </van-col> | ||
| 28 | - <van-col span="12" style="text-align: right;"> | ||
| 29 | - <span style="font-weight: bold;">{{ progress1 }}%</span> | ||
| 30 | - </van-col> | ||
| 31 | - </van-row> | ||
| 32 | - <div style="overflow: hidden;"> | ||
| 33 | - <van-progress :percentage="progress1" color="#4caf50" :show-pivot="false" /> | ||
| 34 | - </div> | ||
| 35 | - </div> | ||
| 36 | - <!-- <div class="class-percentage-main"> | ||
| 37 | - <van-row justify="space-between" style="margin: 0.5rem 0; font-size: 0.9rem;"> | ||
| 38 | - <van-col span="12"> | ||
| 39 | - <span>班级目标</span> | ||
| 40 | - </van-col> | ||
| 41 | - <van-col span="12" style="text-align: right;"> | ||
| 42 | - <span style="font-weight: bold;">{{ progress2 }}%</span> | ||
| 43 | - </van-col> | ||
| 44 | - </van-row> | ||
| 45 | - <van-progress :percentage="progress2" color="#4caf50" :show-pivot="false" /> | ||
| 46 | - </div> --> | ||
| 47 | - <div style="padding: 0.75rem 1rem;"> | ||
| 48 | - <van-image round width="2.8rem" height="2.8rem" :src="item ? item : 'https://cdn.ipadbiz.cn/mlaj/images/icon_1.jpeg'" fit="contain" | ||
| 49 | - v-for="(item, index) in teamAvatars.splice(0, 8)" :key="index" | ||
| 50 | - :style="{ marginLeft: index > 0 ? '-0.5rem' : '', border: '2px solid #eff6ff', background: '#fff' }" /> | ||
| 51 | - </div> | ||
| 52 | - </div> | ||
| 53 | </div> | 21 | </div> |
| 54 | 22 | ||
| 55 | - <div class="text-wrapper"> | 23 | + <!-- 可滚动的内容区域 --> |
| 56 | - <div class="text-header">作业描述</div> | 24 | + <div class="scrollable-content"> |
| 57 | - </div> | 25 | + <div class="text-wrapper"> |
| 58 | - | 26 | + <div class="text-header">作业描述</div> |
| 59 | - <div v-if="!taskDetail.is_finish" class="text-wrapper"> | ||
| 60 | - <div class="text-header">打卡类型</div> | ||
| 61 | - <div class="upload-wrapper"> | ||
| 62 | - <div @click="goToCheckinImagePage" class="upload-boxer"> | ||
| 63 | - <div><van-icon name="photo" size="2.5rem" /></div> | ||
| 64 | - <div style="font-size: 0.85rem;">图文打卡</div> | ||
| 65 | - </div> | ||
| 66 | - <div @click="goToCheckinVideoPage()" class="upload-boxer"> | ||
| 67 | - <div><van-icon name="video" size="2.5rem" /></div> | ||
| 68 | - <div style="font-size: 0.85rem;">视频打卡</div> | ||
| 69 | - </div> | ||
| 70 | - <div @click="goToCheckinAudioPage()" class="upload-boxer"> | ||
| 71 | - <div><van-icon name="music" size="2.5rem" /></div> | ||
| 72 | - <div style="font-size: 0.85rem;">音频打卡</div> | ||
| 73 | - </div> | ||
| 74 | </div> | 27 | </div> |
| 75 | - </div> | ||
| 76 | 28 | ||
| 77 | - <div class="text-wrapper"> | 29 | + <div v-if="showProgress" class="text-wrapper"> |
| 78 | - <div class="text-header">打卡动态</div> | 30 | + <div class="text-header">目标进度</div> |
| 79 | - <van-list | 31 | + <div style="background-color: #FFF; margin-top: 1rem;"> |
| 80 | - v-if="checkinDataList.length" | 32 | + <div class="grade-percentage-main"> |
| 81 | - v-model:loading="loading" | 33 | + <van-row justify="space-between" style="margin: 0.5rem 0; font-size: 0.9rem;"> |
| 82 | - :finished="finished" | 34 | + <van-col span="12"> |
| 83 | - finished-text="没有更多了" | 35 | + <span>作业目标</span> |
| 84 | - @load="onLoad" | ||
| 85 | - class="py-3 space-y-4" | ||
| 86 | - > | ||
| 87 | - <div class="post-card" v-for="post in checkinDataList" :key="post.id"> | ||
| 88 | - <div class="post-header"> | ||
| 89 | - <van-row> | ||
| 90 | - <van-col span="4"> | ||
| 91 | - <van-image round width="2.5rem" height="2.5rem" :src="post.user.avatar || 'https://cdn.ipadbiz.cn/mlaj/images/icon_1.jpeg'" fit="cover" /> | ||
| 92 | </van-col> | 36 | </van-col> |
| 93 | - <van-col span="17"> | 37 | + <van-col span="12" style="text-align: right;"> |
| 94 | - <div class="user-info"> | 38 | + <span style="font-weight: bold;">{{ progress1 }}%</span> |
| 95 | - <div class="username">{{ post.user.name }}</div> | ||
| 96 | - <div class="post-time">{{ post.user.time }}</div> | ||
| 97 | - </div> | ||
| 98 | </van-col> | 39 | </van-col> |
| 99 | - <van-col span="3"> | 40 | + </van-row> |
| 100 | - <div v-if="post.is_my" class="post-menu"> | 41 | + <div style="overflow: hidden;"> |
| 101 | - <van-icon name="edit" @click="editCheckin(post)" /> | 42 | + <van-progress :percentage="progress1" color="#4caf50" :show-pivot="false" /> |
| 102 | - <van-icon name="delete-o" @click="delCheckin(post)" /> | 43 | + </div> |
| 103 | - </div> | 44 | + </div> |
| 45 | + <!-- <div class="class-percentage-main"> | ||
| 46 | + <van-row justify="space-between" style="margin: 0.5rem 0; font-size: 0.9rem;"> | ||
| 47 | + <van-col span="12"> | ||
| 48 | + <span>班级目标</span> | ||
| 49 | + </van-col> | ||
| 50 | + <van-col span="12" style="text-align: right;"> | ||
| 51 | + <span style="font-weight: bold;">{{ progress2 }}%</span> | ||
| 104 | </van-col> | 52 | </van-col> |
| 105 | </van-row> | 53 | </van-row> |
| 54 | + <van-progress :percentage="progress2" color="#4caf50" :show-pivot="false" /> | ||
| 55 | + </div> --> | ||
| 56 | + <div style="padding: 0.75rem 1rem;"> | ||
| 57 | + <van-image round width="2.8rem" height="2.8rem" :src="item ? item : 'https://cdn.ipadbiz.cn/mlaj/images/icon_1.jpeg'" fit="contain" | ||
| 58 | + v-for="(item, index) in teamAvatars.splice(0, 8)" :key="index" | ||
| 59 | + :style="{ marginLeft: index > 0 ? '-0.5rem' : '', border: '2px solid #eff6ff', background: '#fff' }" /> | ||
| 106 | </div> | 60 | </div> |
| 107 | - <div class="post-content"> | 61 | + </div> |
| 108 | - <div class="post-text">{{ post.content }}</div> | 62 | + </div> |
| 109 | - <div class="post-media"> | 63 | + |
| 110 | - <div v-if="post.images.length" class="post-images"> | 64 | + <div v-if="!taskDetail.is_finish" class="text-wrapper"> |
| 111 | - <van-image width="30%" fit="cover" v-for="(image, index) in post.images" :key="index" :src="image" radius="5" | 65 | + <div class="text-header">打卡类型</div> |
| 112 | - @click="openImagePreview(index, post)" /> | 66 | + <div class="upload-wrapper"> |
| 113 | - </div> | 67 | + <div @click="goToCheckinImagePage" class="upload-boxer"> |
| 114 | - <van-image-preview v-if="currentPost" v-model:show="showImagePreview" :images="currentPost.images" :start-position="startPosition" :show-index="true" @change="onChange" /> | 68 | + <div><van-icon name="photo" size="2.5rem" /></div> |
| 115 | - <div v-for="(v, idx) in post.videoList" :key="idx"> | 69 | + <div style="font-size: 0.85rem;">图文打卡</div> |
| 116 | - <!-- 视频封面和播放按钮 --> | 70 | + </div> |
| 117 | - <div v-if="v.video && !v.isPlaying" class="relative w-full rounded-lg overflow-hidden" style="aspect-ratio: 16/9; margin-bottom: 1rem;"> | 71 | + <div @click="goToCheckinVideoPage()" class="upload-boxer"> |
| 118 | - <img :src="v.videoCover || 'https://cdn.ipadbiz.cn/mlaj/images/cover_video_2.png'" | 72 | + <div><van-icon name="video" size="2.5rem" /></div> |
| 119 | - :alt="v.content" class="w-full h-full object-cover" /> | 73 | + <div style="font-size: 0.85rem;">视频打卡</div> |
| 120 | - <div class="absolute inset-0 flex items-center justify-center cursor-pointer bg-black/20" | 74 | + </div> |
| 121 | - @click="startPlay(v)"> | 75 | + <div @click="goToCheckinAudioPage()" class="upload-boxer"> |
| 122 | - <div | 76 | + <div><van-icon name="music" size="2.5rem" /></div> |
| 123 | - class="w-16 h-16 rounded-full bg-black/50 flex items-center justify-center hover:bg-black/70 transition-colors"> | 77 | + <div style="font-size: 0.85rem;">音频打卡</div> |
| 124 | - <van-icon name="play-circle-o" class="text-white" size="40" /> | 78 | + </div> |
| 79 | + </div> | ||
| 80 | + </div> | ||
| 81 | + | ||
| 82 | + <div class="text-wrapper"> | ||
| 83 | + <div class="text-header">打卡动态</div> | ||
| 84 | + <van-list | ||
| 85 | + v-if="checkinDataList.length" | ||
| 86 | + v-model:loading="loading" | ||
| 87 | + :finished="finished" | ||
| 88 | + finished-text="没有更多了" | ||
| 89 | + @load="onLoad" | ||
| 90 | + class="py-3 space-y-4" | ||
| 91 | + > | ||
| 92 | + <div class="post-card" v-for="post in checkinDataList" :key="post.id"> | ||
| 93 | + <div class="post-header"> | ||
| 94 | + <van-row> | ||
| 95 | + <van-col span="4"> | ||
| 96 | + <van-image round width="2.5rem" height="2.5rem" :src="post.user.avatar || 'https://cdn.ipadbiz.cn/mlaj/images/icon_1.jpeg'" fit="cover" /> | ||
| 97 | + </van-col> | ||
| 98 | + <van-col span="17"> | ||
| 99 | + <div class="user-info"> | ||
| 100 | + <div class="username">{{ post.user.name }}</div> | ||
| 101 | + <div class="post-time">{{ post.user.time }}</div> | ||
| 102 | + </div> | ||
| 103 | + </van-col> | ||
| 104 | + <van-col span="3"> | ||
| 105 | + <div v-if="post.is_my" class="post-menu"> | ||
| 106 | + <van-icon name="edit" @click="editCheckin(post)" /> | ||
| 107 | + <van-icon name="delete-o" @click="delCheckin(post)" /> | ||
| 108 | + </div> | ||
| 109 | + </van-col> | ||
| 110 | + </van-row> | ||
| 111 | + </div> | ||
| 112 | + <div class="post-content"> | ||
| 113 | + <div class="post-text">{{ post.content }}</div> | ||
| 114 | + <div class="post-media"> | ||
| 115 | + <div v-if="post.images.length" class="post-images"> | ||
| 116 | + <van-image width="30%" fit="cover" v-for="(image, index) in post.images" :key="index" :src="image" radius="5" | ||
| 117 | + @click="openImagePreview(index, post)" /> | ||
| 118 | + </div> | ||
| 119 | + <van-image-preview v-if="currentPost" v-model:show="showImagePreview" :images="currentPost.images" :start-position="startPosition" :show-index="true" @change="onChange" /> | ||
| 120 | + <div v-for="(v, idx) in post.videoList" :key="idx"> | ||
| 121 | + <!-- 视频封面和播放按钮 --> | ||
| 122 | + <div v-if="v.video && !v.isPlaying" class="relative w-full rounded-lg overflow-hidden" style="aspect-ratio: 16/9; margin-bottom: 1rem;"> | ||
| 123 | + <img :src="v.videoCover || 'https://cdn.ipadbiz.cn/mlaj/images/cover_video_2.png'" | ||
| 124 | + :alt="v.content" class="w-full h-full object-cover" /> | ||
| 125 | + <div class="absolute inset-0 flex items-center justify-center cursor-pointer bg-black/20" | ||
| 126 | + @click="startPlay(v)"> | ||
| 127 | + <div | ||
| 128 | + class="w-16 h-16 rounded-full bg-black/50 flex items-center justify-center hover:bg-black/70 transition-colors"> | ||
| 129 | + <van-icon name="play-circle-o" class="text-white" size="40" /> | ||
| 130 | + </div> | ||
| 125 | </div> | 131 | </div> |
| 126 | </div> | 132 | </div> |
| 133 | + <!-- 视频播放器 --> | ||
| 134 | + <VideoPlayer v-if="v.video && v.isPlaying" :video-url="v.video" class="post-video rounded-lg overflow-hidden" | ||
| 135 | + :ref="el => { | ||
| 136 | + if(el) { | ||
| 137 | + // 确保不重复添加 | ||
| 138 | + if (!videoPlayers?.includes(el)) { | ||
| 139 | + videoPlayers?.push(el); | ||
| 140 | + } | ||
| 141 | + } | ||
| 142 | + }" | ||
| 143 | + @onPlay="handleVideoPlay(player, post)" | ||
| 144 | + @onPause="handleVideoPause(post)" /> | ||
| 127 | </div> | 145 | </div> |
| 128 | - <!-- 视频播放器 --> | 146 | + <AudioPlayer |
| 129 | - <VideoPlayer v-if="v.video && v.isPlaying" :video-url="v.video" class="post-video rounded-lg overflow-hidden" | 147 | + v-if="post.audio.length" |
| 148 | + :songs="post.audio" | ||
| 149 | + class="post-audio" | ||
| 150 | + :id="post.id" | ||
| 130 | :ref="el => { | 151 | :ref="el => { |
| 131 | if(el) { | 152 | if(el) { |
| 132 | // 确保不重复添加 | 153 | // 确保不重复添加 |
| 133 | - if (!videoPlayers?.includes(el)) { | 154 | + if (!audioPlayers?.includes(el)) { |
| 134 | - videoPlayers?.push(el); | 155 | + audioPlayers?.push(el); |
| 135 | } | 156 | } |
| 136 | } | 157 | } |
| 137 | }" | 158 | }" |
| 138 | - @onPlay="handleVideoPlay(player, post)" | 159 | + @play="(player) => handleAudioPlay(player, post)" |
| 139 | - @onPause="handleVideoPause(post)" /> | 160 | + /> |
| 140 | </div> | 161 | </div> |
| 141 | - <AudioPlayer | 162 | + </div> |
| 142 | - v-if="post.audio.length" | 163 | + <div class="post-footer"> |
| 143 | - :songs="post.audio" | 164 | + <van-icon @click="handLike(post)"name="good-job" class="like-icon" :color="post.is_liked ? 'red' : ''" /> |
| 144 | - class="post-audio" | 165 | + <span class="like-count">{{ post.likes }}</span> |
| 145 | - :id="post.id" | ||
| 146 | - :ref="el => { | ||
| 147 | - if(el) { | ||
| 148 | - // 确保不重复添加 | ||
| 149 | - if (!audioPlayers?.includes(el)) { | ||
| 150 | - audioPlayers?.push(el); | ||
| 151 | - } | ||
| 152 | - } | ||
| 153 | - }" | ||
| 154 | - @play="(player) => handleAudioPlay(player, post)" | ||
| 155 | - /> | ||
| 156 | </div> | 166 | </div> |
| 157 | </div> | 167 | </div> |
| 158 | - <div class="post-footer"> | 168 | + </van-list> |
| 159 | - <van-icon @click="handLike(post)"name="good-job" class="like-icon" :color="post.is_liked ? 'red' : ''" /> | 169 | + <van-empty v-else description="暂无数据" /> |
| 160 | - <span class="like-count">{{ post.likes }}</span> | 170 | + <van-back-top right="5vw" bottom="10vh" /> |
| 161 | - </div> | 171 | + </div> |
| 162 | - </div> | ||
| 163 | - </van-list> | ||
| 164 | - <van-empty v-else description="暂无数据" /> | ||
| 165 | - <van-back-top right="5vw" bottom="10vh" /> | ||
| 166 | - </div> | ||
| 167 | 172 | ||
| 168 | - <div style="height: 5rem;"></div> | 173 | + <div style="height: 5rem;"></div> |
| 174 | + </div> <!-- 闭合 scrollable-content --> | ||
| 169 | </van-config-provider> | 175 | </van-config-provider> |
| 170 | 176 | ||
| 171 | <van-dialog v-model:show="dialog_show" title="标题" show-cancel-button></van-dialog> | 177 | <van-dialog v-model:show="dialog_show" title="标题" show-cancel-button></van-dialog> |
| ... | @@ -196,52 +202,29 @@ const myRefCalendar = ref(null); | ... | @@ -196,52 +202,29 @@ const myRefCalendar = ref(null); |
| 196 | const windowHeight = ref(window.innerHeight); | 202 | const windowHeight = ref(window.innerHeight); |
| 197 | const windowWidth = ref(window.innerWidth); | 203 | const windowWidth = ref(window.innerWidth); |
| 198 | 204 | ||
| 205 | +// 日历高度相关的响应式数据 | ||
| 206 | +const calendarRef = ref(null); | ||
| 207 | +const calendarHeight = ref(200); // 默认高度 | ||
| 208 | + | ||
| 199 | /** | 209 | /** |
| 200 | - * 动态计算日历高度 | 210 | + * 动态获取日历组件的实际高度 |
| 201 | - * 根据屏幕尺寸和设备类型自适应调整 | ||
| 202 | */ | 211 | */ |
| 203 | -const calendarHeight = computed(() => { | 212 | +const updateCalendarHeight = async () => { |
| 204 | - // 获取可视窗口高度 | 213 | + await nextTick(); |
| 205 | - const viewportHeight = windowHeight.value; | 214 | + if (calendarRef.value) { |
| 206 | - | 215 | + const rect = calendarRef.value.$el.getBoundingClientRect(); |
| 207 | - // 预留给其他内容的空间(头部、底部等) | 216 | + calendarHeight.value = rect.height; |
| 208 | - const reservedSpace = 200; // 可根据实际需要调整 | 217 | + } |
| 209 | - | 218 | +}; |
| 210 | - // 计算可用高度 | ||
| 211 | - const availableHeight = viewportHeight - reservedSpace; | ||
| 212 | - | ||
| 213 | - // 设置最小和最大高度限制 | ||
| 214 | - const minHeight = 300; // 最小高度 | ||
| 215 | - const maxHeight = 500; // 最大高度 | ||
| 216 | - | ||
| 217 | - // 根据屏幕宽度调整高度比例 | ||
| 218 | - let heightRatio = 0.6; // 默认占可用高度的55% | ||
| 219 | - | ||
| 220 | - if (windowWidth.value < 375) { | ||
| 221 | - // 小屏手机 | ||
| 222 | - heightRatio = 0.95; | ||
| 223 | - } else if (windowWidth.value < 414) { | ||
| 224 | - // 中等屏幕手机 | ||
| 225 | - heightRatio = 0.95; | ||
| 226 | - } else if (windowWidth.value >= 768) { | ||
| 227 | - // 平板或更大屏幕 | ||
| 228 | - heightRatio = 0.95; | ||
| 229 | - } | ||
| 230 | - | ||
| 231 | - const calculatedHeight = Math.floor(availableHeight * heightRatio); | ||
| 232 | - | ||
| 233 | - // 确保高度在合理范围内 | ||
| 234 | - const finalHeight = Math.max(minHeight, Math.min(maxHeight, calculatedHeight)); | ||
| 235 | - | ||
| 236 | - return `${finalHeight}px`; | ||
| 237 | -}); | ||
| 238 | 219 | ||
| 239 | /** | 220 | /** |
| 240 | * 监听窗口尺寸变化 | 221 | * 监听窗口尺寸变化 |
| 241 | */ | 222 | */ |
| 242 | const handleResize = () => { | 223 | const handleResize = () => { |
| 243 | - windowHeight.value = window.innerHeight; | 224 | + windowHeight.value = window.innerHeight; |
| 244 | - windowWidth.value = window.innerWidth; | 225 | + windowWidth.value = window.innerWidth; |
| 226 | + // 重新计算日历高度 | ||
| 227 | + updateCalendarHeight(); | ||
| 245 | }; | 228 | }; |
| 246 | 229 | ||
| 247 | // 组件挂载时添加事件监听 | 230 | // 组件挂载时添加事件监听 |
| ... | @@ -252,6 +235,9 @@ onMounted(() => { | ... | @@ -252,6 +235,9 @@ onMounted(() => { |
| 252 | // 延迟更新,等待方向变化完成 | 235 | // 延迟更新,等待方向变化完成 |
| 253 | setTimeout(handleResize, 100); | 236 | setTimeout(handleResize, 100); |
| 254 | }); | 237 | }); |
| 238 | + | ||
| 239 | + // 初始化时计算日历高度 | ||
| 240 | + updateCalendarHeight(); | ||
| 255 | }); | 241 | }); |
| 256 | 242 | ||
| 257 | // 存储所有视频播放器的引用 | 243 | // 存储所有视频播放器的引用 |
| ... | @@ -731,6 +717,25 @@ const formatData = (data) => { | ... | @@ -731,6 +717,25 @@ const formatData = (data) => { |
| 731 | </script> | 717 | </script> |
| 732 | 718 | ||
| 733 | <style lang="less"> | 719 | <style lang="less"> |
| 720 | +// 固定日历样式 | ||
| 721 | +.fixed-calendar { | ||
| 722 | + position: fixed; | ||
| 723 | + top: 0; | ||
| 724 | + left: 0; | ||
| 725 | + right: 0; | ||
| 726 | + z-index: 1000; | ||
| 727 | + background: linear-gradient(to bottom right, #f0fdf4, #f0fdfa, #eff6ff); // 与AppLayout保持一致的渐变背景 | ||
| 728 | + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); | ||
| 729 | +} | ||
| 730 | + | ||
| 731 | +// 可滚动内容区域样式 | ||
| 732 | +.scrollable-content { | ||
| 733 | + margin-top: v-bind('calendarHeight + "px"'); // 动态计算日历高度 | ||
| 734 | + padding-top: 1rem; | ||
| 735 | + height: v-bind('"calc(100vh - " + calendarHeight + "px)"'); // 动态计算剩余高度 | ||
| 736 | + overflow-y: auto; | ||
| 737 | +} | ||
| 738 | + | ||
| 734 | .van-back-top { | 739 | .van-back-top { |
| 735 | background-color: #4caf50; | 740 | background-color: #4caf50; |
| 736 | } | 741 | } | ... | ... |
-
Please register or login to post a comment