mirror of
https://github.com/kuaifan/dootask.git
synced 2026-01-21 16:48:13 +00:00
refactor: 优化 webTab 管理和状态同步
- 封装 safeCloseWebTab 方法,复用标签关闭时的未保存数据检查逻辑 - 添加 recreatePreloadPool,支持主题切换后重建预加载池 - broadcastCommand 扩展到 webTab views,确保子窗口收到同步消息 - 修复 synchTheme 和 saveDialogDraft 的跨窗口参数传递 - IDBDel 返回 Promise 并正确 await
This commit is contained in:
parent
9c7ec58bb6
commit
a34b0c88d5
9
electron/electron.js
vendored
9
electron/electron.js
vendored
@ -789,11 +789,20 @@ ipcMain.on('windowMax', (event) => {
|
||||
ipcMain.on('broadcastCommand', (event, args) => {
|
||||
const channel = args.channel || args.command
|
||||
const payload = args.payload || args.data
|
||||
// 广播给所有 BrowserWindow
|
||||
BrowserWindow.getAllWindows().forEach(window => {
|
||||
if (window.webContents.id !== event.sender.id) {
|
||||
window.webContents.send(channel, payload)
|
||||
}
|
||||
})
|
||||
// 广播给 webTabManager 中的所有 view
|
||||
for (const [, windowData] of webTabManager.getWebTabWindows()) {
|
||||
windowData.views?.forEach(({ view }) => {
|
||||
if (view && !view.webContents.isDestroyed() && view.webContents.id !== event.sender.id) {
|
||||
view.webContents.send(channel, payload)
|
||||
}
|
||||
})
|
||||
}
|
||||
event.returnValue = "ok"
|
||||
})
|
||||
|
||||
|
||||
117
electron/lib/web-tab-manager.js
vendored
117
electron/lib/web-tab-manager.js
vendored
@ -220,6 +220,38 @@ function clearPreloadPool() {
|
||||
preloadViewPool = []
|
||||
}
|
||||
|
||||
/**
|
||||
* 重建预加载池(清理后重新创建)
|
||||
*/
|
||||
function recreatePreloadPool() {
|
||||
clearPreloadPool()
|
||||
while (preloadViewPool.length < PRELOAD_CONFIG.poolSize) {
|
||||
const view = createPreloadView()
|
||||
if (view) {
|
||||
preloadViewPool.push(view)
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 内置浏览器 - 延迟发送导航状态
|
||||
*/
|
||||
function notifyNavigationState(item) {
|
||||
setTimeout(() => {
|
||||
const wd = webTabWindows.get(item.view.webTabWindowId)
|
||||
if (wd && wd.window) {
|
||||
utils.onDispatchEvent(wd.window.webContents, {
|
||||
event: 'navigation-state',
|
||||
id: item.id,
|
||||
canGoBack: item.view.webContents.navigationHistory.canGoBack(),
|
||||
canGoForward: item.view.webContents.navigationHistory.canGoForward()
|
||||
}).then(_ => { })
|
||||
}
|
||||
}, 100)
|
||||
}
|
||||
|
||||
// ============================================================
|
||||
// 核心函数
|
||||
// ============================================================
|
||||
@ -527,7 +559,7 @@ function createWebTabWindowInstance(windowId, position, mode = 'tab') {
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
// 点击窗口关闭按钮:依次检查并关闭每个标签页
|
||||
const checkAndCloseTabs = async () => {
|
||||
// 复制标签列表,因为关闭时会修改原数组
|
||||
@ -1080,6 +1112,32 @@ function closeWebTabInWindow(windowId, id) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 安全关闭标签(检查未保存数据后关闭)
|
||||
* @param windowId 窗口ID
|
||||
* @param tabId 标签ID
|
||||
*/
|
||||
function safeCloseWebTab(windowId, tabId) {
|
||||
const windowData = webTabWindows.get(windowId)
|
||||
if (!windowData) {
|
||||
closeWebTabInWindow(windowId, tabId)
|
||||
return
|
||||
}
|
||||
|
||||
const tab = windowData.views.find(v => v.id === tabId)
|
||||
if (!tab) {
|
||||
closeWebTabInWindow(windowId, tabId)
|
||||
return
|
||||
}
|
||||
|
||||
const proxyWindow = Object.create(windowData.window, {
|
||||
webContents: { get: () => tab.view.webContents }
|
||||
})
|
||||
utils.onBeforeUnload({ preventDefault: () => {} }, proxyWindow).then(() => {
|
||||
closeWebTabInWindow(windowId, tabId)
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 分离标签到新窗口
|
||||
* @param windowId 源窗口ID
|
||||
@ -1432,6 +1490,14 @@ function destroyAllWindowMode() {
|
||||
function registerIPC() {
|
||||
const electronMenu = getElectronMenu()
|
||||
|
||||
/**
|
||||
* 重建预加载池
|
||||
*/
|
||||
ipcMain.on('recreatePreloadPool', (event) => {
|
||||
recreatePreloadPool()
|
||||
event.returnValue = "ok"
|
||||
})
|
||||
|
||||
/**
|
||||
* 获取路由窗口信息(从 webTabWindows 中查找 mode='window' 的窗口)
|
||||
*/
|
||||
@ -1598,21 +1664,7 @@ function registerIPC() {
|
||||
windowId = findWindowIdByTabId(tabId)
|
||||
}
|
||||
if (windowId) {
|
||||
const windowData = webTabWindows.get(windowId)
|
||||
if (windowData) {
|
||||
const tab = windowData.views.find(v => v.id === tabId)
|
||||
if (tab) {
|
||||
const proxyWindow = Object.create(windowData.window, {
|
||||
webContents: { get: () => tab.view.webContents }
|
||||
})
|
||||
utils.onBeforeUnload({ preventDefault: () => {} }, proxyWindow).then(() => {
|
||||
closeWebTabInWindow(windowId, tabId)
|
||||
})
|
||||
event.returnValue = "ok"
|
||||
return
|
||||
}
|
||||
}
|
||||
closeWebTabInWindow(windowId, tabId)
|
||||
safeCloseWebTab(windowId, tabId)
|
||||
}
|
||||
event.returnValue = "ok"
|
||||
})
|
||||
@ -1726,23 +1778,6 @@ function registerIPC() {
|
||||
event.returnValue = "ok"
|
||||
})
|
||||
|
||||
/**
|
||||
* 内置浏览器 - 延迟发送导航状态
|
||||
*/
|
||||
function notifyNavigationState(item) {
|
||||
setTimeout(() => {
|
||||
const wd = webTabWindows.get(item.view.webTabWindowId)
|
||||
if (wd && wd.window) {
|
||||
utils.onDispatchEvent(wd.window.webContents, {
|
||||
event: 'navigation-state',
|
||||
id: item.id,
|
||||
canGoBack: item.view.webContents.navigationHistory.canGoBack(),
|
||||
canGoForward: item.view.webContents.navigationHistory.canGoForward()
|
||||
}).then(_ => { })
|
||||
}
|
||||
}, 100)
|
||||
}
|
||||
|
||||
/**
|
||||
* 内置浏览器 - 后退
|
||||
*/
|
||||
@ -1864,21 +1899,7 @@ function registerIPC() {
|
||||
const tabId = event.sender.id
|
||||
const windowId = findWindowIdByTabId(tabId)
|
||||
if (windowId !== null) {
|
||||
const windowData = webTabWindows.get(windowId)
|
||||
if (windowData) {
|
||||
const tab = windowData.views.find(v => v.id === tabId)
|
||||
if (tab) {
|
||||
const proxyWindow = Object.create(windowData.window, {
|
||||
webContents: { get: () => tab.view.webContents }
|
||||
})
|
||||
utils.onBeforeUnload({ preventDefault: () => {} }, proxyWindow).then(() => {
|
||||
closeWebTabInWindow(windowId, tabId)
|
||||
})
|
||||
event.returnValue = "ok"
|
||||
return
|
||||
}
|
||||
}
|
||||
closeWebTabInWindow(windowId, tabId)
|
||||
safeCloseWebTab(windowId, tabId)
|
||||
} else {
|
||||
const win = BrowserWindow.fromWebContents(event.sender)
|
||||
win?.close()
|
||||
|
||||
10
resources/assets/js/functions/common.js
vendored
10
resources/assets/js/functions/common.js
vendored
@ -889,10 +889,10 @@ const timezone = require("dayjs/plugin/timezone");
|
||||
|
||||
/**
|
||||
* 输入框数字限制
|
||||
* @param object
|
||||
* @param min
|
||||
* @param max
|
||||
* @returns
|
||||
* @param object
|
||||
* @param min
|
||||
* @param max
|
||||
* @returns
|
||||
*/
|
||||
inputNumberLimit(object, min = null, max = null) {
|
||||
if (object === null || typeof object !== "object") return;
|
||||
@ -1674,7 +1674,7 @@ const timezone = require("dayjs/plugin/timezone");
|
||||
},
|
||||
|
||||
IDBDel(key) {
|
||||
localforage.removeItem(key).then(_ => {})
|
||||
return localforage.removeItem(key)
|
||||
},
|
||||
|
||||
IDBSet(key, value) {
|
||||
|
||||
2
resources/assets/js/language/index.js
vendored
2
resources/assets/js/language/index.js
vendored
@ -95,7 +95,7 @@ function setLanguage(language, silence = false) {
|
||||
if (silence) {
|
||||
utils.saveLanguage(language);
|
||||
(async () => {
|
||||
$A.IDBDel("callAt")
|
||||
await $A.IDBDel("callAt")
|
||||
$A.reloadUrl()
|
||||
})()
|
||||
} else {
|
||||
|
||||
@ -56,6 +56,7 @@ export default {
|
||||
return
|
||||
}
|
||||
$A.messageSuccess('保存成功');
|
||||
$A.Electron?.sendMessage('recreatePreloadPool');
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
12
resources/assets/js/store/actions.js
vendored
12
resources/assets/js/store/actions.js
vendored
@ -556,7 +556,7 @@ export default {
|
||||
resolve(false)
|
||||
return;
|
||||
}
|
||||
dispatch("synchTheme", mode)
|
||||
dispatch("synchTheme", {mode})
|
||||
resolve(true)
|
||||
});
|
||||
},
|
||||
@ -566,8 +566,11 @@ export default {
|
||||
* @param state
|
||||
* @param dispatch
|
||||
* @param mode
|
||||
* @param args
|
||||
*/
|
||||
synchTheme({state, dispatch}, mode = undefined) {
|
||||
synchTheme({state, dispatch}, {mode, ...args} = {}) {
|
||||
$A.syncDispatch("synchTheme", {...args, mode})
|
||||
//
|
||||
if (typeof mode === "undefined") {
|
||||
mode = state.themeConf
|
||||
} else {
|
||||
@ -3814,13 +3817,14 @@ export default {
|
||||
* @param id
|
||||
* @param content
|
||||
* @param immediate
|
||||
* @param args
|
||||
*/
|
||||
saveDialogDraft({commit}, {id, content, immediate = false}) {
|
||||
saveDialogDraft({commit}, {id, content, immediate = false, ...args}) {
|
||||
if ($A.isSubElectron) {
|
||||
dialogDraftState.subTemp = {id, content, immediate: true}
|
||||
return
|
||||
}
|
||||
$A.syncDispatch("saveDialogDraft", {id, content, immediate})
|
||||
$A.syncDispatch("saveDialogDraft", {...args, id, content, immediate})
|
||||
|
||||
// 清除已有的计时器
|
||||
if (dialogDraftState.timer[id]) {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user