hookehuyr

refactor(页面布局): 重构打卡页面布局为固定日历和可滚动内容区域

将日历组件改为固定定位,内容区域改为可滚动布局
动态计算日历高度并设置内容区域margin-top
移除日历背景样式以保持整体设计一致
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 + <!-- 固定的日历组件 -->
12 + <div class="fixed-calendar">
11 <CollapsibleCalendar 13 <CollapsibleCalendar
12 - ref="myRefCalendar" 14 + ref="calendarRef"
13 :title="taskDetail.title" 15 :title="taskDetail.title"
14 :formatter="formatter" 16 :formatter="formatter"
15 v-model="selectedDate" 17 v-model="selectedDate"
16 @select="onSelectDay" 18 @select="onSelectDay"
17 @click-subtitle="onClickSubtitle" 19 @click-subtitle="onClickSubtitle"
18 /> 20 />
21 + </div>
22 +
23 + <!-- 可滚动的内容区域 -->
24 + <div class="scrollable-content">
25 + <div class="text-wrapper">
26 + <div class="text-header">作业描述</div>
27 + </div>
19 28
20 <div v-if="showProgress" class="text-wrapper"> 29 <div v-if="showProgress" class="text-wrapper">
21 <div class="text-header">目标进度</div> 30 <div class="text-header">目标进度</div>
...@@ -52,10 +61,6 @@ ...@@ -52,10 +61,6 @@
52 </div> 61 </div>
53 </div> 62 </div>
54 63
55 - <div class="text-wrapper">
56 - <div class="text-header">作业描述</div>
57 - </div>
58 -
59 <div v-if="!taskDetail.is_finish" class="text-wrapper"> 64 <div v-if="!taskDetail.is_finish" class="text-wrapper">
60 <div class="text-header">打卡类型</div> 65 <div class="text-header">打卡类型</div>
61 <div class="upload-wrapper"> 66 <div class="upload-wrapper">
...@@ -166,6 +171,7 @@ ...@@ -166,6 +171,7 @@
166 </div> 171 </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,45 +202,20 @@ const myRefCalendar = ref(null); ...@@ -196,45 +202,20 @@ 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; // 可根据实际需要调整
209 -
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 } 217 }
230 - 218 +};
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 * 监听窗口尺寸变化
...@@ -242,6 +223,8 @@ const calendarHeight = computed(() => { ...@@ -242,6 +223,8 @@ const calendarHeight = computed(() => {
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 }
......