Skip to content

Commit fade97e

Browse files
authored
Merge pull request #135 from jumpserver/dev
merge dev
2 parents 2f1cbc7 + 04395b9 commit fade97e

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

60 files changed

+3216
-2437
lines changed

go-client/config.json

+5-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,11 @@
44
"defaultSetting": {
55
"layout": "list",
66
"language": "en",
7-
"theme": "light"
7+
"theme": "light",
8+
"windowBounds": {
9+
"width": 1024,
10+
"height": 768
11+
}
812
},
913
"windows": {
1014
"terminal": [

ui/electron-builder.yml

+6-6
Original file line numberDiff line numberDiff line change
@@ -12,16 +12,20 @@ files:
1212
extraResources:
1313
- from: 'bin'
1414
win:
15+
artifactName: JumpServer-Client-Installer-${os}-v${version}-${arch}.${ext}
1516
executableName: JumpServerClient
1617
icon: build/icons/icon.ico
1718
target:
1819
- target: nsis
1920
arch:
2021
- x64
2122
- ia32
23+
- target: msiWrapped
24+
arch:
25+
- x64
26+
- ia32
2227
afterSign: build/sign/notarize.cjs
2328
nsis:
24-
artifactName: JumpServer-Client-Installer-${os}-v${version}-${arch}.${ext}
2529
shortcutName: ${productName}
2630
uninstallDisplayName: ${productName}
2731
createDesktopShortcut: always
@@ -40,12 +44,8 @@ mac:
4044
dmg:
4145
artifactName: JumpServer-Client-Installer-${os}-v${version}-${arch}.${ext}
4246
linux:
43-
icon: build/icons/,
47+
icon: build/icons
4448
target:
45-
- target: AppImage
46-
arch:
47-
- x64
48-
- arm64
4949
- target: deb
5050
arch:
5151
- x64

ui/electron.vite.config.ts

+2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import vue from '@vitejs/plugin-vue';
22
import tailwindcss from 'tailwindcss';
33
import autoprefixer from 'autoprefixer';
4+
import VueJSX from '@vitejs/plugin-vue-jsx';
45
import AutoImport from 'unplugin-auto-import/vite';
56
import Components from 'unplugin-vue-components/vite';
67

@@ -28,6 +29,7 @@ export default defineConfig({
2829
},
2930
plugins: [
3031
vue(),
32+
VueJSX(),
3133
AutoImport({
3234
imports: ['vue']
3335
}),

ui/package.json

+5-3
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "jumpserver-client",
33
"author": "Fit2Cloud Technology Co., Ltd.; <[email protected]>",
4-
"version": "v3.0.0",
4+
"version": "v3.0.2",
55
"homepage": "https://jumpserver.org",
66
"main": "./out/main/index.js",
77
"scripts": {
@@ -29,6 +29,7 @@
2929
"electron-conf": "^1.2.1",
3030
"electron-store": "^10.0.0",
3131
"electron-updater": "^6.1.7",
32+
"lucide-vue-next": "^0.468.0",
3233
"mitt": "^3.0.1",
3334
"pinia": "^2.2.5",
3435
"pinia-plugin-persistedstate": "3.2.1",
@@ -51,6 +52,7 @@
5152
"@vicons/material": "^0.12.0",
5253
"@vicons/tabler": "^0.12.0",
5354
"@vitejs/plugin-vue": "^5.0.5",
55+
"@vitejs/plugin-vue-jsx": "^4.1.1",
5456
"@vue/eslint-config-prettier": "^9.0.0",
5557
"@vue/eslint-config-typescript": "^13.0.0",
5658
"autoprefixer": "^10.4.20",
@@ -61,15 +63,15 @@
6163
"eslint": "^8.57.0",
6264
"eslint-plugin-vue": "^9.26.0",
6365
"jsencrypt": "^3.2.1",
64-
"naive-ui": "^2.40.1",
66+
"naive-ui": "^2.41.0",
6567
"normalize.css": "^8.0.1",
6668
"postcss": "^8.4.47",
6769
"prettier": "^3.3.2",
6870
"sass": "^1.80.5",
6971
"typescript": "^5.5.2",
7072
"unplugin-auto-import": "^0.18.3",
7173
"unplugin-vue-components": "^0.27.4",
72-
"vite": "^5.4.10",
74+
"vite": "^6.0.0",
7375
"vue": "^3.4.30",
7476
"vue-tsc": "^2.0.22"
7577
}

ui/src/main/index.ts

+79-19
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,43 @@
11
import path, { join, resolve } from 'path';
22
import { Conf, useConf } from 'electron-conf/main';
3-
import icon from '../../resources/JumpServer.ico?asset';
4-
import { electronApp, is, optimizer } from '@electron-toolkit/utils';
3+
54
import { app, BrowserWindow, ipcMain, session, shell } from 'electron';
65

76
import { execFile } from 'child_process';
87
import { existsSync, readFileSync } from 'fs';
98

10-
let mainWindow: BrowserWindow | null = null;
11-
12-
const platform =
13-
process.platform === 'win32' ? 'windows' : process.platform === 'darwin' ? 'macos' : 'linux';
9+
import icon from '../../resources/JumpServer.ico?asset';
10+
import { electronApp, is, optimizer } from '@electron-toolkit/utils';
1411

1512
process.env['ELECTRON_DISABLE_SECURITY_WARNINGS'] = 'true';
1613

14+
let defaults = {
15+
windowBounds: {
16+
width: 1280,
17+
height: 800
18+
},
19+
defaultSetting: {
20+
theme: 'light',
21+
layout: 'list',
22+
language: 'en'
23+
}
24+
};
25+
let mainWindow: BrowserWindow | null = null;
26+
27+
const platform = process.platform === 'win32' ? 'windows' : process.platform === 'darwin' ? 'macos' : 'linux';
1728
const configFilePath = path.join(app.getPath('userData'), 'config.json');
18-
let defaults = {};
29+
1930
if (!existsSync(configFilePath)) {
2031
let subPath = path.join(process.resourcesPath);
32+
2133
if (is.dev) {
2234
subPath = 'bin';
2335
}
36+
2437
const data = readFileSync(path.join(subPath, 'config.json'), 'utf8');
2538
defaults = JSON.parse(data);
2639
}
40+
2741
const conf = new Conf({ defaults: defaults! });
2842

2943
const setDefaultProtocol = () => {
@@ -50,14 +64,12 @@ const handleUrl = (url: string) => {
5064
} else {
5165
handleClientPullUp(url);
5266
}
53-
console.error();
5467
} catch (error) {
5568
console.error('Failed to parse decoded token:', error);
5669
}
5770
}
5871
};
5972

60-
// Window
6173
const handleArgv = (argv: any) => {
6274
const offset = app.isPackaged ? 1 : 2;
6375
const url = argv.find((arg, i) => i >= offset && arg.startsWith('jms'));
@@ -95,16 +107,19 @@ const handleClientPullUp = (url: string) => {
95107
};
96108

97109
const createWindow = async (): Promise<void> => {
110+
const windowBounds = (conf.get('windowBounds') as { width: number; height: number }) || defaults.windowBounds;
111+
98112
mainWindow = new BrowserWindow({
99-
width: 1300,
100-
height: 800,
113+
width: windowBounds.width,
114+
height: windowBounds.height,
101115
show: false,
102116
frame: false, // 无边框窗口
103117
center: true,
104118
autoHideMenuBar: true,
105119
title: 'JumpServer Client',
106120
titleBarStyle: 'hidden',
107121
...(process.platform === 'linux' ? { icon } : { icon }),
122+
...(process.platform !== 'darwin' ? { titleBarOverlay: true } : {}),
108123
webPreferences: {
109124
preload: join(__dirname, '../preload/index.js'),
110125
sandbox: false,
@@ -133,16 +148,30 @@ const createWindow = async (): Promise<void> => {
133148
});
134149
});
135150

136-
if (is.dev && process.env['ELECTRON_RENDERER_URL']) {
137-
mainWindow.webContents.openDevTools();
138-
139-
const token =
140-
'eyJ0eXBlIjogImF1dGgiLCAiYmVhcmVyX3Rva2VuIjogImZpRlA3Uk82dzd0ZzhSeWtzRE5qS1NqYVdacjkwMFU4ZFZ4VSIsICJkYXRlX2V4cGlyZWQiOiAxNzMxNjIyMzIwLjgzNjc4Nn0=';
151+
mainWindow.on('close', () => {
152+
try {
153+
if (!mainWindow?.isDestroyed()) {
154+
const bounds = mainWindow?.getBounds();
155+
conf.set('windowBounds', bounds);
156+
}
157+
} catch (error) {
158+
console.error('Error saving window bounds:', error);
159+
}
160+
});
141161

142-
const decodedTokenJson = Buffer.from(token, 'base64').toString('utf-8');
143-
const decodedToken = JSON.parse(decodedTokenJson);
162+
mainWindow.on('resize', () => {
163+
try {
164+
if (!mainWindow?.isDestroyed()) {
165+
const bounds = mainWindow?.getBounds();
166+
conf.set('windowBounds', bounds);
167+
}
168+
} catch (error) {
169+
console.error('Error saving window bounds on resize:', error);
170+
}
171+
});
144172

145-
mainWindow?.webContents.send('set-token', decodedToken.bearer_token);
173+
if (is.dev && process.env['ELECTRON_RENDERER_URL']) {
174+
mainWindow.webContents.openDevTools();
146175

147176
await mainWindow.loadURL(process.env['ELECTRON_RENDERER_URL']);
148177
} else {
@@ -162,12 +191,24 @@ app.whenReady().then(async () => {
162191
optimizer.watchWindowShortcuts(window);
163192
});
164193

194+
app.on('certificate-error', (event, webContents, url, error, certificate, callback) => {
195+
//允许私有证书
196+
event.preventDefault();
197+
callback(true);
198+
});
199+
165200
conf.registerRendererListener();
166201
useConf();
167202

168203
await createWindow();
169204
setDefaultProtocol();
170205

206+
setTitleBar(conf.get('defaultSetting.theme') as string);
207+
208+
if (process.platform === 'win32') {
209+
handleArgv(process.argv);
210+
}
211+
171212
app.on('activate', function () {
172213
if (BrowserWindow.getAllWindows().length === 0) createWindow();
173214
});
@@ -189,6 +230,7 @@ app.whenReady().then(async () => {
189230

190231
// 除外 macOS 外,关闭所有窗口时退出 app
191232
app.on('window-all-closed', () => {
233+
// mainWindow 可能已经被销毁,所以不要再尝试访问它
192234
if (process.platform !== 'darwin') {
193235
app.quit();
194236
}
@@ -211,6 +253,24 @@ app.on('open-url', (_event: Event, url: string) => {
211253
handleUrl(url);
212254
});
213255

256+
const setTitleBar = (theme: string) => {
257+
if (mainWindow && process.platform !== 'darwin') {
258+
theme === 'dark'
259+
? mainWindow.setTitleBarOverlay({
260+
color: '#00000000',
261+
symbolColor: '#fff'
262+
})
263+
: mainWindow.setTitleBarOverlay({
264+
color: '#00000000',
265+
symbolColor: '#000'
266+
});
267+
}
268+
};
269+
270+
ipcMain.on('update-titlebar-overlay', (_, theme) => {
271+
setTitleBar(theme);
272+
});
273+
214274
ipcMain.on('open-client', (_, url) => {
215275
handleClientPullUp(url);
216276
});

ui/src/renderer/components.d.ts

+19
Original file line numberDiff line numberDiff line change
@@ -8,30 +8,43 @@ export {}
88
declare module 'vue' {
99
export interface GlobalComponents {
1010
Drawer: typeof import('./src/components/Drawer/index.vue')['default']
11+
ListContainer: typeof import('./src/components/ListContainer/index.vue')['default']
1112
ListItem: typeof import('./src/components/ListItem/index.vue')['default']
1213
LoginModal: typeof import('./src/components/LoginModal/index.vue')['default']
1314
MainSection: typeof import('./src/components/MainSection/index.vue')['default']
1415
NA: typeof import('naive-ui')['NA']
16+
NAvatar: typeof import('naive-ui')['NAvatar']
1517
NButton: typeof import('naive-ui')['NButton']
1618
NCard: typeof import('naive-ui')['NCard']
1719
NCollapse: typeof import('naive-ui')['NCollapse']
1820
NCollapseItem: typeof import('naive-ui')['NCollapseItem']
1921
NConfigProvider: typeof import('naive-ui')['NConfigProvider']
22+
NDataTable: typeof import('naive-ui')['NDataTable']
2023
NDescriptions: typeof import('naive-ui')['NDescriptions']
2124
NDescriptionsItem: typeof import('naive-ui')['NDescriptionsItem']
2225
NDivider: typeof import('naive-ui')['NDivider']
2326
NDrawer: typeof import('naive-ui')['NDrawer']
2427
NDrawerContent: typeof import('naive-ui')['NDrawerContent']
2528
NDropdown: typeof import('naive-ui')['NDropdown']
2629
NEllipsis: typeof import('naive-ui')['NEllipsis']
30+
NEmpty: typeof import('naive-ui')['NEmpty']
31+
NFl: typeof import('naive-ui')['NFl']
2732
NFlex: typeof import('naive-ui')['NFlex']
33+
NFlexl: typeof import('naive-ui')['NFlexl']
34+
NFom: typeof import('naive-ui')['NFom']
2835
NForm: typeof import('naive-ui')['NForm']
2936
NFormItem: typeof import('naive-ui')['NFormItem']
37+
NGi: typeof import('naive-ui')['NGi']
38+
NGrid: typeof import('naive-ui')['NGrid']
39+
NGridForm: typeof import('naive-ui')['NGridForm']
40+
NGridItem: typeof import('naive-ui')['NGridItem']
3041
NH3: typeof import('naive-ui')['NH3']
42+
NHighlight: typeof import('naive-ui')['NHighlight']
3143
NIcon: typeof import('naive-ui')['NIcon']
3244
NInfiniteScroll: typeof import('naive-ui')['NInfiniteScroll']
3345
NInput: typeof import('naive-ui')['NInput']
3446
NInputGroup: typeof import('naive-ui')['NInputGroup']
47+
NIocn: typeof import('naive-ui')['NIocn']
3548
NLayout: typeof import('naive-ui')['NLayout']
3649
NLayoutContent: typeof import('naive-ui')['NLayoutContent']
3750
NLayoutSider: typeof import('naive-ui')['NLayoutSider']
@@ -42,15 +55,21 @@ declare module 'vue' {
4255
NMessageProvider: typeof import('naive-ui')['NMessageProvider']
4356
NModal: typeof import('naive-ui')['NModal']
4457
NModalProvider: typeof import('naive-ui')['NModalProvider']
58+
NPopconfirm: typeof import('naive-ui')['NPopconfirm']
4559
NPopover: typeof import('naive-ui')['NPopover']
4660
NPopselect: typeof import('naive-ui')['NPopselect']
4761
NResult: typeof import('naive-ui')['NResult']
4862
NScrollbar: typeof import('naive-ui')['NScrollbar']
4963
NSelect: typeof import('naive-ui')['NSelect']
5064
NSpin: typeof import('naive-ui')['NSpin']
5165
NSwitch: typeof import('naive-ui')['NSwitch']
66+
NTabPane: typeof import('naive-ui')['NTabPane']
67+
NTabs: typeof import('naive-ui')['NTabs']
5268
NTag: typeof import('naive-ui')['NTag']
69+
NTex: typeof import('naive-ui')['NTex']
5370
NText: typeof import('naive-ui')['NText']
71+
NTooltip: typeof import('naive-ui')['NTooltip']
72+
RenderList: typeof import('./src/components/RenderList/index.vue')['default']
5473
RouterLink: typeof import('vue-router')['RouterLink']
5574
RouterView: typeof import('vue-router')['RouterView']
5675
}

0 commit comments

Comments
 (0)