666ghj commited on
Commit
d6672eb
·
1 Parent(s): 023053b

refactor(HistoryDatabase): enhance card expansion logic with pending state management

Browse files

- Introduced a pending state to track the target expansion state during animations.
- Improved debounce handling to ensure smoother transitions and prevent rapid state changes.
- Updated logic to check for new pending states after animations complete, enhancing responsiveness and stability.

frontend/src/components/HistoryDatabase.vue CHANGED
@@ -106,6 +106,7 @@ const historyContainer = ref(null)
106
  let observer = null
107
  let isAnimating = false // 动画锁,防止闪烁
108
  let expandDebounceTimer = null // 防抖定时器
 
109
 
110
  // 卡片布局配置 - 调整为更宽的比例
111
  const CARDS_PER_ROW = 4
@@ -316,35 +317,60 @@ onMounted(() => {
316
  observer = new IntersectionObserver(
317
  (entries) => {
318
  entries.forEach((entry) => {
319
- // 如果正在动画中,忽略新的触发
320
- if (isAnimating) return
321
-
322
  const shouldExpand = entry.isIntersecting
323
 
324
- // 如果状态没有变化,不做任何处理
325
- if (shouldExpand === isExpanded.value) return
326
 
327
- // 清除之前的防抖定时器
328
  if (expandDebounceTimer) {
329
  clearTimeout(expandDebounceTimer)
330
  expandDebounceTimer = null
331
  }
332
 
 
 
 
 
 
 
 
 
 
333
  // 使用防抖延迟状态切换,防止快速闪烁
334
  // 展开时延迟较短(50ms),收起时延迟较长(200ms)以增加稳定性
335
  const delay = shouldExpand ? 50 : 200
336
 
337
  expandDebounceTimer = setTimeout(() => {
338
- // 再次检查是否正在动画
339
  if (isAnimating) return
340
 
 
 
 
341
  // 设置动画锁
342
  isAnimating = true
343
- isExpanded.value = shouldExpand
 
344
 
345
- // 动画完成后解除锁定(700ms 动画时长)
346
  setTimeout(() => {
347
  isAnimating = false
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
348
  }, 750)
349
  }, delay)
350
  })
 
106
  let observer = null
107
  let isAnimating = false // 动画锁,防止闪烁
108
  let expandDebounceTimer = null // 防抖定时器
109
+ let pendingState = null // 记录待执行的目标状态
110
 
111
  // 卡片布局配置 - 调整为更宽的比例
112
  const CARDS_PER_ROW = 4
 
317
  observer = new IntersectionObserver(
318
  (entries) => {
319
  entries.forEach((entry) => {
 
 
 
320
  const shouldExpand = entry.isIntersecting
321
 
322
+ // 更新待执行的目标状态(无论是否在动画中都要记录最新的目标状态)
323
+ pendingState = shouldExpand
324
 
325
+ // 清除之前的防抖定时器(新的滚动意图会覆盖旧的)
326
  if (expandDebounceTimer) {
327
  clearTimeout(expandDebounceTimer)
328
  expandDebounceTimer = null
329
  }
330
 
331
+ // 如果正在动画中,只记录状态,等动画结束后处理
332
+ if (isAnimating) return
333
+
334
+ // 如果目标状态与当前状态相同,不需要处理
335
+ if (shouldExpand === isExpanded.value) {
336
+ pendingState = null
337
+ return
338
+ }
339
+
340
  // 使用防抖延迟状态切换,防止快速闪烁
341
  // 展开时延迟较短(50ms),收起时延迟较长(200ms)以增加稳定性
342
  const delay = shouldExpand ? 50 : 200
343
 
344
  expandDebounceTimer = setTimeout(() => {
345
+ // 检查是否正在动画
346
  if (isAnimating) return
347
 
348
+ // 检查待执行状态是否仍需要执行(可能已被后续滚动覆盖)
349
+ if (pendingState === null || pendingState === isExpanded.value) return
350
+
351
  // 设置动画锁
352
  isAnimating = true
353
+ isExpanded.value = pendingState
354
+ pendingState = null
355
 
356
+ // 动画完成后解除锁定,并检查否有待处理的状态变化
357
  setTimeout(() => {
358
  isAnimating = false
359
+
360
+ // 动画结束后,检查是否有新的待执行状态
361
+ if (pendingState !== null && pendingState !== isExpanded.value) {
362
+ // 延迟一小段时间再执行,避免太快切换
363
+ expandDebounceTimer = setTimeout(() => {
364
+ if (pendingState !== null && pendingState !== isExpanded.value) {
365
+ isAnimating = true
366
+ isExpanded.value = pendingState
367
+ pendingState = null
368
+ setTimeout(() => {
369
+ isAnimating = false
370
+ }, 750)
371
+ }
372
+ }, 100)
373
+ }
374
  }, 750)
375
  }, delay)
376
  })