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