为了可拖拽tab的效果,引入electron-tabs包
This commit is contained in:
parent
346f88d21e
commit
f99c1bb88e
28
index.html
28
index.html
@ -1,17 +1,20 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="zh-CN">
|
<html lang="zh-CN">
|
||||||
|
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
<meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline';" />
|
<meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline';" />
|
||||||
<title>中国电信-工作台</title>
|
<title>中国电信-工作台</title>
|
||||||
<link rel="stylesheet" href="./src/index.css">
|
<link rel="stylesheet" href="./src/index.css">
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<div class="app-container">
|
<div class="app-container">
|
||||||
<header class="app-header">
|
<header class="app-header">
|
||||||
<div class="header-left">
|
<div class="header-left">
|
||||||
<img src="./assets/logo.png" alt="Logo" class="logo">
|
<img id="logo" src="./assets/logo.png" alt="Logo" class="logo" />
|
||||||
<h1>中国电信-工作台</h1>
|
<h1>中国电信-工作台</h1>
|
||||||
</div>
|
</div>
|
||||||
<div class="header-right">
|
<div class="header-right">
|
||||||
@ -19,24 +22,17 @@
|
|||||||
<button id="btnLogout" class="logout-btn">退出登录</button>
|
<button id="btnLogout" class="logout-btn">退出登录</button>
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
<main class="app-main">
|
<main class="app-main">
|
||||||
<nav class="sidebar">
|
<nav class="sidebar" style="display: none;">
|
||||||
<ul id="menuList" class="menu-list">
|
<ul id="menuList" class="menu-list">
|
||||||
<!-- 菜单项将通过JavaScript动态加载 -->
|
<!-- 菜单项将通过JavaScript动态加载 -->
|
||||||
</ul>
|
</ul>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
<div class="content-area">
|
<div class="content-area">
|
||||||
<div class="tabs-container">
|
<div class="tabs-container">
|
||||||
<div class="tabs-header">
|
<tab-group sortable="true"></tab-group>
|
||||||
<ul id="tabsList" class="tabs-list">
|
|
||||||
<!-- Tabs will be added here dynamically -->
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
<div id="tabsContent" class="tabs-content">
|
|
||||||
<!-- Webviews will be added here dynamically -->
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</main>
|
</main>
|
||||||
@ -50,7 +46,9 @@
|
|||||||
<button id="closeErrorModal" class="close-btn">确定</button>
|
<button id="closeErrorModal" class="close-btn">确定</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<script src="node_modules/electron-tabs/dist/electron-tabs.js"></script>
|
||||||
<script type="module" src="./src/index.ts"></script>
|
<script type="module" src="./src/index.ts"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
|
||||||
|
</html>
|
@ -2,7 +2,8 @@
|
|||||||
<html lang="zh-CN">
|
<html lang="zh-CN">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
<meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline';" />
|
<meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline';" />
|
||||||
<title>登录</title>
|
<title>登录</title>
|
||||||
<link rel="stylesheet" href="./src/login.css">
|
<link rel="stylesheet" href="./src/login.css">
|
||||||
|
10062
package-lock.json
generated
Normal file
10062
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
@ -28,6 +28,7 @@
|
|||||||
"@electron-forge/plugin-vite": "^7.8.0",
|
"@electron-forge/plugin-vite": "^7.8.0",
|
||||||
"@electron/fuses": "^1.8.0",
|
"@electron/fuses": "^1.8.0",
|
||||||
"@types/electron-squirrel-startup": "^1.0.2",
|
"@types/electron-squirrel-startup": "^1.0.2",
|
||||||
|
"@types/sortablejs": "^1.15.8",
|
||||||
"@typescript-eslint/eslint-plugin": "^5.62.0",
|
"@typescript-eslint/eslint-plugin": "^5.62.0",
|
||||||
"@typescript-eslint/parser": "^5.62.0",
|
"@typescript-eslint/parser": "^5.62.0",
|
||||||
"cross-env": "^7.0.3",
|
"cross-env": "^7.0.3",
|
||||||
@ -39,6 +40,8 @@
|
|||||||
"vite": "^5.4.18"
|
"vite": "^5.4.18"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"electron-squirrel-startup": "^1.0.1"
|
"electron-squirrel-startup": "^1.0.1",
|
||||||
|
"electron-tabs": "^1.0.4",
|
||||||
|
"sortablejs": "^1.15.6"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -178,81 +178,4 @@ body {
|
|||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
|
||||||
|
|
||||||
.tabs-header {
|
|
||||||
background-color: #f5f5f5;
|
|
||||||
border-bottom: 1px solid #ddd;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tabs-list {
|
|
||||||
display: flex;
|
|
||||||
list-style: none;
|
|
||||||
margin: 0;
|
|
||||||
padding: 0;
|
|
||||||
height: 40px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tab-item {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
padding: 0 15px;
|
|
||||||
height: 100%;
|
|
||||||
border-right: 1px solid #ddd;
|
|
||||||
background-color: #fff;
|
|
||||||
cursor: pointer;
|
|
||||||
user-select: none;
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tab-item.active {
|
|
||||||
background-color: #fff;
|
|
||||||
border-bottom: 2px solid #1890ff;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tab-item .tab-title {
|
|
||||||
margin-right: 8px;
|
|
||||||
max-width: 150px;
|
|
||||||
overflow: hidden;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
white-space: nowrap;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tab-item .tab-close {
|
|
||||||
width: 16px;
|
|
||||||
height: 16px;
|
|
||||||
line-height: 16px;
|
|
||||||
text-align: center;
|
|
||||||
border-radius: 50%;
|
|
||||||
color: #999;
|
|
||||||
font-size: 12px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tab-item .tab-close:hover {
|
|
||||||
background-color: #e6e6e6;
|
|
||||||
color: #666;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tabs-content {
|
|
||||||
flex: 1;
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tab-pane {
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tab-pane.active {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tab-pane webview {
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
border: none;
|
|
||||||
}
|
}
|
203
src/index.ts
203
src/index.ts
@ -1,4 +1,4 @@
|
|||||||
import { ipcRenderer, WebviewTag } from "electron";
|
import { TabGroup, Tab } from 'electron-tabs';
|
||||||
|
|
||||||
// 菜单项
|
// 菜单项
|
||||||
interface MenuItem {
|
interface MenuItem {
|
||||||
@ -28,122 +28,9 @@ interface ApiResponse<T> {
|
|||||||
data: T;
|
data: T;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tab management
|
const tabGroup: TabGroup = document.querySelector('tab-group') as TabGroup;
|
||||||
interface Tab {
|
|
||||||
id: string;
|
|
||||||
title: string;
|
|
||||||
url: string;
|
|
||||||
webview: WebviewTag;
|
|
||||||
}
|
|
||||||
|
|
||||||
let tabs: Tab[] = [];
|
// Check login status
|
||||||
let activeTabId: string | null = null;
|
|
||||||
|
|
||||||
// Create a new tab
|
|
||||||
function createTab(title: string, url: string): Tab {
|
|
||||||
const id = `tab-${Date.now()}`;
|
|
||||||
const tabPane = document.createElement('div');
|
|
||||||
tabPane.className = 'tab-pane';
|
|
||||||
tabPane.id = `pane-${id}`;
|
|
||||||
|
|
||||||
const webview = document.createElement('webview');
|
|
||||||
webview.className = 'page-content';
|
|
||||||
webview.setAttribute('autosize', 'on');
|
|
||||||
webview.setAttribute('allowpopups', 'true');
|
|
||||||
webview.setAttribute('webpreferences', 'contextIsolation=yes, nodeIntegration=no');
|
|
||||||
webview.src = url;
|
|
||||||
|
|
||||||
tabPane.appendChild(webview);
|
|
||||||
document.getElementById('tabsContent')?.appendChild(tabPane);
|
|
||||||
|
|
||||||
const tab: Tab = {
|
|
||||||
id,
|
|
||||||
title,
|
|
||||||
url,
|
|
||||||
webview
|
|
||||||
};
|
|
||||||
|
|
||||||
tabs.push(tab);
|
|
||||||
return tab;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create tab header
|
|
||||||
function createTabHeader(tab: Tab): HTMLLIElement {
|
|
||||||
const li = document.createElement('li');
|
|
||||||
li.className = 'tab-item';
|
|
||||||
li.dataset.tabId = tab.id;
|
|
||||||
|
|
||||||
const titleSpan = document.createElement('span');
|
|
||||||
titleSpan.className = 'tab-title';
|
|
||||||
titleSpan.textContent = tab.title;
|
|
||||||
|
|
||||||
const closeButton = document.createElement('span');
|
|
||||||
closeButton.className = 'tab-close';
|
|
||||||
closeButton.textContent = '×';
|
|
||||||
closeButton.addEventListener('click', (e) => {
|
|
||||||
e.stopPropagation();
|
|
||||||
closeTab(tab.id);
|
|
||||||
});
|
|
||||||
|
|
||||||
li.appendChild(titleSpan);
|
|
||||||
li.appendChild(closeButton);
|
|
||||||
|
|
||||||
li.addEventListener('click', () => {
|
|
||||||
activateTab(tab.id);
|
|
||||||
});
|
|
||||||
|
|
||||||
return li;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Activate a tab
|
|
||||||
function activateTab(tabId: string) {
|
|
||||||
const tab = tabs.find(t => t.id === tabId);
|
|
||||||
if (!tab) return;
|
|
||||||
|
|
||||||
// Update active states
|
|
||||||
document.querySelectorAll('.tab-item').forEach(item => {
|
|
||||||
item.classList.remove('active');
|
|
||||||
});
|
|
||||||
document.querySelectorAll('.tab-pane').forEach(pane => {
|
|
||||||
pane.classList.remove('active');
|
|
||||||
});
|
|
||||||
|
|
||||||
// Activate the selected tab
|
|
||||||
const tabElement = document.querySelector(`.tab-item[data-tab-id="${tabId}"]`);
|
|
||||||
const paneElement = document.getElementById(`pane-${tabId}`);
|
|
||||||
if (tabElement && paneElement) {
|
|
||||||
tabElement.classList.add('active');
|
|
||||||
paneElement.classList.add('active');
|
|
||||||
}
|
|
||||||
|
|
||||||
activeTabId = tabId;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Close a tab
|
|
||||||
function closeTab(tabId: string) {
|
|
||||||
const tabIndex = tabs.findIndex(t => t.id === tabId);
|
|
||||||
if (tabIndex === -1) return;
|
|
||||||
|
|
||||||
const tab = tabs[tabIndex];
|
|
||||||
const tabElement = document.querySelector(`.tab-item[data-tab-id="${tabId}"]`);
|
|
||||||
const paneElement = document.getElementById(`pane-${tabId}`);
|
|
||||||
|
|
||||||
if (tabElement) tabElement.remove();
|
|
||||||
if (paneElement) paneElement.remove();
|
|
||||||
|
|
||||||
tabs.splice(tabIndex, 1);
|
|
||||||
|
|
||||||
// If we closed the active tab, activate another one
|
|
||||||
if (activeTabId === tabId) {
|
|
||||||
if (tabs.length > 0) {
|
|
||||||
activateTab(tabs[Math.min(tabIndex, tabs.length - 1)].id);
|
|
||||||
} else {
|
|
||||||
activeTabId = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 检查登录状态
|
|
||||||
function checkLoginStatus() {
|
function checkLoginStatus() {
|
||||||
const cookie = window.electronAPI.getSessionStorage('cookie');
|
const cookie = window.electronAPI.getSessionStorage('cookie');
|
||||||
if (!cookie) {
|
if (!cookie) {
|
||||||
@ -151,20 +38,20 @@ function checkLoginStatus() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 显示用户信息
|
// Show user information
|
||||||
const userInfo = document.getElementById('userInfo');
|
const userInfo = document.getElementById('userInfo');
|
||||||
if (userInfo) {
|
if (userInfo) {
|
||||||
userInfo.textContent = '欢迎使用';
|
userInfo.textContent = '欢迎使用';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 处理退出登录
|
// Handle logout
|
||||||
function handleLogout() {
|
function handleLogout() {
|
||||||
window.electronAPI.removeSessionStorage('cookie');
|
window.electronAPI.removeSessionStorage('cookie');
|
||||||
window.location.href = 'login.html';
|
window.location.href = 'login.html';
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取菜单列表
|
// Get menu list
|
||||||
async function getMenuList(): Promise<MenuItem[]> {
|
async function getMenuList(): Promise<MenuItem[]> {
|
||||||
try {
|
try {
|
||||||
const response = await fetch('http://1.12.73.211:8848/EIAC_Desktop_Api/api/Menu/GetMenu', {
|
const response = await fetch('http://1.12.73.211:8848/EIAC_Desktop_Api/api/Menu/GetMenu', {
|
||||||
@ -178,10 +65,10 @@ async function getMenuList(): Promise<MenuItem[]> {
|
|||||||
if (result.status === 0) {
|
if (result.status === 0) {
|
||||||
return result.data;
|
return result.data;
|
||||||
} else {
|
} else {
|
||||||
throw new Error(result.msg || '获取菜单失败');
|
throw new Error(result.msg || '获取菜单列表失败');
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('获取菜单失败:', error);
|
console.error('获取菜单列表失败:', error);
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -220,29 +107,15 @@ function createMenuItem(item: MenuItem, menuList: MenuItem[]): HTMLLIElement {
|
|||||||
li.classList.add('active');
|
li.classList.add('active');
|
||||||
icon.src = item.IconConfig._1x.Selected;
|
icon.src = item.IconConfig._1x.Selected;
|
||||||
|
|
||||||
const url: string = item.Url.startsWith("http") ? item.Url : `http://${item.Url}`;
|
// Create new tab
|
||||||
const result = await window.electronAPI.checkUrlAvailable(url);
|
await addTab(tabGroup, item);
|
||||||
if (result.ok && result.status >= 200 && result.status < 400) {
|
|
||||||
console.log('✅ URL 可访问:', result.status);
|
|
||||||
const cookies: string = window.electronAPI.getSessionStorage('cookie');
|
|
||||||
await window.electronAPI.setWebviewCookie(url, cookies);
|
|
||||||
|
|
||||||
// Create new tab
|
|
||||||
const tab = createTab(item.ShowName, url);
|
|
||||||
const tabHeader = createTabHeader(tab);
|
|
||||||
document.getElementById('tabsList')?.appendChild(tabHeader);
|
|
||||||
activateTab(tab.id);
|
|
||||||
} else {
|
|
||||||
console.warn('❌ URL 不可访问:', result.error ?? `status ${result.status}`);
|
|
||||||
showErrorModal(`无法访问 ${url}\r\n异常原因:${result.error ?? `status ${result.status}`}\r\n请联系10000技术支持。`);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
return li;
|
return li;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 渲染菜单
|
// Render menu
|
||||||
function renderMenu(menuList: MenuItem[]) {
|
function renderMenu(menuList: MenuItem[]) {
|
||||||
const menuContainer = document.getElementById('menuList');
|
const menuContainer = document.getElementById('menuList');
|
||||||
if (!menuContainer) return;
|
if (!menuContainer) return;
|
||||||
@ -263,7 +136,7 @@ function renderMenu(menuList: MenuItem[]) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// 显示故障窗口
|
// Show error modal
|
||||||
function showErrorModal(message: string) {
|
function showErrorModal(message: string) {
|
||||||
const errorModal = document.getElementById('errorModal') as HTMLDivElement;
|
const errorModal = document.getElementById('errorModal') as HTMLDivElement;
|
||||||
const errorMessage = document.getElementById('errorMessage') as HTMLParagraphElement;
|
const errorMessage = document.getElementById('errorMessage') as HTMLParagraphElement;
|
||||||
@ -271,6 +144,44 @@ function showErrorModal(message: string) {
|
|||||||
errorModal.style.display = 'block';
|
errorModal.style.display = 'block';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function addTab(tabGroup: TabGroup, menuItem: MenuItem): Promise<Tab> {
|
||||||
|
const url = menuItem.Url.startsWith("http") ? menuItem.Url : `http://${menuItem.Url}`;
|
||||||
|
const result = await window.electronAPI.checkUrlAvailable(url);
|
||||||
|
if (result.ok && result.status >= 200 && result.status < 400) {
|
||||||
|
console.log('✅ URL 可访问:', result.status);
|
||||||
|
const cookies: string = window.electronAPI.getSessionStorage('cookie');
|
||||||
|
await window.electronAPI.setWebviewCookie(url, cookies);
|
||||||
|
} else {
|
||||||
|
console.warn('❌ URL 不可访问:', result.error ?? `status ${result.status}`);
|
||||||
|
showErrorModal(`无法访问 ${url}\r\n异常原因:${result.error ?? `status ${result.status}`}\r\n请联系10000技术支持。`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const tab: Tab = tabGroup.addTab({
|
||||||
|
active: true,
|
||||||
|
closable: true,
|
||||||
|
title: menuItem.ShowName,
|
||||||
|
src: url,
|
||||||
|
iconURL: menuItem.IconConfig._1x.Default,
|
||||||
|
webviewAttributes: {
|
||||||
|
'webpreferences': 'contextIsolation=yes, nodeIntegration=no',
|
||||||
|
'autosize': 'on',
|
||||||
|
'allowpopups': true,
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return tab;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function bindLogoClickEvent(tabGroup: TabGroup, menuItem: MenuItem) {
|
||||||
|
const logo = document.getElementById('logo') as HTMLImageElement;
|
||||||
|
logo.addEventListener('click', async () => {
|
||||||
|
console.log('logo clicked');
|
||||||
|
|
||||||
|
const tab: Tab = await addTab(tabGroup, menuItem);
|
||||||
|
tab.setPosition(0);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// Modify the initialize function to create the first tab
|
// Modify the initialize function to create the first tab
|
||||||
async function initialize() {
|
async function initialize() {
|
||||||
// Check login status
|
// Check login status
|
||||||
@ -281,10 +192,8 @@ async function initialize() {
|
|||||||
renderMenu(menuList);
|
renderMenu(menuList);
|
||||||
|
|
||||||
// Create initial tab
|
// Create initial tab
|
||||||
const initialTab = createTab('首页', 'about:blank');
|
const firstMenuItem = menuList[0];
|
||||||
const tabHeader = createTabHeader(initialTab);
|
await addTab(tabGroup, firstMenuItem);
|
||||||
document.getElementById('tabsList')?.appendChild(tabHeader);
|
|
||||||
activateTab(initialTab.id);
|
|
||||||
|
|
||||||
// Bind logout event
|
// Bind logout event
|
||||||
const logoutBtn = document.getElementById('btnLogout');
|
const logoutBtn = document.getElementById('btnLogout');
|
||||||
@ -295,16 +204,20 @@ async function initialize() {
|
|||||||
const errorModal = document.getElementById('errorModal') as HTMLDivElement;
|
const errorModal = document.getElementById('errorModal') as HTMLDivElement;
|
||||||
const closeErrorModal = document.getElementById('closeErrorModal') as HTMLButtonElement;
|
const closeErrorModal = document.getElementById('closeErrorModal') as HTMLButtonElement;
|
||||||
// Close button click event
|
// Close button click event
|
||||||
closeErrorModal.addEventListener('click', (event) => {
|
closeErrorModal.addEventListener('click', (event: Event) => {
|
||||||
errorModal.style.display = 'none';
|
errorModal.style.display = 'none';
|
||||||
});
|
});
|
||||||
|
|
||||||
// Click outside to close
|
// Click outside to close
|
||||||
window.addEventListener('click', (event) => {
|
window.addEventListener('click', (event: Event) => {
|
||||||
if (event.target === errorModal) {
|
if (event.target === errorModal) {
|
||||||
errorModal.style.display = 'none';
|
errorModal.style.display = 'none';
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Listen logo click event
|
||||||
|
const lastMenuItem = menuList[menuList.length - 1];
|
||||||
|
await bindLogoClickEvent(tabGroup, lastMenuItem);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('初始化失败:', error);
|
console.error('初始化失败:', error);
|
||||||
}
|
}
|
||||||
|
17
src/main.ts
17
src/main.ts
@ -5,13 +5,12 @@ import * as http from 'http';
|
|||||||
import * as https from 'https';
|
import * as https from 'https';
|
||||||
import { URL } from 'url';
|
import { URL } from 'url';
|
||||||
|
|
||||||
// 确保只有一个实例在运行
|
// Ensure only one instance is running
|
||||||
const gotTheLock = app.requestSingleInstanceLock();
|
const gotTheLock = app.requestSingleInstanceLock();
|
||||||
|
|
||||||
if (!gotTheLock) {
|
if (!gotTheLock) {
|
||||||
app.exit(0); // 使用 exit 而不是 quit,确保立即退出
|
app.exit(0); // 使用 exit 而不是 quit,确保立即退出
|
||||||
} else {
|
} else {
|
||||||
app.on('second-instance', (event, commandLine, workingDirectory) => {
|
app.on('second-instance', (event: Event, cmdArgs: string[], workingDirectory: string) => {
|
||||||
// 当运行第二个实例时,我们应该聚焦到主窗口
|
// 当运行第二个实例时,我们应该聚焦到主窗口
|
||||||
const win = BrowserWindow.getAllWindows()[0];
|
const win = BrowserWindow.getAllWindows()[0];
|
||||||
if (win) {
|
if (win) {
|
||||||
@ -63,7 +62,7 @@ ipcMain.handle('check-url-available', async (event, rawUrl: string) => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// 设置webview的cookie
|
// Set webview‘s cookie
|
||||||
ipcMain.handle('set-webview-cookie', async (event, url: string, cookie: string) => {
|
ipcMain.handle('set-webview-cookie', async (event, url: string, cookie: string) => {
|
||||||
try {
|
try {
|
||||||
const parsedUrl = new URL(url);
|
const parsedUrl = new URL(url);
|
||||||
@ -109,7 +108,7 @@ const createWindow = () => {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
// 隐藏顶部菜单栏
|
// Hide top menu bar
|
||||||
win.setMenuBarVisibility(false);
|
win.setMenuBarVisibility(false);
|
||||||
win.setAutoHideMenuBar(true);
|
win.setAutoHideMenuBar(true);
|
||||||
win.setMenu(null);
|
win.setMenu(null);
|
||||||
@ -136,17 +135,17 @@ const createWindow = () => {
|
|||||||
// });
|
// });
|
||||||
// });
|
// });
|
||||||
|
|
||||||
// 设置session
|
// Set session
|
||||||
win.webContents.session.setPermissionRequestHandler((webContents, permission, callback) => {
|
win.webContents.session.setPermissionRequestHandler((webContents, permission, callback) => {
|
||||||
callback(true);
|
callback(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
// 最小化到系统托盘
|
// Minimize to system tray
|
||||||
win.on('minimize', () => {
|
win.on('minimize', () => {
|
||||||
win.hide();
|
win.hide();
|
||||||
});
|
});
|
||||||
|
|
||||||
// 监听窗口关闭(用户点击右上角X)
|
// Listen window close (user clicks the X in the top right corner)
|
||||||
win.on('close', (event) => {
|
win.on('close', (event) => {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
win.hide();
|
win.hide();
|
||||||
@ -169,7 +168,7 @@ const createWindow = () => {
|
|||||||
win.loadFile(path.join(__dirname, `../renderer/${MAIN_WINDOW_VITE_NAME}/login.html`));
|
win.loadFile(path.join(__dirname, `../renderer/${MAIN_WINDOW_VITE_NAME}/login.html`));
|
||||||
}
|
}
|
||||||
|
|
||||||
// 创建托盘图标
|
// Create tray icon
|
||||||
const contextMenu = Menu.buildFromTemplate([
|
const contextMenu = Menu.buildFromTemplate([
|
||||||
{ label: '显示窗口', click: () => win.show() },
|
{ label: '显示窗口', click: () => win.show() },
|
||||||
{ label: '退出程序', click: () => app.exit() }
|
{ label: '退出程序', click: () => app.exit() }
|
||||||
|
Loading…
x
Reference in New Issue
Block a user