update list load

This commit is contained in:
Timi
2026-09-09 22:57:57 +08:00
parent 8e77b114f9
commit 5991cbc1d4
+56 -69
View File
@@ -8,29 +8,28 @@
@right-button-click="confirmSelection"
>
<div class="customer-selector">
<div class="search-wrapper">
<div class="search-row">
<t-input
v-model.trim="keyword"
class="search"
borderless
clearable
placeholder="搜索编码、姓名(拼音)、电话"
/>
<t-button
v-if="props.enableScan"
class="scan-button"
theme="primary"
@click="toggleScanner"
>
<template #icon>
<t-icon name="scan" />
</template>
<span v-text="scannerVisible ? '关闭扫码' : '扫码'" />
</t-button>
</div>
<div class="search-wrap">
<t-input
v-model.trim="keyword"
class="search"
borderless
clearable
placeholder="搜索编码、姓名(拼音)、电话"
/>
<t-button
v-if="props.enableScan"
class="scan"
size="small"
theme="primary"
@click="toggleScanner"
>
<template #icon>
<t-icon name="scan" />
</template>
<span v-text="scannerVisible ? '关闭扫码' : '扫码'" />
</t-button>
</div>
<div v-if="scannerVisible" class="scanner-wrapper">
<div v-if="scannerVisible" class="scanner-wrap">
<code-scanner
:visible="scannerVisible"
:status-text="scanStatus"
@@ -39,7 +38,13 @@
@status-change="handleScanStatusChange"
/>
</div>
<div ref="resultListRef" class="result-list">
<t-pull-down-refresh
class="result-list"
v-model="isRefreshing"
:refresh-timeout="30000"
@refresh="refresh"
@scrolltolower="loadCustomers"
>
<customer-list
:customer-list="customerOptions"
:selected-id-list="draftSelectedIdList"
@@ -47,13 +52,13 @@
:empty-text="loading ? '正在加载客户' : '未找到匹配客户'"
@select="toggleCustomer"
/>
</div>
</t-pull-down-refresh>
</div>
</bottom-popup>
</template>
<script setup lang="ts">
import { Scroller } from "timi-web";
import { Toolkit } from "timi-web";
import { BottomPopup } from "timi-tdesign-mobile";
import CustomerAPI from "@/api/CustomerAPI";
import CodeScanner from "@/components/CodeScanner.vue";
@@ -86,18 +91,16 @@ const emit = defineEmits<{
}>();
const pageSize = 20;
const scrollListenerName = "CustomerSelector";
const keyword = ref("");
const loading = ref(false);
const noMore = ref(false);
const pageIndex = ref(0);
const totalCount = ref(0);
const customerOptions = ref<Customer[]>([]);
const resultListRef = ref<HTMLElement>();
const isRefreshing = ref(false);
const draftSelectedIdList = ref<string[]>([]);
const selectedCustomerCache = new Map<string, Customer>();
let searchToken = 0;
let keywordTimer: number | undefined;
const scannerVisible = ref(false);
const scanStatus = ref("点击扫码开始识别");
let latestDecodedText = "";
@@ -122,6 +125,18 @@ async function reloadCustomers(): Promise<void> {
await loadCustomers();
}
async function refresh(): Promise<void> {
try {
await reloadCustomers();
} finally {
isRefreshing.value = false;
}
}
const reloadByKeyword = Toolkit.debounce(async () => {
await reloadCustomers();
}, false);
async function loadCustomers(): Promise<void> {
if (loading.value || noMore.value) {
return;
@@ -161,19 +176,6 @@ async function loadCustomers(): Promise<void> {
}
}
async function bindScrollListener(): Promise<void> {
if (!props.visible || 0 === customerOptions.value.length) {
Scroller.removeListener(scrollListenerName);
return;
}
await nextTick();
Scroller.addBottomListener(scrollListenerName, loadCustomers, {
distance: 48,
canLoad: () => props.visible && !loading.value && !noMore.value,
getElement: () => resultListRef.value
});
}
function getModelValueIdList(): string[] {
const value = props.modelValue;
return (Array.isArray(value) ? value : [value]).filter((item): item is string => Boolean(item));
@@ -283,13 +285,11 @@ watch(() => props.visible, async (value) => {
latestDecodedText = "";
scanToken++;
scanStatus.value = "点击扫码开始识别";
window.clearTimeout(keywordTimer);
Scroller.removeListener(scrollListenerName);
reloadByKeyword.cancel();
return;
}
syncDraftSelection();
await reloadCustomers();
await bindScrollListener();
});
watch(() => props.enableScan, (value) => {
@@ -305,27 +305,17 @@ watch(() => props.storeId, async () => {
return;
}
await reloadCustomers();
await bindScrollListener();
});
watch(keyword, async () => {
watch(keyword, () => {
if (!props.visible) {
return;
}
window.clearTimeout(keywordTimer);
keywordTimer = window.setTimeout(async () => {
await reloadCustomers();
await bindScrollListener();
}, 300);
});
watch(() => customerOptions.value.length, async () => {
await bindScrollListener();
reloadByKeyword();
});
onUnmounted(() => {
window.clearTimeout(keywordTimer);
Scroller.removeListener(scrollListenerName);
reloadByKeyword.cancel();
});
</script>
@@ -335,34 +325,31 @@ onUnmounted(() => {
display: flex;
flex-direction: column;
.search-wrapper {
.search-wrap {
gap: .5rem;
display: flex;
z-index: 1;
padding: 1rem 0 .5rem;
padding: .5rem;
box-shadow: 0 4px 4px rgba(0, 0, 0, .05);
.search-row {
gap: .5rem;
display: flex;
padding: 0 1rem;
align-items: center;
}
align-items: center;
.search {
--td-input-vertical-padding: 8px 14px;
flex: 1;
border: 1px solid var(--td-component-border);
padding: .25rem .5rem;
min-width: 0;
border-radius: .875rem;
border-radius: .75rem;
}
.scan-button {
.scan {
--td-button-border-radius: .75rem;
flex-shrink: 0;
}
}
.scanner-wrapper {
.scanner-wrap {
padding: .5rem 1rem 0;
}