bug处理加文字样式微调

This commit is contained in:
2026-07-17 20:00:24 +08:00
parent d429bae98a
commit 33ecccdcb0
9 changed files with 538 additions and 229 deletions
+76 -30
View File
@@ -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))