smooth exist bug
This commit is contained in:
parent
0ff56a83d4
commit
ea139100e6
|
|
@ -2,7 +2,7 @@
|
|||
<!-- 顶部Tabs栏 -->
|
||||
<uv-tabs :list="topTabs" @click="clickTab"></uv-tabs>
|
||||
<!-- 内容区域 -->
|
||||
<view class="content-wrapper" >
|
||||
<view class="content-wrapper">
|
||||
<view>
|
||||
<uv-calendar ref="calendar" mode="single" @confirm="handleConfirm" ></uv-calendar>
|
||||
<button @click="openCalendar">选择日期</button>
|
||||
|
|
@ -10,8 +10,31 @@
|
|||
当前选择日期:{{ selectedDate }},事件数:{{ eventsInDay.length }}
|
||||
</view>
|
||||
</view>
|
||||
<!-- 时间轴表格 -->
|
||||
<TimeTable :hours="hours" :events="eventsInDay" />
|
||||
<!-- 滑动容器 -->
|
||||
<view
|
||||
class="swipe-container"
|
||||
@touchstart="handleTouchStart"
|
||||
@touchmove="handleTouchMove"
|
||||
@touchend="handleTouchEnd"
|
||||
>
|
||||
<view
|
||||
class="swipe-wrapper"
|
||||
:style="{ transform: `translateX(${translateX}px)`, transition: isAnimating ? 'transform 0.3s ease-out' : 'none' }"
|
||||
>
|
||||
<!-- 昨天的表格 -->
|
||||
<view class="table-item">
|
||||
<TimeTable :hours="hours" :events="prevDayEvents" />
|
||||
</view>
|
||||
<!-- 今天的表格 -->
|
||||
<view class="table-item">
|
||||
<TimeTable :hours="hours" :events="eventsInDay" />
|
||||
</view>
|
||||
<!-- 明天的表格 -->
|
||||
<view class="table-item">
|
||||
<TimeTable :hours="hours" :events="nextDayEvents" />
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 悬浮新建按钮 -->
|
||||
|
|
@ -31,7 +54,7 @@
|
|||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, computed, watch } from 'vue';
|
||||
import { ref, computed, watch, onMounted } from 'vue';
|
||||
|
||||
import TimeTable from '@/components/TimeTable.vue';
|
||||
import FabPlus from '@/components/FabPlus.vue';
|
||||
|
|
@ -68,12 +91,10 @@ yesterday.setDate(yesterday.getDate() - 1);
|
|||
const yesterdayStr = yesterday.toISOString().slice(0, 10);
|
||||
|
||||
const allEvents = ref([
|
||||
{id:1,title:'今天的日程1',startHour:15,startMin:30,color:'#e3fae6',date:today},
|
||||
{id:2,title:'今天的日程2',startHour:16,startMin:0,color:'#fae1e1',date:today},
|
||||
{id:3,title:'今天的日程3',startHour:23,startMin:0,color:'#e3fae6',date:today},
|
||||
{id:4,title:'明天的日程1',startHour:9,startMin:0,color:'#e3fae6',date:tomorrowStr},
|
||||
{id:5,title:'明天的日程2',startHour:14,startMin:30,color:'#fae1e1',date:tomorrowStr},
|
||||
{id:6,title:'昨天的日程',startHour:10,startMin:0,color:'#e3fae6',date:yesterdayStr},
|
||||
{id:1,title:'今天的日程1',startHour:10,startMin:30,color:'#e3fae6',date:today},
|
||||
|
||||
{id:5,title:'明天的日程2',startHour:10,startMin:30,color:'#fae1e1',date:tomorrowStr},
|
||||
{id:6,title:'昨天的日程3',startHour:10,startMin:30,color:'#e3fae6',date:yesterdayStr},
|
||||
]);
|
||||
|
||||
// 根据当前选择日期过滤
|
||||
|
|
@ -83,6 +104,29 @@ const eventsInDay = computed(() => {
|
|||
return filtered;
|
||||
});
|
||||
|
||||
// 计算相邻日期
|
||||
const prevDate = computed(() => {
|
||||
const date = new Date(selectedDate.value);
|
||||
date.setDate(date.getDate() - 1);
|
||||
return date.toISOString().slice(0, 10);
|
||||
});
|
||||
|
||||
const nextDate = computed(() => {
|
||||
const date = new Date(selectedDate.value);
|
||||
date.setDate(date.getDate() + 1);
|
||||
return date.toISOString().slice(0, 10);
|
||||
});
|
||||
|
||||
// 前一天的事件
|
||||
const prevDayEvents = computed(() => {
|
||||
return allEvents.value.filter(e => e.date === prevDate.value);
|
||||
});
|
||||
|
||||
// 后一天的事件
|
||||
const nextDayEvents = computed(() => {
|
||||
return allEvents.value.filter(e => e.date === nextDate.value);
|
||||
});
|
||||
|
||||
// 监控 selectedDate 的变化
|
||||
watch(selectedDate, (newDate, oldDate) => {
|
||||
console.log('selectedDate 发生变化:', oldDate, '->', newDate);
|
||||
|
|
@ -162,6 +206,167 @@ function addEvent(e) {
|
|||
showAdd.value = false;
|
||||
}
|
||||
const value=ref(0);
|
||||
|
||||
// 滑动相关变量
|
||||
const touchStartX = ref(0);
|
||||
const touchStartY = ref(0);
|
||||
const screenWidth = ref(375); // 屏幕宽度,默认值,会在mounted时更新
|
||||
const translateX = ref(-375); // 当前滑动偏移量,初始值设为 -375(假设屏幕宽度,会在mounted时更新)
|
||||
const baseTranslateX = ref(-375); // 基础偏移量
|
||||
const isAnimating = ref(false); // 是否正在执行动画
|
||||
const isDragging = ref(false); // 是否正在拖动
|
||||
|
||||
// 初始化屏幕宽度
|
||||
const initScreenWidth = () => {
|
||||
uni.getSystemInfo({
|
||||
success: (res) => {
|
||||
const width = res.windowWidth || res.screenWidth || 375;
|
||||
screenWidth.value = width;
|
||||
// 只有在初始值时才更新,避免覆盖用户操作
|
||||
if (translateX.value === -375) {
|
||||
translateX.value = -width;
|
||||
baseTranslateX.value = -width;
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// 触摸开始
|
||||
const handleTouchStart = (e) => {
|
||||
if (isAnimating.value) return;
|
||||
const touch = e.touches[0];
|
||||
touchStartX.value = touch.clientX;
|
||||
touchStartY.value = touch.clientY;
|
||||
isDragging.value = true;
|
||||
baseTranslateX.value = translateX.value; // 保存当前偏移量
|
||||
};
|
||||
|
||||
// 触摸移动
|
||||
const handleTouchMove = (e) => {
|
||||
if (!isDragging.value || isAnimating.value) return;
|
||||
|
||||
const touch = e.touches[0];
|
||||
const deltaX = touch.clientX - touchStartX.value;
|
||||
const deltaY = Math.abs(touch.clientY - touchStartY.value);
|
||||
|
||||
// 如果是水平滑动(水平距离大于垂直距离),阻止页面滚动
|
||||
if (Math.abs(deltaX) > deltaY && Math.abs(deltaX) > 10) {
|
||||
e.preventDefault();
|
||||
}
|
||||
|
||||
// 实时更新偏移量
|
||||
translateX.value = baseTranslateX.value + deltaX;
|
||||
|
||||
// 限制滑动范围(不能超出左右边界)
|
||||
const minTranslate = -screenWidth.value * 2; // 最左边(昨天)
|
||||
const maxTranslate = 0; // 最右边(明天)
|
||||
translateX.value = Math.max(minTranslate, Math.min(maxTranslate, translateX.value));
|
||||
};
|
||||
|
||||
// 触摸结束
|
||||
const handleTouchEnd = (e) => {
|
||||
if (!isDragging.value || isAnimating.value) return;
|
||||
|
||||
const touch = e.changedTouches[0];
|
||||
const deltaX = touch.clientX - touchStartX.value;
|
||||
const deltaY = Math.abs(touch.clientY - touchStartY.value);
|
||||
const minSwipeDistance = screenWidth.value * 0.2; // 最小滑动距离为屏幕宽度的20%
|
||||
|
||||
// 判断是否为有效的水平滑动
|
||||
const isHorizontalSwipe = Math.abs(deltaX) > deltaY && Math.abs(deltaX) > minSwipeDistance;
|
||||
|
||||
isDragging.value = false;
|
||||
|
||||
if (isHorizontalSwipe) {
|
||||
// 滑动距离超过阈值,自动滑动到下一个页面
|
||||
if (deltaX > 0) {
|
||||
// 向右滑动,滑动到前一天的位置
|
||||
// slideToPreviousDay();
|
||||
} else {
|
||||
// 向左滑动,滑动到后一天的位置
|
||||
slideToNextDay();
|
||||
}
|
||||
} else {
|
||||
// 滑动距离不够,回到中间位置
|
||||
resetToCenter();
|
||||
}
|
||||
};
|
||||
|
||||
// 重置到中心位置(今天)
|
||||
const resetToCenter = () => {
|
||||
isAnimating.value = true;
|
||||
translateX.value = -screenWidth.value;
|
||||
|
||||
setTimeout(() => {
|
||||
isAnimating.value = false;
|
||||
}, 1000);
|
||||
};
|
||||
|
||||
// 滑动到前一天的位置(动画完成后更新日期)
|
||||
const slideToPreviousDay = () => {
|
||||
isAnimating.value = true;
|
||||
// 从当前位置继续滑动到前一天的完整位置(-screenWidth * 2)
|
||||
const targetX = -screenWidth.value*2;
|
||||
translateX.value = targetX;
|
||||
|
||||
setTimeout(() => {
|
||||
// 滑动动画完成后,先暂时禁用 transition
|
||||
isAnimating.value = false;
|
||||
|
||||
// 在下一帧更新日期和重置位置(确保没有 transition 动画)
|
||||
setTimeout(() => {
|
||||
// 更新日期
|
||||
const currentDate = new Date(selectedDate.value);
|
||||
currentDate.setDate(currentDate.getDate() - 1);
|
||||
selectedDate.value = currentDate.toISOString().slice(0, 10);
|
||||
|
||||
// 重置到中心位置(此时日期已更新,prev/next 已重新计算,且没有 transition)
|
||||
translateX.value = -screenWidth.value;
|
||||
baseTranslateX.value = -screenWidth.value;
|
||||
|
||||
console.log(`日期切换:上一天,新日期:${selectedDate.value}`);
|
||||
}, 16); // 一帧的时间,确保 transition 已禁用
|
||||
}, 1000);
|
||||
};
|
||||
|
||||
// 滑动到后一天的位置(动画完成后更新日期)
|
||||
const slideToNextDay = () => {
|
||||
isAnimating.value = true;
|
||||
// 从当前位置继续滑动到后一天的完整位置(0)
|
||||
const targetX = 0;
|
||||
translateX.value = targetX;
|
||||
|
||||
setTimeout(() => {
|
||||
// 滑动动画完成后,先暂时禁用 transition
|
||||
isAnimating.value = false;
|
||||
|
||||
// 在下一帧更新日期和重置位置(确保没有 transition 动画)
|
||||
setTimeout(() => {
|
||||
// 更新日期
|
||||
const currentDate = new Date(selectedDate.value);
|
||||
currentDate.setDate(currentDate.getDate() + 1);
|
||||
selectedDate.value = currentDate.toISOString().slice(0, 10);
|
||||
|
||||
// 重置到中心位置(此时日期已更新,prev/next 已重新计算,且没有 transition)
|
||||
translateX.value = -screenWidth.value;
|
||||
baseTranslateX.value = -screenWidth.value;
|
||||
|
||||
console.log(`日期切换:下一天,新日期:${selectedDate.value}`);
|
||||
}, 16); // 一帧的时间,确保 transition 已禁用
|
||||
}, 1000);
|
||||
};
|
||||
|
||||
// 监听日期变化,重置位置
|
||||
watch(selectedDate, () => {
|
||||
if (!isDragging.value && !isAnimating.value) {
|
||||
resetToCenter();
|
||||
}
|
||||
});
|
||||
|
||||
// 组件挂载时初始化
|
||||
onMounted(() => {
|
||||
initScreenWidth();
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
|
@ -186,6 +391,7 @@ const value=ref(0);
|
|||
|
||||
.content-wrapper {
|
||||
min-height: 100vh;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
:deep(.bottom-tabbar) { z-index: 1000 !important; }
|
||||
|
|
@ -193,4 +399,23 @@ const value=ref(0);
|
|||
.schedule-timeline {
|
||||
padding-bottom: 130rpx !important;
|
||||
}
|
||||
|
||||
.swipe-container {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
overflow: hidden;
|
||||
touch-action: pan-y; /* 允许垂直滚动,但控制水平滑动 */
|
||||
}
|
||||
|
||||
.swipe-wrapper {
|
||||
display: flex;
|
||||
width: 300%; /* 三个表格的宽度 */
|
||||
will-change: transform; /* 优化性能 */
|
||||
}
|
||||
|
||||
.table-item {
|
||||
flex: 0 0 33.333%; /* 每个表格占33.333% */
|
||||
width: 33.333%;
|
||||
min-width: 0;
|
||||
}
|
||||
</style>
|
||||
Loading…
Reference in New Issue
Block a user