Skip to content

Commit a43fdef

Browse files
authored
Merge pull request #1474 from jumpserver/dev
v4.10.13-lts
2 parents 42246be + 52cb6ff commit a43fdef

10 files changed

Lines changed: 93 additions & 53 deletions

File tree

src/app/elements/asset-tree/asset-tree.component.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -241,7 +241,7 @@ export class ElementAssetTreeComponent implements OnInit {
241241
}
242242

243243
if (treeNode.meta.data.platform_type === 'k8s') {
244-
return connectOnNewPage(treeNode, 'auto');
244+
return connectOnNewPage(treeNode, 'new');
245245
}
246246

247247
if (this.isOpenNewWindow) {
@@ -465,6 +465,7 @@ export class ElementAssetTreeComponent implements OnInit {
465465
}
466466

467467
async connectAsset(node: TreeNode) {
468+
await this._appSvc.getConnectMethods();
468469
const action = 'asset';
469470
const evt = new ConnectEvt(node, action);
470471
connectEvt.next(evt);
@@ -565,6 +566,7 @@ export class ElementAssetTreeComponent implements OnInit {
565566
return;
566567
}
567568
const node = this.rightClickSelectNode;
569+
await this._appSvc.getConnectMethods();
568570
const action = 'connect';
569571
const evt = splitConnect ? new ConnectEvt(node, action, true) : new ConnectEvt(node, action);
570572
connectEvt.next(evt);

src/app/elements/connect/connect-dialog/select-account/select-account.component.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { User } from '@app/globals';
22
import { FormControl } from '@angular/forms';
3-
import { AppService, I18nService } from '@app/services';
3+
import { AppService, I18nService, SettingService } from '@app/services';
44
import { BehaviorSubject, ReplaySubject, Subject } from 'rxjs';
55
import { Account, AccountGroup, Asset, AuthInfo, Protocol } from '@app/model';
66

@@ -36,7 +36,7 @@ export class ElementSelectAccountComponent implements OnInit, OnDestroy {
3636
@ViewChild('password', { static: false }) passwordRef: ElementRef;
3737

3838
public hidePassword = true;
39-
public rememberAuthDisabled = false;
39+
public rememberAuthDisabled = null;
4040
usernameControl = new FormControl();
4141
localAuthItems: AuthInfo[];
4242
filteredOptions: AuthInfo[];
@@ -51,11 +51,13 @@ export class ElementSelectAccountComponent implements OnInit, OnDestroy {
5151
private userManuallySelected = false; // 标记用户是否手动选择了账号
5252

5353
constructor(
54+
private _settingSvc: SettingService,
5455
private _appSvc: AppService,
5556
private _i18n: I18nService,
5657
private _cdRef: ChangeDetectorRef
5758
) {
5859
this.usernamePlaceholder = this._i18n.instant('Username');
60+
this.rememberAuthDisabled = !this._settingSvc.globalSetting.SECURITY_LUNA_REMEMBER_AUTH;
5961
}
6062

6163
get noSecretAccounts() {

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,15 +187,20 @@ export class ElementConnectComponent implements OnInit, OnDestroy {
187187

188188
async callLocalClient(connToken: ConnectionToken) {
189189
this._logger.debug('Call local client');
190+
190191
if (connToken.connect_options.token_reusable) {
191192
await this._connectTokenSvc.setReusable(connToken, true).toPromise();
192193
}
194+
193195
const response = await firstValueFrom(
194196
this._http.getLocalClientUrl(connToken, this._settingSvc.setting)
195197
);
198+
196199
const url = response['url'];
200+
197201
launchLocalApp(url, () => {
198202
const downLoadStatus = localStorage.getItem('hasDownLoadApp');
203+
199204
if (downLoadStatus !== '1') {
200205
this._dialog.create({
201206
nzTitle: this._i18n.instant('DownloadClient'),

src/app/elements/replay/asciicast/asciicast.component.ts

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -170,10 +170,10 @@ export class ElementReplayAsciicastComponent implements OnInit, AfterViewInit {
170170
/**
171171
* 重置播放器并保持当前播放位置和状态
172172
*/
173-
private resetPlayerWithCurrentTime() {
173+
private async resetPlayerWithCurrentTime() {
174174
if (!this.player) return;
175175

176-
this.currentTime = this.player.getCurrentTime();
176+
this.currentTime = await this.player.getCurrentTime();
177177

178178
if (isNaN(this.currentTime) || this.currentTime < 0) {
179179
this.currentTime = 0;
@@ -204,8 +204,6 @@ export class ElementReplayAsciicastComponent implements OnInit, AfterViewInit {
204204
speed: this.speed,
205205
preload: true,
206206
autoPlay: this.isPlaying ? 1 : 0,
207-
rows: this.rows,
208-
cols: 100,
209207
fit: false,
210208
terminalFontSize: '12px'
211209
};

src/app/elements/replay/mp4/mp4.component.html

Lines changed: 40 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,53 +1,58 @@
11
<div class="replay-container">
22
<!-- 信息头部 -->
3-
<div class="info-header">
4-
<div class="info-item" *ngIf="replay.user">
5-
<span class="label">{{ "user" | translate }}:</span>
6-
<span class="value">{{ replay.user }}</span>
7-
</div>
8-
<div class="info-item" *ngIf="replay.asset">
9-
<span class="label">{{ "asset" | translate }}:</span>
10-
<span class="value">{{ replay.asset }}</span>
11-
</div>
12-
<div class="info-item" *ngIf="replay.system_user">
13-
<span class="label">{{ "system user" | translate }}:</span>
14-
<span class="value">{{ replay.system_user }}</span>
15-
</div>
16-
<div class="info-item" *ngIf="replay.date_start">
17-
<span class="label">{{ "start time" | translate }}:</span>
18-
<span class="value">{{ startTime }}</span>
19-
</div>
20-
<div class="info-actions">
21-
<a *ngIf="replay.download_url" [href]="replay.download_url" class="download-link">
22-
{{ "download" | translate }}
23-
</a>
3+
@if (!type) {
4+
<div class="info-header">
5+
<div class="info-item" *ngIf="replay.user">
6+
<span class="label">{{ 'user' | translate }}:</span>
7+
<span class="value">{{ replay.user }}</span>
8+
</div>
9+
<div class="info-item" *ngIf="replay.asset">
10+
<span class="label">{{ 'asset' | translate }}:</span>
11+
<span class="value">{{ replay.asset }}</span>
12+
</div>
13+
<div class="info-item" *ngIf="replay.system_user">
14+
<span class="label">{{ 'system user' | translate }}:</span>
15+
<span class="value">{{ replay.system_user }}</span>
16+
</div>
17+
<div class="info-item" *ngIf="replay.date_start">
18+
<span class="label">{{ 'start time' | translate }}:</span>
19+
<span class="value">{{ startTime }}</span>
20+
</div>
21+
<div class="info-actions">
22+
<a *ngIf="replay.download_url" [href]="replay.download_url" class="download-link">
23+
{{ 'download' | translate }}
24+
</a>
25+
</div>
2426
</div>
25-
</div>
27+
}
2628

27-
<!-- 主体内容 -->
2829
<div class="main-content">
2930
<!-- 视频播放区 -->
3031
<div class="video-area">
3132
<video controls>
32-
<source [src]="replay.src" type="video/mp4">
33+
<source [src]="replay.src" type="video/mp4" />
3334
</video>
3435
</div>
3536

3637
<!-- 命令列表 -->
3738
<div class="commands-area" *ngIf="commands.length > 0">
3839
<div class="commands-header">
39-
<span>{{ "Commands" | translate }} ({{ commands.length }})</span>
40+
<span>{{ 'Commands' | translate }} ({{ commands.length }})</span>
4041
</div>
41-
<div class="commands-list"
42-
infiniteScroll
43-
[infiniteScrollDistance]="2"
44-
[infiniteScrollThrottle]="50"
45-
(scrolled)="onScroll()"
46-
[scrollWindow]="false">
47-
<div class="command-item"
48-
*ngFor="let item of commands"
49-
(click)="commandClick(item)"
50-
[title]="item.input">
42+
<div
43+
class="commands-list"
44+
infiniteScroll
45+
[infiniteScrollDistance]="2"
46+
[infiniteScrollThrottle]="50"
47+
(scrolled)="onScroll()"
48+
[scrollWindow]="false"
49+
>
50+
<div
51+
class="command-item"
52+
*ngFor="let item of commands"
53+
(click)="commandClick(item)"
54+
[title]="item.input"
55+
>
5156
<div class="command-text">{{ item.input }}</div>
5257
<div class="command-time">{{ item.atime }}</div>
5358
</div>

src/app/elements/replay/mp4/mp4.component.scss

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -205,7 +205,7 @@ video {
205205
// 主内容区
206206
.main-content {
207207
display: flex;
208-
flex: 1;
208+
// flex: 1;
209209
min-height: 0;
210210

211211
// 视频区域
@@ -217,8 +217,8 @@ video {
217217
justify-content: center;
218218

219219
video {
220-
width: 100%;
221-
height: 100%;
220+
// width: 100%;
221+
// height: 100%;
222222
max-width: 100%;
223223
max-height: 100%;
224224
object-fit: contain;

src/app/elements/replay/mp4/mp4.component.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
import {Component, Input, OnInit} from '@angular/core';
1+
import {Component, Input, OnInit, Output,
2+
EventEmitter} from '@angular/core';
23
import {Command, Replay} from '@app/model';
34
import {HttpService} from '@app/services';
45
import {TranslateService} from '@ngx-translate/core';
@@ -12,6 +13,9 @@ import {formatTime} from '@app/utils/common';
1213
})
1314
export class ElementsReplayMp4Component implements OnInit {
1415
@Input() replay: Replay;
16+
@Input() type: string | undefined;
17+
@Output() ready = new EventEmitter<void>();
18+
1519
startTime = null;
1620
startTimeStamp = null;
1721
commands: Command[];
@@ -30,6 +34,7 @@ export class ElementsReplayMp4Component implements OnInit {
3034
this.getCommands(this.page);
3135
this.height = window.innerHeight - 100;
3236
this.width = window.innerWidth - 100;
37+
this.ready.emit();
3338
}
3439

3540
toSafeLocalDateStr(d) {

src/app/elements/replay/parts/parts.component.html

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@
2828
</div>
2929
</div>
3030

31-
<!-- 主体内容 -->
3231
<div class="main-content">
3332
<!-- 视频播放区 -->
3433
<div class="video-area" [class.playlist-hidden]="playlistCollapsed">
@@ -39,12 +38,18 @@
3938
<i nz-icon nzType="menu" nzTheme="outline"></i>
4039
{{ 'Playlist' | translate }}
4140
</button>
42-
<elements-replay-guacamole
41+
42+
@if(this.replayType === 'mp4') {
43+
<elements-replay-mp4 *ngIf="currentVideo && currentVideo.src" (ready)="videoLoading = false"
44+
[replay]="currentVideo" type="parts" class="video-player"></elements-replay-mp4>
45+
} @else {
46+
<elements-replay-guacamole
4347
*ngIf="currentVideo && currentVideo.src"
4448
[replay]="currentVideo"
4549
(ready)="videoLoading = false"
4650
class="video-player">
4751
</elements-replay-guacamole>
52+
}
4853
</div>
4954

5055
<!-- 播放列表 -->

src/app/services/app.ts

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -200,11 +200,19 @@ export class AppService {
200200
return null;
201201
}
202202

203-
getConnectMethods() {
203+
getConnectMethods(): Promise<void> {
204204
const url = '/api/v1/terminal/components/connect-methods/';
205-
this._http.get(url).subscribe(response => {
206-
this.protocolConnectTypesMap = response;
207-
});
205+
206+
// 当用户先打开 luna 并进行操作时如果后在 lina 中去设置连接方式的 ACL 此时并不生效,因此修改为在 toPromise 后直接赋值
207+
return this._http
208+
.get(url)
209+
.toPromise()
210+
.then(response => {
211+
this.protocolConnectTypesMap = response;
212+
})
213+
.catch(error => {
214+
this._logger.error('Get connect methods error:', error);
215+
});
208216
}
209217

210218
getProtocolConnectMethods(protocol: string) {
@@ -338,7 +346,7 @@ export class AppService {
338346
newAuth.alias = account.alias;
339347
}
340348

341-
if (!auth.secret || !auth.rememberAuth) {
349+
if (!auth.secret || !auth.rememberAuth || !this._settingSvc.globalSetting.SECURITY_LUNA_REMEMBER_AUTH) {
342350
newAuth.secret = '';
343351
} else {
344352
newAuth.secret = this.encrypt(auth.secret);

src/app/utils/common.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -341,24 +341,34 @@ export function launchLocalApp(url, fail) {
341341
export function connectOnNewPage(node: TreeNode, newWindowMode?: string) {
342342
const url = `/luna/connect?login_to=${node.id}&type=${node.meta.type}`;
343343
let params = 'toolbar=yes,scrollbars=yes,resizable=yes';
344+
345+
// auto 模式:尺寸为屏幕的三分之一并根据会话内的计数在屏幕上“级联/平铺”位置
344346
if (newWindowMode === 'auto') {
345347
let count: number;
346348
let top = 50;
349+
347350
count = parseInt(window.sessionStorage.getItem('newWindowCount'), 10);
351+
348352
if (isNaN(count)) {
349353
count = 0;
350354
}
355+
351356
let left = 100 + count * 100;
352357
top = 50 + count * 50;
358+
353359
if (left + screen.width / 3 > screen.width) {
354360
// 支持两排足以
355361
top = screen.height / 3;
356362
count = 1;
357363
left = 100;
358364
}
365+
359366
params = params + `,top=${top},left=${left},width=${screen.width / 3},height=${screen.height / 3}`;
360367
window.sessionStorage.setItem('newWindowCount', `${count + 1}`);
368+
361369
window.open(url, '_blank', params);
370+
371+
// auto 模式:尺寸为当前窗口的 innerWidth x innerHeight;位置固定在 top=50,left=100
362372
} else if (newWindowMode === 'new') {
363373
params = params + `,top=50,left=100,width=${window.innerWidth},height=${window.innerHeight}`;
364374
window.open(url, '_blank', params);

0 commit comments

Comments
 (0)