From 8dba4a610440fee8c1cbc0a6a4bdaed90a813e73 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B5=85=E5=BF=B5?= Date: Tue, 25 Aug 2026 19:06:55 +0800 Subject: [PATCH] =?UTF-8?q?fix(staffchat):=20ContactsPane=20=E5=8A=A0?= =?UTF-8?q?=E8=AF=B7=E6=B1=82=E5=BA=8F=E5=8F=B7=E9=98=B2=20ownerId/?= =?UTF-8?q?=E7=BF=BB=E9=A1=B5=E5=88=87=E6=8D=A2=E7=AB=9E=E6=80=81(?= =?UTF-8?q?=E5=AF=B9=E9=BD=90=20ChatMain/MomentsPane=20=E6=83=AF=E4=BE=8B)?= =?UTF-8?q?+=E4=BF=AE=E6=AD=A3=E8=B7=A8tab=E5=85=B3=E9=94=AE=E8=AF=8D?= =?UTF-8?q?=E6=B3=A8=E9=87=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude --- .../src/components/staffchat/ContactsPane.vue | 20 +++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/yunkes/src/components/staffchat/ContactsPane.vue b/yunkes/src/components/staffchat/ContactsPane.vue index 35dbd5d..ab213d8 100644 --- a/yunkes/src/components/staffchat/ContactsPane.vue +++ b/yunkes/src/components/staffchat/ContactsPane.vue @@ -22,7 +22,8 @@ const PAGE_SIZE = 10 type TabKey = 'customers' | 'groups' const activeTab = ref('customers') -/** 输入框值 / 已应用值:点「查询」(或回车)才生效重查,对齐云客。 */ +/** 输入框值 / 已应用值:点「查询」(或回车)才生效重查,对齐云客。 + 单一搜索框设计——关键词跨 tab 保留并应用于新 tab 的查询(placeholder 随 tab 切换,关键词可见)。 */ const keyword = ref('') const appliedKeyword = ref('') @@ -42,7 +43,12 @@ const groupLoading = ref(false) const groupError = ref(null) const selectedGroups = ref([]) +/** 请求序号: ownerId/翻页切换后在途旧响应整体丢弃(防竞态覆盖新员工/新页的数据)。 */ +let customerSeq = 0 +let groupSeq = 0 + async function loadCustomers(): Promise { + const mySeq = ++customerSeq customerLoading.value = true customerError.value = null try { @@ -53,18 +59,21 @@ async function loadCustomers(): Promise { page: customerPage.value, page_size: PAGE_SIZE, }) + if (mySeq !== customerSeq) return customers.value = res.items customerTotal.value = res.total } catch (e) { + if (mySeq !== customerSeq) return customerError.value = (e as Error).message customers.value = [] customerTotal.value = 0 } finally { - customerLoading.value = false + if (mySeq === customerSeq) customerLoading.value = false } } async function loadGroups(): Promise { + const mySeq = ++groupSeq groupLoading.value = true groupError.value = null try { @@ -75,18 +84,20 @@ async function loadGroups(): Promise { page: groupPage.value, page_size: PAGE_SIZE, }) + if (mySeq !== groupSeq) return groups.value = res.items groupTotal.value = res.total } catch (e) { + if (mySeq !== groupSeq) return groupError.value = (e as Error).message groups.value = [] groupTotal.value = 0 } finally { - groupLoading.value = false + if (mySeq === groupSeq) groupLoading.value = false } } -/** 当前 tab 重查(tab 切换时总是重查,另一 tab 不会残留旧关键词的旧数据)。 */ +/** 当前 tab 重查(tab 切换时按保留的关键词重查新 tab,对齐云客单一搜索框)。 */ function loadActiveTab(): void { if (activeTab.value === 'customers') void loadCustomers() else void loadGroups() @@ -116,6 +127,7 @@ function onGroupSelection(rows: Group[]): void { selectedGroups.value = rows } +// tab 切换即按当前(跨 tab 保留的)关键词重查新 tab watch(activeTab, loadActiveTab) watch( () => props.ownerId,