remove AppPullDownRefresh.vue

This commit is contained in:
Timi
2026-09-21 13:05:37 +08:00
parent 4e860800a7
commit f0c2f70968
35 changed files with 73 additions and 216 deletions
-152
View File
@@ -1,152 +0,0 @@
<template>
<t-pull-down-refresh
ref="rootRef"
class="app-pull-down-refresh"
v-bind="forwardedAttrs"
@touchstart.capture="guardTouch"
@touchmove.capture="guardTouch"
@touchend.capture="guardTouch"
@touchcancel.capture="guardTouch"
>
<slot />
</t-pull-down-refresh>
</template>
<script setup lang="ts">
import type { ComponentPublicInstance } from "vue";
defineOptions({
name: "AppPullDownRefresh",
inheritAttrs: false
});
type EventListener = (...args: unknown[]) => unknown;
type ScrollTarget = HTMLElement | Window;
const scrollToLowerThreshold = 20;
const attrs = useAttrs();
const rootRef = ref<ComponentPublicInstance | null>(null);
const forwardedAttrs = computed(() => Object.fromEntries(
Object.entries(attrs).filter(([key]) => key !== "onScrolltolower")
));
let rootElement: HTMLElement | null = null;
let scrollFrame = 0;
let isScrollListenerBound = false;
function isScrollable(element: HTMLElement): boolean {
const overflowY = window.getComputedStyle(element).overflowY;
return /auto|scroll/i.test(overflowY) && element.clientHeight < element.scrollHeight;
}
function getScrollParents(target: EventTarget | null): HTMLElement[] {
let current = target instanceof HTMLElement
? target
: target instanceof Element ? target.parentElement : null;
const parents: HTMLElement[] = [];
while (current) {
if (isScrollable(current)) {
parents.push(current);
}
current = current.parentElement;
}
return parents;
}
function getWindowScrollTop(): number {
return window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop;
}
function isAtTop(target: EventTarget | null): boolean {
if (getScrollParents(target).some(parent => 0 < parent.scrollTop)) {
return false;
}
return getWindowScrollTop() < 1;
}
function guardTouch(event: TouchEvent): void {
if (isAtTop(event.target)) {
return;
}
event.stopImmediatePropagation();
}
function getScrollTarget(event: Event): ScrollTarget {
return getScrollParents(event.target)[0] || window;
}
function isReachBottom(target: ScrollTarget): boolean {
if (target === window) {
const documentElement = document.documentElement;
const scrollHeight = Math.max(documentElement.scrollHeight, document.body.scrollHeight);
const clientHeight = window.innerHeight || documentElement.clientHeight;
return clientHeight < scrollHeight && scrollHeight - scrollToLowerThreshold < getWindowScrollTop() + clientHeight;
}
if (!(target instanceof HTMLElement)) {
return false;
}
return target.clientHeight < target.scrollHeight
&& target.scrollHeight - scrollToLowerThreshold < target.scrollTop + target.clientHeight;
}
function invokeListener(listener: unknown): void {
if (Array.isArray(listener)) {
for (const item of listener) {
invokeListener(item);
}
return;
}
if (typeof listener === "function") {
(listener as EventListener)();
}
}
function handleScroll(event: Event): void {
const target = getScrollTarget(event);
if (scrollFrame || !isReachBottom(target)) {
return;
}
scrollFrame = requestAnimationFrame(() => {
scrollFrame = 0;
if (isReachBottom(target)) {
invokeListener(attrs.onScrolltolower);
}
});
}
function bindScrollListeners(): void {
if (isScrollListenerBound) {
return;
}
const element = rootRef.value?.$el;
if (!(element instanceof HTMLElement)) {
return;
}
rootElement = element;
rootElement.addEventListener("scroll", handleScroll, true);
window.addEventListener("scroll", handleScroll, { passive: true });
isScrollListenerBound = true;
}
function unbindScrollListeners(): void {
if (!isScrollListenerBound) {
return;
}
rootElement?.removeEventListener("scroll", handleScroll, true);
window.removeEventListener("scroll", handleScroll);
isScrollListenerBound = false;
if (scrollFrame) {
cancelAnimationFrame(scrollFrame);
scrollFrame = 0;
}
}
onMounted(bindScrollListeners);
onActivated(bindScrollListeners);
onDeactivated(unbindScrollListeners);
onUnmounted(unbindScrollListeners);
</script>
+2 -2
View File
@@ -38,7 +38,7 @@
@status-change="handleScanStatusChange"
/>
</div>
<app-pull-down-refresh
<t-pull-down-refresh
class="result-list"
v-model="isRefreshing"
:refresh-timeout="30000"
@@ -52,7 +52,7 @@
:empty-text="loading ? '正在加载客户' : '未找到匹配客户'"
@select="toggleCustomer"
/>
</app-pull-down-refresh>
</t-pull-down-refresh>
</div>
</bottom-popup>
</template>
@@ -237,8 +237,17 @@ function confirm(): void {
<style scoped lang="less">
:global(.bottom-popup:has(.filter-popup)) {
display: flex;
flex-direction: column;
max-height: 86vh;
overflow: hidden;
}
:global(.bottom-popup:has(.filter-popup) .body) {
min-height: 0;
overflow-y: auto;
touch-action: pan-y;
-webkit-overflow-scrolling: touch;
}
.filter-popup {