Toggle navigation
Toggle navigation
This project
Loading...
Sign in
Hooke
/
mlaj
Go to a project
Toggle navigation
Toggle navigation pinning
Projects
Groups
Snippets
Help
Project
Activity
Repository
Pipelines
Graphs
Issues
0
Merge Requests
0
Wiki
Snippets
Network
Create a new issue
Builds
Commits
Issue Boards
Authored by
hookehuyr
2025-12-18 22:34:43 +0800
Browse Files
Options
Browse Files
Download
Email Patches
Plain Diff
Commit
01c115ffb5822e4b76fc856ba6c8754003841dc9
01c115ff
1 parent
4b776157
refactor(日历组件): 优化日历高度计算和滚动隐藏逻辑
使用 ResizeObserver 替代手动计算日历高度 添加滚动时隐藏日历头部的动画效果
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
87 additions
and
20 deletions
src/components/ui/CollapsibleCalendar.vue
src/views/checkin/IndexCheckInPage.vue
src/components/ui/CollapsibleCalendar.vue
View file @
01c115f
<!--
* @Date: 2025-01-25 15:34:17
* @LastEditors: hookehuyr hookehuyr@gmail.com
* @LastEditTime: 2025-12-18 22:
13:17
* @LastEditTime: 2025-12-18 22:
33:09
* @FilePath: /mlaj/src/components/ui/CollapsibleCalendar.vue
* @Description: 可折叠日历组件
-->
<template>
<div class="collapsible-calendar ">
<!-- 折叠状态显示 -->
<div class="calendar-collapsed">
<div class="calendar-collapsed"
:class="{ 'is-compact': isHeaderHidden }"
>
<div class="calendar-header">
<div class="calendar-icon">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
...
...
@@ -29,7 +29,7 @@
<div class="calendar-date-display" @click="expandCalendar">
<div class="calendar-date-main">{{ formattedCurrentDate }}</div>
<div class="calendar-weekday">{{ formattedWeekday }}</div>
<div class="text-xs text-gray-500 mt-1">点击切换日期</div>
<div class="text-xs text-gray-500 mt-1
collapsible-text
">点击切换日期</div>
</div>
<!-- <div class="calendar-action">
<div class="calendar-action-text">指定日期</div>
...
...
@@ -49,7 +49,7 @@
</svg>
</div>
</div>
<div v-if="selectedSubtask" class="text-xs text-gray-500 mt-1 cursor-pointer hover:text-green-600 transition-colors" @click.stop="openRulesPopup">点击查看打卡规则</div>
<div v-if="selectedSubtask" class="text-xs text-gray-500 mt-1 cursor-pointer hover:text-green-600 transition-colors
collapsible-text
" @click.stop="openRulesPopup">点击查看打卡规则</div>
</div>
</div>
</div>
...
...
@@ -119,6 +119,7 @@
<script setup>
import { ref, computed, watch, onMounted } from 'vue'
import { useScroll } from '@vueuse/core'
import dayjs from 'dayjs'
// Props定义
...
...
@@ -155,6 +156,44 @@ const selectedCourseText = ref('全部作业')
const selectedCourseId = ref('')
const showRulesPopup = ref(false)
const { y } = useScroll(window)
const isHeaderHidden = ref(false)
const lastY = ref(0)
watch(y, (newY) => {
// 忽略弹性滚动造成的负值
if (newY < 0) return
// 获取文档高度和窗口高度,用于判断是否触底
const windowHeight = window.innerHeight
const documentHeight = document.documentElement.scrollHeight
const bottomThreshold = 20 // 触底阈值
// 如果接近底部,不执行隐藏逻辑(避免回弹导致的显示)
if (newY + windowHeight >= documentHeight - bottomThreshold) {
// 如果已经在底部,保持之前的状态,或者强制隐藏(根据需求,通常保持当前状态更稳妥,或者强制隐藏因为是在向下浏览)
// 这里选择保持状态,但更新lastY防止下次误判
lastY.value = newY
return
}
// 滚动方向判定
const direction = newY > lastY.value ? 'down' : 'up'
const scrollThreshold = 50 // 滚动阈值
if (newY > scrollThreshold && direction === 'down') {
isHeaderHidden.value = true
} else if (direction === 'up') {
// 只有当向上滚动超过一定距离或者不在底部反弹区域时才显示
// 这里的判断其实已经被上面的触底检测覆盖了一部分,但为了保险,可以加一个最小变动阈值
if (Math.abs(newY - lastY.value) > 5) {
isHeaderHidden.value = false
}
}
lastY.value = newY
})
const courseColumns = computed(() => {
return [
{ text: '全部作业', value: '' },
...
...
@@ -335,11 +374,39 @@ defineExpose({
transition: all 0.1s ease;
}
// 紧凑模式下的样式控制
&.is-compact {
.calendar-header {
max-height: 0;
margin-bottom: 0;
opacity: 0;
pointer-events: none;
}
.collapsible-text {
max-height: 0;
margin-top: 0;
opacity: 0;
overflow: hidden;
}
}
.calendar-header {
display: flex;
align-items: center;
margin-bottom: 16px;
gap: 12px;
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
max-height: 100px;
opacity: 1;
overflow: hidden;
&.is-hidden {
max-height: 0;
margin-bottom: 0;
opacity: 0;
pointer-events: none;
}
.calendar-icon {
display: flex;
...
...
@@ -458,6 +525,12 @@ defineExpose({
}
}
.collapsible-text {
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
max-height: 20px; // 假设文字高度不超过20px
opacity: 1;
}
.calendar-popup-content {
height: 100%;
overflow: hidden;
...
...
src/views/checkin/IndexCheckInPage.vue
View file @
01c115f
...
...
@@ -9,7 +9,7 @@
<AppLayout :hasTitle="false">
<van-config-provider :theme-vars="themeVars">
<!-- 固定的日历组件 -->
<div class="fixed-calendar">
<div class="fixed-calendar"
ref="fixedCalendarWrapper"
>
<CollapsibleCalendar
ref="calendarRef"
:title="taskDetail.title"
...
...
@@ -146,7 +146,7 @@ import FrostedGlass from "@/components/ui/FrostedGlass.vue";
import CollapsibleCalendar from "@/components/ui/CollapsibleCalendar.vue";
import PostCountModel from "@/components/count/postCountModel.vue";
import CheckinCard from "@/components/checkin/CheckinCard.vue";
import { useTitle } from '@vueuse/core';
import { useTitle
, useResizeObserver
} from '@vueuse/core';
import dayjs from 'dayjs';
import { getTaskDetailAPI, getUploadTaskListAPI, delUploadTaskInfoAPI, likeUploadTaskInfoAPI, dislikeUploadTaskInfoAPI } from "@/api/checkin";
...
...
@@ -167,18 +167,17 @@ const windowWidth = ref(window.innerWidth);
// 日历高度相关的响应式数据
const calendarRef = ref(null);
const fixedCalendarWrapper = ref(null);
const calendarHeight = ref(200); // 默认高度
/**
* 动态获取日历组件的实际高度
*/
const updateCalendarHeight = async () => {
await nextTick();
if (calendarRef.value) {
const rect = calendarRef.value.$el.getBoundingClientRect();
calendarHeight.value = rect.height;
// 使用 ResizeObserver 监听日历容器高度变化
useResizeObserver(fixedCalendarWrapper, (entries) => {
const entry = entries[0];
if (entry && entry.target) {
// 使用 getBoundingClientRect 获取包含 padding 和 border 的完整高度
calendarHeight.value = entry.target.getBoundingClientRect().height;
}
};
}
)
;
/**
* 监听窗口尺寸变化
...
...
@@ -186,8 +185,6 @@ const updateCalendarHeight = async () => {
const handleResize = () => {
windowHeight.value = window.innerHeight;
windowWidth.value = window.innerWidth;
// 重新计算日历高度
updateCalendarHeight();
};
// 组件挂载时添加事件监听
...
...
@@ -198,9 +195,6 @@ onMounted(() => {
// 延迟更新,等待方向变化完成
setTimeout(handleResize, 100);
});
// 初始化时计算日历高度
updateCalendarHeight();
});
// CheckinCard refs
...
...
Please
register
or
login
to post a comment