Skip to content

Commit 394b7f5

Browse files
authored
Merge pull request #1489 from jumpserver/dev
v4.10.14
2 parents a43fdef + 4cd64bb commit 394b7f5

9 files changed

Lines changed: 312 additions & 67 deletions

File tree

src/app/elements/connect/connect.component.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,10 @@ export class ElementConnectComponent implements OnInit, OnDestroy {
169169
if (!this._settingSvc.hasXPack()) {
170170
appletConnectMethod = 'web';
171171
}
172+
let virtualappConnectMethod = connectOption ? connectOption['virtualappConnectMethod'] : 'web';
173+
if (!this._settingSvc.hasXPack()) {
174+
virtualappConnectMethod = 'web';
175+
}
172176

173177
if (connectInfo.downloadRDP) {
174178
return this._http.downloadRDPFile(
@@ -180,6 +184,8 @@ export class ElementConnectComponent implements OnInit, OnDestroy {
180184
this.callLocalClient(connToken).then();
181185
} else if (connectMethod.type === 'applet' && appletConnectMethod === 'client') {
182186
this.callLocalClient(connToken).then();
187+
} else if (connectMethod.type === 'virtual_app' && virtualappConnectMethod === 'client') {
188+
this.callLocalClient(connToken).then();
183189
} else {
184190
this.createWebView(asset, connectInfo, connToken);
185191
}

src/app/elements/content/content-window/magnus/magnus.component.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -112,8 +112,7 @@ export class ElementConnectorMagnusComponent implements OnInit {
112112
cli = `redis-cli` +
113113
` -h ${host}` +
114114
` -p ${port ? port : ''}` +
115-
` -a ${this.token.id}` +
116-
`@${passwordHolder}`;
115+
` -a ${passwordHolder}`;
117116
break;
118117
case 'oracle':
119118
cli = `sqlplus` +

src/app/elements/content/content.component.ts

Lines changed: 34 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import _ from 'lodash-es';
2-
import jQuery from 'jquery';
32
import { View, ViewAction } from '@app/model';
43
import { fromEvent, Subscription } from 'rxjs';
4+
import { I18nService } from '@app/services/i18n';
55
import { CdkDragDrop, moveItemInArray } from '@angular/cdk/drag-drop';
66
import {
77
ViewService,
@@ -60,8 +60,9 @@ export class ElementContentComponent implements OnInit, OnDestroy {
6060

6161
constructor(
6262
public _viewSvc: ViewService,
63-
private _connectTokenSvc: ConnectTokenService,
63+
private _i18nSvc: I18nService,
6464
private _settingSvc: SettingService,
65+
private _connectTokenSvc: ConnectTokenService,
6566
private _drawerStateService: DrawerStateService
6667
) {}
6768

@@ -116,9 +117,20 @@ export class ElementContentComponent implements OnInit, OnDestroy {
116117
onNewView(view) {
117118
this.scrollEnd();
118119
this.toggleMenu.emit();
119-
setTimeout(() => {
120-
this._viewSvc.addView(view);
121-
this.setViewActive(view);
120+
121+
setTimeout(async () => {
122+
// 如果已经打开了 15 个,那么弹出一个确认框,点击确认重新再一个新的浏览器 tab 下打开 luna 应用
123+
if (this.viewList.length >= 15) {
124+
const msg = await this._i18nSvc.t('tabLimits');
125+
const ok = window.confirm(msg);
126+
127+
if (ok) {
128+
window.open(window.location.href, '_blank');
129+
}
130+
} else {
131+
this._viewSvc.addView(view);
132+
this.setViewActive(view);
133+
}
122134
}, 100);
123135
}
124136

@@ -208,16 +220,26 @@ export class ElementContentComponent implements OnInit, OnDestroy {
208220
{
209221
title: 'Clone Connect',
210222
icon: 'fa-copy',
211-
callback: () => {
223+
callback: async () => {
212224
const id = this.rIdx + 1;
213225
const oldId = this.viewIds[this.rIdx];
214226
const oldView = this.viewList.find(i => i.id === oldId);
215227
const oldConnectToken = oldView.connectToken;
216-
this._connectTokenSvc.exchange(oldConnectToken).then(newConnectToken => {
217-
const newView = new View(oldView.asset, oldView.connectData, newConnectToken);
218-
this._viewSvc.addView(newView);
219-
this.setViewActive(newView);
220-
});
228+
229+
if (this.viewList.length >= 15) {
230+
const msg = await this._i18nSvc.t('tabLimits');
231+
const ok = window.confirm(msg);
232+
233+
if (ok) {
234+
window.open(window.location.href, '_blank');
235+
}
236+
} else {
237+
this._connectTokenSvc.exchange(oldConnectToken).then(newConnectToken => {
238+
const newView = new View(oldView.asset, oldView.connectData, newConnectToken);
239+
this._viewSvc.addView(newView);
240+
this.setViewActive(newView);
241+
});
242+
}
221243
}
222244
},
223245
{
@@ -227,7 +249,7 @@ export class ElementContentComponent implements OnInit, OnDestroy {
227249
const viewId = this.viewIds[this.rIdx];
228250
const currentView = this.viewList.find(i => i.id === viewId);
229251
this._drawerStateService.sendComponentMessage({
230-
name: 'DRAWER_RECONNECT',
252+
name: 'DRAWER_RECONNECT'
231253
});
232254
currentView.termComp.reconnect();
233255
}

src/app/elements/iframe/iframe.component.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
[src]="src | safeUrl"
1414
[style.visibility]="showIframe ? 'visible' : 'hidden'"
1515
allowtransparency="true"
16+
allow="clipboard-read; clipboard-write"
1617
height="100%"
1718
width="100%"
1819
>

src/app/elements/iframe/iframe.component.ts

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,8 @@ export class ElementIframeComponent implements OnInit, AfterViewInit, OnDestroy
124124
}
125125
break;
126126
case 'CLICK':
127+
this.renewalTrigger.next();
128+
127129
document.body.click();
128130
document.dispatchEvent(
129131
new MouseEvent('mouseup', {
@@ -138,12 +140,6 @@ export class ElementIframeComponent implements OnInit, AfterViewInit, OnDestroy
138140
this._viewSvc.keyboardSwitchTab(msg.data);
139141
}, 200);
140142
break;
141-
case 'KEYBOARDEVENT':
142-
case 'MOUSEEVENT':
143-
this.renewalTrigger.next();
144-
// Lion 组件 默认会发送的 KEYBOARDEVENT 和 MOUSEEVENT
145-
this.sendInputActiveToOtherViews();
146-
break;
147143
case 'CREATE_FILE_CONNECT_TOKEN':
148144
this.createFileConnectToken.emit(true);
149145
break;
@@ -157,7 +153,10 @@ export class ElementIframeComponent implements OnInit, AfterViewInit, OnDestroy
157153
this.view.terminalContentData = msg.data;
158154
this._iframeSvc.sendMessage({ name: 'TERMINAL_CONTENT_RESPONSE', data: msg.data });
159155
break;
156+
case 'KEYBOARDEVENT':
157+
case 'MOUSEEVENT':
160158
case 'INPUT_ACTIVE':
159+
this.renewalTrigger.next();
161160
// KOKO 新定义的 input 事件,给所有其他 view 发送 sendInputActive 函数续期
162161
this.sendInputActiveToOtherViews();
163162
}

src/app/pages/connect/connect.component.html

Lines changed: 30 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,32 @@
11
<app-face-monitor *ngIf="isAdminConnect"></app-face-monitor>
22
<elements-chat></elements-chat>
33

4+
<ng-template #timerWidget>
5+
<div
6+
*ngIf="isTimerVisible"
7+
class="timer-container"
8+
[class.dragging]="isTimerDragging"
9+
[ngStyle]="getTimerContainerStyle()"
10+
(pointerdown)="onTimerPointerDown($event)"
11+
(pointermove)="onTimerPointerMove($event)"
12+
(pointerup)="onTimerPointerUp($event)"
13+
(pointercancel)="onTimerPointerUp($event)"
14+
>
15+
<div class="timer">
16+
<div [class.active]="isActive" class="status-dot"></div>
17+
<span class="time-value">{{ totalConnectTime }}</span>
18+
<span
19+
class="timer-close"
20+
nz-icon
21+
nzType="close"
22+
nzTheme="outline"
23+
(pointerdown)="$event.stopPropagation()"
24+
(click)="hideTimer()"
25+
></span>
26+
</div>
27+
</div>
28+
</ng-template>
29+
430
<div #contentWindow *ngIf="isDirect">
531
<div class="terminal-connect" *ngIf="view && isTerminalComponent()">
632
<div *ngIf="isWebSftp()" style="height: 100%; width: 100%">
@@ -55,12 +81,7 @@
5581
</div>
5682
</div> -->
5783
</div>
58-
<div class="timer-container">
59-
<div class="timer">
60-
<div [class.active]="isActive" class="status-dot"></div>
61-
<span>{{ totalConnectTime }}</span>
62-
</div>
63-
</div>
84+
<ng-container *ngTemplateOutlet="timerWidget"></ng-container>
6485
<nz-card class="terminal-card" [nzBordered]="false">
6586
<div class="card-content" style="height: 100%; overflow: hidden">
6687
<elements-content-window #contentWindow *ngIf="view" [view]="view">
@@ -71,12 +92,7 @@
7192
</div>
7293

7394
<div class="gui" *ngIf="view && isGuiComponent()">
74-
<div class="timer-container">
75-
<div class="timer">
76-
<div [class.active]="isActive" class="status-dot"></div>
77-
<span>{{ totalConnectTime }}</span>
78-
</div>
79-
</div>
95+
<ng-container *ngTemplateOutlet="timerWidget"></ng-container>
8096

8197
<div class="action-icons" [class.show]="showActionIcons">
8298
<div class="close-icon" (click)="handleCloseConnect()">
@@ -156,12 +172,7 @@
156172
</div>
157173
</div>
158174
</div>
159-
<div class="timer-container">
160-
<div class="timer">
161-
<div [class.active]="isActive" class="status-dot"></div>
162-
<span>{{ totalConnectTime }}</span>
163-
</div>
164-
</div>
175+
<ng-container *ngTemplateOutlet="timerWidget"></ng-container>
165176
<nz-card class="terminal-card" [nzBordered]="false">
166177
<div class="card-content" style="height: 100%; overflow: hidden">
167178
<elements-connect
@@ -176,12 +187,7 @@
176187
</div>
177188

178189
<div class="gui" *ngIf="view && isGuiComponent()">
179-
<div class="timer-container">
180-
<div class="timer">
181-
<div [class.active]="isActive" class="status-dot"></div>
182-
<span>{{ totalConnectTime }}</span>
183-
</div>
184-
</div>
190+
<ng-container *ngTemplateOutlet="timerWidget"></ng-container>
185191

186192
<div class="action-icons" [class.show]="showActionIcons">
187193
<div class="close-icon" (click)="handleCloseConnect()">

src/app/pages/connect/connect.component.scss

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,13 @@
33
bottom: 40px;
44
right: 30px;
55
z-index: 999999;
6+
touch-action: none;
7+
8+
&.dragging {
9+
.timer {
10+
cursor: grabbing;
11+
}
12+
}
613

714
.timer {
815
display: flex;
@@ -14,8 +21,10 @@
1421
font-family: monospace;
1522
font-size: 14px;
1623
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
24+
cursor: grab;
25+
user-select: none;
1726

18-
span {
27+
.time-value {
1928
margin-left: 4px;
2029
}
2130

@@ -31,6 +40,23 @@
3140
animation: blink 1s infinite;
3241
}
3342
}
43+
44+
.timer-close {
45+
display: inline-flex;
46+
align-items: center;
47+
justify-content: center;
48+
margin-left: 8px;
49+
width: 18px;
50+
height: 18px;
51+
border-radius: 50%;
52+
cursor: pointer;
53+
color: rgba(255, 255, 255, 0.9);
54+
55+
&:hover {
56+
background: rgba(255, 255, 255, 0.15);
57+
color: rgba(255, 255, 255, 1);
58+
}
59+
}
3460
}
3561

3662
@media screen and (max-width: 768px) {

0 commit comments

Comments
 (0)