bug处理加文字样式微调
This commit is contained in:
+76
-30
@@ -45,8 +45,8 @@
|
||||
* ------------------------------------------------------------
|
||||
* | 数据名(name) | 中文名称 | 说明 |
|
||||
* | ----------------------------- | -------------- | --------------------------------- |
|
||||
* * | offerpieBrowserPlugUsage | 插件使用状态 | 标识插件正在运行 { usage: string, version: string } |
|
||||
* * | offerpaiDeliveryLinkList | 投递链接列表 | 记录要投递职位的来源链接,目前用于解决投递网站的重定向 { linkList: string[] },useCsl:true |
|
||||
* | offerpieBrowserPlugUsage | 插件使用状态 | 标识插件正在运行 { usage: string, version: string } |
|
||||
* | offerpaiDeliveryLinkList | 投递链接列表 | 记录要投递职位的来源链接,目前用于解决投递网站的重定向 { linkList: string[] } |
|
||||
* ============================================================
|
||||
*/
|
||||
|
||||
@@ -108,8 +108,6 @@ export interface ChannelBridgeOptions {
|
||||
|
||||
/** IndexedDB 数据库名称(含固定雪花ID保证唯一性) */
|
||||
const DB_NAME = 'offerpie_comm_7394028156183472'
|
||||
/** IndexedDB 版本号 */
|
||||
const DB_VERSION = 1
|
||||
/** get 方法 BroadcastChannel 超时时间(毫秒) */
|
||||
const GET_TIMEOUT_MS = 60
|
||||
/** emit 方法节流写库间隔(毫秒) */
|
||||
@@ -235,10 +233,30 @@ function _getCslProxyChannel(domain: string): BroadcastChannel {
|
||||
|
||||
// ============ IndexedDB 操作 ============
|
||||
|
||||
/** 打开/创建 IndexedDB 数据库,按 domain 动态创建 ObjectStore */
|
||||
/** 数据库连接缓存(避免重复打开和版本冲突) */
|
||||
const _dbCache = new Map<string, Promise<IDBDatabase>>()
|
||||
|
||||
/** 打开/创建 IndexedDB 数据库,按 domain 动态创建 ObjectStore,带连接缓存防并发冲突 */
|
||||
function openDB(storeName: string): Promise<IDBDatabase> {
|
||||
return new Promise((resolve, reject) => {
|
||||
const request = indexedDB.open(DB_NAME, DB_VERSION)
|
||||
// 如果已有进行中或已完成的连接,直接复用
|
||||
if (_dbCache.has(storeName)) {
|
||||
return _dbCache.get(storeName)!.then(db => {
|
||||
// 检查连接是否还有效(可能被 close 了)
|
||||
try {
|
||||
// 尝试创建事务验证连接有效性
|
||||
if (db.objectStoreNames.contains(storeName)) {
|
||||
return db
|
||||
}
|
||||
} catch {
|
||||
// 连接已关闭,清除缓存重新打开
|
||||
_dbCache.delete(storeName)
|
||||
}
|
||||
return openDB(storeName)
|
||||
})
|
||||
}
|
||||
|
||||
const promise = new Promise<IDBDatabase>((resolve, reject) => {
|
||||
const request = indexedDB.open(DB_NAME)
|
||||
request.onupgradeneeded = () => {
|
||||
const db = request.result
|
||||
if (!db.objectStoreNames.contains(storeName)) {
|
||||
@@ -248,9 +266,10 @@ function openDB(storeName: string): Promise<IDBDatabase> {
|
||||
}
|
||||
request.onsuccess = () => {
|
||||
const db = request.result
|
||||
// 如果 store 不存在(版本没升级的情况),关闭后升版本重建
|
||||
if (!db.objectStoreNames.contains(storeName)) {
|
||||
// store 不存在,需要升版本。关闭当前连接再重开
|
||||
db.close()
|
||||
_dbCache.delete(storeName)
|
||||
const version = db.version + 1
|
||||
const req2 = indexedDB.open(DB_NAME, version)
|
||||
req2.onupgradeneeded = () => {
|
||||
@@ -261,37 +280,60 @@ function openDB(storeName: string): Promise<IDBDatabase> {
|
||||
}
|
||||
}
|
||||
req2.onsuccess = () => resolve(req2.result)
|
||||
req2.onerror = () => reject(req2.error)
|
||||
req2.onerror = () => { _dbCache.delete(storeName); reject(req2.error) }
|
||||
req2.onblocked = () => {
|
||||
// 其他标签页占用数据库导致升级被阻塞,超时后放弃
|
||||
console.warn('[ChannelBridge] IndexedDB upgrade blocked, retrying...')
|
||||
_dbCache.delete(storeName)
|
||||
reject(new Error('IndexedDB upgrade blocked'))
|
||||
}
|
||||
} else {
|
||||
resolve(db)
|
||||
}
|
||||
}
|
||||
request.onerror = () => reject(request.error)
|
||||
request.onerror = () => { _dbCache.delete(storeName); reject(request.error) }
|
||||
request.onblocked = () => {
|
||||
console.warn('[ChannelBridge] IndexedDB open blocked')
|
||||
_dbCache.delete(storeName)
|
||||
reject(new Error('IndexedDB open blocked'))
|
||||
}
|
||||
})
|
||||
|
||||
_dbCache.set(storeName, promise)
|
||||
return promise
|
||||
}
|
||||
|
||||
/** 写入或更新一条记录到 IndexedDB */
|
||||
async function dbPut(storeName: string, record: DBRecord): Promise<void> {
|
||||
const db = await openDB(storeName)
|
||||
return new Promise((resolve, reject) => {
|
||||
const tx = db.transaction(storeName, 'readwrite')
|
||||
const store = tx.objectStore(storeName)
|
||||
store.put(record)
|
||||
tx.oncomplete = () => { db.close(); resolve() }
|
||||
tx.onerror = () => { db.close(); reject(tx.error) }
|
||||
})
|
||||
try {
|
||||
const db = await openDB(storeName)
|
||||
return new Promise((resolve, reject) => {
|
||||
const tx = db.transaction(storeName, 'readwrite')
|
||||
const store = tx.objectStore(storeName)
|
||||
store.put(record)
|
||||
tx.oncomplete = () => resolve()
|
||||
tx.onerror = () => reject(tx.error)
|
||||
})
|
||||
} catch (err) {
|
||||
console.warn('[ChannelBridge] dbPut failed:', err)
|
||||
}
|
||||
}
|
||||
|
||||
/** 从 IndexedDB 读取一条记录 */
|
||||
async function dbGet(storeName: string, name: string): Promise<DBRecord | null> {
|
||||
const db = await openDB(storeName)
|
||||
return new Promise((resolve, reject) => {
|
||||
const tx = db.transaction(storeName, 'readonly')
|
||||
const store = tx.objectStore(storeName)
|
||||
const req = store.get(name)
|
||||
req.onsuccess = () => { db.close(); resolve(req.result || null) }
|
||||
req.onerror = () => { db.close(); reject(req.error) }
|
||||
})
|
||||
try {
|
||||
const db = await openDB(storeName)
|
||||
return new Promise((resolve, reject) => {
|
||||
const tx = db.transaction(storeName, 'readonly')
|
||||
const store = tx.objectStore(storeName)
|
||||
const req = store.get(name)
|
||||
req.onsuccess = () => resolve(req.result || null)
|
||||
req.onerror = () => reject(req.error)
|
||||
})
|
||||
} catch (err) {
|
||||
console.warn('[ChannelBridge] dbGet failed:', err)
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
// ============ 核心:创建通信桥接实例 ============
|
||||
@@ -499,19 +541,23 @@ export function createChannelBridge(options: ChannelBridgeOptions) {
|
||||
}
|
||||
|
||||
// 默认模式:IndexedDB
|
||||
// 先尝试获取 createTime(从暂存或数据库)
|
||||
// 先尝试获取 createTime(从暂存或内存缓存)
|
||||
let createTime: string
|
||||
const pending = emitPending.get(key)
|
||||
if (pending) {
|
||||
createTime = pending.createTime
|
||||
} else {
|
||||
const existing = await dbGet(targetDomain, name)
|
||||
// 只在首次查库获取 createTime,失败就用当前时间(不阻塞后续 emit)
|
||||
let existing: DBRecord | null = null
|
||||
try {
|
||||
existing = await dbGet(targetDomain, name)
|
||||
} catch {}
|
||||
createTime = existing?.createTime || now
|
||||
}
|
||||
const updateTime = now
|
||||
const record: DBRecord = { name, data, createTime, updateTime }
|
||||
|
||||
// 暂存最新数据
|
||||
// 暂存最新数据(不再 delete,保证后续 emit 总能命中缓存不走 dbGet)
|
||||
emitPending.set(key, record)
|
||||
|
||||
// BroadcastChannel 每次都广播(保证 watch 实时性)
|
||||
@@ -525,7 +571,7 @@ export function createChannelBridge(options: ChannelBridgeOptions) {
|
||||
emitTimers.delete(key)
|
||||
const latestRecord = emitPending.get(key)
|
||||
if (latestRecord) {
|
||||
emitPending.delete(key)
|
||||
// 注意:不再 delete emitPending,让下次 emit 继续命中缓存
|
||||
await dbPut(targetDomain, latestRecord)
|
||||
}
|
||||
}, EMIT_THROTTLE_MS))
|
||||
|
||||
Reference in New Issue
Block a user