From a2002ba0e8aa2a0e4eee61b5205748d8f6e454fc Mon Sep 17 00:00:00 2001
From: zhangwencui <1064582902@qq.com>
Date: 星期二, 21 七月 2026 17:30:10 +0800
Subject: [PATCH] 其余新增后弹窗不自动关闭问题修改

---
 src/views/im/utils/pull.ts |  155 +++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 155 insertions(+), 0 deletions(-)

diff --git a/src/views/im/utils/pull.ts b/src/views/im/utils/pull.ts
new file mode 100644
index 0000000..4e3ec11
--- /dev/null
+++ b/src/views/im/utils/pull.ts
@@ -0,0 +1,155 @@
+import { getDb } from './db'
+
+/**
+ * IM 鐘舵�佷簨浠惰ˉ鍋匡紙澧為噺鎷夊彇锛夐�氱敤缂栨帓
+ *
+ * 鍚勪笟鍔℃ā鍧楋紙濂藉弸銆佺兢銆佺敵璇枫�佽浣嶇疆锛夊叡鐢ㄤ竴濂� update_time + id 姝e悜娓告爣锛�
+ * 浠庢寔涔呭寲娓告爣鍑哄彂寰幆鎷夊彇鍙樻洿骞跺悎骞惰繘鏈湴 store锛岀洿鍒版煇椤典笉婊★紙娌℃湁鏇村锛夛紝
+ * 鐢ㄤ簬 WebSocket 婕忔帹鍚庣殑鍏滃簳琛ュ伩锛堣繘鍏� IM銆佹柇绾块噸杩炴椂瑙﹀彂锛�
+ */
+
+/** 澧為噺鎷夊彇娓告爣锛氫笂娆℃媺鍒扮殑浣嶇疆 */
+export interface PullCursor {
+  lastUpdateTime?: number
+  lastId?: number
+}
+
+/** 鍙綔涓烘父鏍囩殑鎷夊彇璁板綍锛氭湇鍔$鎸� update_time + id 杩斿洖锛屽鎴风鍙栨渶鍚庝竴鏉℃帹杩涙父鏍� */
+interface PullRecord {
+  id: number
+  updateTime?: number
+}
+
+/** 鍗曟鎷夊彇鏉℃暟锛堜笌鍚庣 limit 涓婇檺瀵归綈锛� */
+const PULL_PAGE_SIZE = 100
+/** 鍗曡疆鏈�澶氱炕椤垫暟锛屽厹搴曢槻寰″紓甯告父鏍囧鑷寸殑姝诲惊鐜� */
+const PULL_MAX_PAGES = 100
+/** 鐘舵�佷簨浠舵媺鍙栧洖鎵獥鍙o紝瑕嗙洊鍚岀鍐呮棫琛屾洿鏂板拰瀹㈡埛绔� / 鏈嶅姟绔椂閽熺簿搴﹀樊 */
+const PULL_OVERLAP_MS = 5000
+/** 娑堟伅绫� minId 鎷夊彇鐨勫崟杞炕椤典笂闄愶紝鍏滃簳闃插尽寮傚父娓告爣姝荤炕锛涙秷鎭噺鍙兘杩滃ぇ浜庣姸鎬佷簨浠讹紝鏀惧鍒� 1000 */
+const MIN_ID_PULL_MAX_PAGES = 1000
+
+/** 璇诲彇鏌愭ā鍧楃殑鎷夊彇娓告爣锛涙棤鍒欒繑鍥炵┖娓告爣锛堥娆℃媺鍏ㄩ噺锛� */
+export async function getPullCursor(key: string): Promise<PullCursor> {
+  return (await getDb().getSetting<PullCursor>(key)) ?? {}
+}
+
+/**
+ * 閫氱敤澧為噺鎷夊彇锛氫粠鎸佷箙鍖栨父鏍囧嚭鍙戯紝寰幆鎷夊彇骞跺簲鐢ㄥ彉鏇达紝鐩村埌鏌愰〉涓嶆弧
+ *
+ * @param cursorKey 娓告爣鍦� settings 閲岀殑 key锛堟瘡涓ā鍧椾竴浠斤級
+ * @param fetchPage 鎸夋父鏍囨媺涓�椤碉紙璋冨搴� pull 鎺ュ彛锛岃繑鍥� VO 鍒楄〃锛�
+ * @param apply 鎶婁竴椤靛彉鏇村悎骞惰繘鏈湴 store锛涜繑鍥� false 琛ㄧず鏈〉鏈畬鍏ㄨ惤鍦帮紙濡傝处鍙峰凡鍒囥�佷緷璧栬祫婧愯ˉ鎷夊け璐ワ級锛�
+ *              姝ゆ椂涓嶆帹杩涙父鏍囧苟缁堟鏈疆锛岄伩鍏嶆父鏍囪秺杩囨湭钀藉湴鐨勮褰曘�佸鑷村悗缁閲忔案涔呮紡鎷夈�傚彲杩斿洖 Promise
+ */
+export async function runIncrementalPull<T extends PullRecord>(
+  cursorKey: string,
+  fetchPage: (params: { lastId?: number; lastUpdateTime?: number; limit: number }) => Promise<T[]>,
+  apply: (records: T[]) => boolean | Promise<boolean>,
+  isActive?: () => boolean
+): Promise<void> {
+  const storedCursor = await getPullCursor(cursorKey)
+  const highWater = { ...storedCursor }
+  let cursor =
+    storedCursor.lastUpdateTime == null
+      ? {}
+      : { lastUpdateTime: Math.max(0, storedCursor.lastUpdateTime - PULL_OVERLAP_MS), lastId: 0 }
+  for (let page = 0; page < PULL_MAX_PAGES; page++) {
+    if (isActive && !isActive()) {
+      return
+    }
+    const list = await fetchPage({
+      lastUpdateTime: cursor.lastUpdateTime,
+      lastId: cursor.lastId,
+      limit: PULL_PAGE_SIZE
+    })
+    if (isActive && !isActive()) {
+      return
+    }
+    if (list.length > 0) {
+      // apply 鏈畬鍏ㄨ惤鍦帮紙杩斿洖 false锛夋椂鐩存帴缁堟锛氭父鏍囧彧鑳借窡鐫�宸茶惤鍦扮殑鏁版嵁璧帮紝鍚﹀垯浼氳烦杩囨湰椤佃褰�
+      if ((await apply(list)) === false) {
+        return
+      }
+      if (isActive && !isActive()) {
+        return
+      }
+      // 鎺ㄨ繘娓告爣鍒版湰椤垫渶鍚庝竴鏉″苟鎸佷箙鍖栵細涓嬫浠庤繖閲屾帴鐫�鎷�
+      const last = list[list.length - 1]
+      if (!last) {
+        return
+      }
+      if (last.updateTime == null) {
+        return
+      }
+      cursor = { lastUpdateTime: last.updateTime, lastId: last.id }
+      if (
+        highWater.lastUpdateTime == null ||
+        cursor.lastUpdateTime > highWater.lastUpdateTime ||
+        (cursor.lastUpdateTime === highWater.lastUpdateTime &&
+          cursor.lastId > (highWater.lastId ?? 0))
+      ) {
+        highWater.lastUpdateTime = cursor.lastUpdateTime
+        highWater.lastId = cursor.lastId
+        await getDb().setSetting(cursorKey, highWater)
+      }
+    }
+    // 涓嶆弧涓�椤� = 娌℃湁鏇村鍙樻洿
+    if (list.length < PULL_PAGE_SIZE) {
+      return
+    }
+  }
+  console.warn(`[IM pull] ${cursorKey} 杈惧埌鍗曡疆缈婚〉涓婇檺锛屾彁鍓嶇粨鏉熸湰杞ˉ鍋縛)
+}
+
+/**
+ * 娑堟伅绫诲閲忔媺鍙栭�氱敤缂栨帓锛氭寜鍗曡皟 minId 娓告爣寰幆缈婚〉锛岀洿鍒扮┖椤垫垨娓告爣涓嶅啀鍓嶈繘
+ *
+ * 涓� runIncrementalPull 鐨勫尯鍒細娑堟伅娓告爣鏄崟璋冩秷鎭� id锛堥潪 update_time + id 澶嶅悎娓告爣锛夛紝涓� messageMaxId 鐨勬寔涔呭寲
+ * 璺熼殢娑堟伅鍏ュ簱鍦� applyPage 鍐呭畬鎴愶紙messageStore锛夛紝鏁呮湰鍑芥暟鍙礋璐c�屽惊鐜炕椤垫満鍒躲�嶏紝涓嶇 settings锛屼篃涓嶆幒娑堟伅涓氬姟銆�
+ *
+ * @param initialMinId 璧峰娓告爣锛氫笂娆″叆搴撶殑鏈�澶ф秷鎭� id
+ * @param pageSize     鍗曢〉鏉℃暟
+ * @param fetchPage    鎸� minId 鎷変竴椤�
+ * @param applyPage    澶勭悊鏈〉锛堝缓浼氳瘽 / 鍒嗗彂 / 鍏ュ簱 + 鎺ㄨ繘 messageMaxId锛夛紱杩斿洖 false 琛ㄧず鏈〉鏈惤鍦帮紝鍋滄涓斾笉鎺ㄨ繘娓告爣
+ * @param isActive     姣忔 await 鍓嶅悗鑷锛氬彇娑� / 鍒囪处鍙锋椂杩斿洖 false锛屼涪寮冩湰鎵逛笉鍏ュ簱銆佷笉鍐嶇炕椤�
+ * @param maxPages     鍗曡疆缈婚〉涓婇檺
+ */
+export async function runMinIdPull<T extends { id?: number }>(options: {
+  applyPage: (records: T[], nextMinId?: number) => Promise<boolean> | Promise<void>
+  fetchPage: (params: { minId: number; size: number }) => Promise<T[]>
+  initialMinId: number
+  isActive?: () => boolean
+  maxPages?: number
+  pageSize: number
+}): Promise<void> {
+  const { initialMinId, pageSize, fetchPage, applyPage, isActive } = options
+  const maxPages = options.maxPages ?? MIN_ID_PULL_MAX_PAGES
+  let minId = initialMinId || 0
+  for (let page = 0; page < maxPages; page++) {
+    if (isActive && !isActive()) {
+      return
+    }
+    const list = await fetchPage({ minId, size: pageSize })
+    // 鎷夊彇鏈熼棿鍙栨秷 / 鍒囪处鍙凤細涓㈠純鏈壒涓嶅叆搴擄紝涔熶笉鍐嶇炕椤�
+    if (isActive && !isActive()) {
+      return
+    }
+    if (!list || list.length === 0) {
+      return
+    }
+    // 鏈壒鏈�澶ф秷鎭� id 浣滀负涓嬫娓告爣锛涙棤鏈夋晥 id 鍒欐湰鎵� apply 鍚庡仠锛堟棤娉曠户缁炕椤碉級
+    const validIds = list.map((record) => record.id).filter((id): id is number => id != null)
+    const nextMinId = validIds.length > 0 ? Math.max(...validIds) : undefined
+    // applyPage 杩斿洖 false锛氭湰椤垫湭钀藉湴锛堝鍏ュ簱澶辫触锛夛紝涓嶆帹杩涙父鏍囧苟缁堟锛岄伩鍏嶆紡娑堟伅
+    if ((await applyPage(list, nextMinId)) === false) {
+      return
+    }
+    // 鏃犳湁鏁� id锛屾垨娓告爣娌″墠杩涳紙鍚庣濂戠害鏄� id > minId锛岀悊璁轰笉浼氬嚭鐜帮級锛氬仠锛岄槻寰℃缈�
+    if (nextMinId == null || nextMinId <= minId) {
+      return
+    }
+    minId = nextMinId
+  }
+  console.warn('[IM pull] runMinIdPull 杈惧埌鍗曡疆缈婚〉涓婇檺锛屾彁鍓嶇粨鏉熸湰杞�')
+}

--
Gitblit v1.9.3