Skip to content

Commit 7272a0a

Browse files
committed
添加引导页功能
1 parent 9f6b3aa commit 7272a0a

File tree

14 files changed

+253
-12
lines changed

14 files changed

+253
-12
lines changed

angular.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@
5555
}
5656
],
5757
"styles": [
58+
"node_modules/driver.js/dist/driver.min.css",
5859
{
5960
"input": "src/styles/default.less",
6061
"bundleName": "default",
@@ -69,7 +70,9 @@
6970
"stylePreprocessorOptions": {
7071
"includePaths": ["src/styles/themes"]
7172
},
72-
"scripts": [],
73+
"scripts": [
74+
"node_modules/driver.js/dist/driver.min.js"
75+
],
7376
"allowedCommonJsDependencies": [
7477
"qs",
7578
"size-sensor",

package-lock.json

Lines changed: 5 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
"@antv/l7-source": "2.5.7",
3131
"@antv/l7-utils": "2.5.7",
3232
"@auth0/angular-jwt": "^5.0.2",
33+
"driver.js": "^0.9.8",
3334
"ng-zorro-antd": "^12.0.1",
3435
"ngx-quicklink": "^0.2.7",
3536
"rxjs": "~6.6.0",

src/app/config/constant.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ export const TokenPre = 'Bearer ';
33
export const AuthKey = 'Authorization';
44
export const IsNightKey = 'IsNightKey';
55
export const ThemeOptionsKey = 'ThemeOptionsKey';
6+
export const IsFirstLogin = 'IsFirstLogin';
67

78

89
export const SideCollapsedMaxWidth = 700;
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
import {Inject, Injectable} from '@angular/core';
2+
import Driver from 'driver.js';
3+
import {DOCUMENT} from "@angular/common";
4+
5+
@Injectable({
6+
providedIn: 'root'
7+
})
8+
export class DriverService {
9+
10+
constructor(@Inject(DOCUMENT) private doc: Document) {
11+
}
12+
13+
/*
14+
* https://madewith.cn/766
15+
* */
16+
load(): void {
17+
const driver = new Driver({
18+
animate: false,
19+
allowClose: true,
20+
doneBtnText: '完成',
21+
closeBtnText: '关闭',
22+
nextBtnText: '下一步',
23+
prevBtnText: '上一步',
24+
onHighlightStarted: () => {
25+
this.doc.body.style.cssText = 'overflow:hidden';
26+
},
27+
onReset: () => {
28+
this.doc.body.style.cssText = 'overflow:auto';
29+
}
30+
});
31+
driver.defineSteps([
32+
{
33+
element: '#menuNav',
34+
popover: {
35+
title: '菜单',
36+
description: '这里是菜单',
37+
position: 'right-center'
38+
}
39+
},
40+
{
41+
element: '#drawer-handle',
42+
popover: {
43+
title: '主题设置按钮',
44+
description: '点击展开设置主题',
45+
position: 'left'
46+
}
47+
},
48+
{
49+
element: '#tools',
50+
popover: {
51+
title: '工具栏',
52+
description: '搜索菜单,帮助文档,通知消息,退出登录,多语言',
53+
position: 'bottom'
54+
}
55+
},
56+
{
57+
element: '#chats',
58+
popover: {
59+
title: '联系管理员',
60+
description: '跟管理员联系联系',
61+
position: 'top'
62+
}
63+
},
64+
{
65+
element: '#trigger',
66+
popover: {
67+
title: '折叠菜单',
68+
description: '点击可以折叠菜单',
69+
position: 'bottom'
70+
}
71+
},
72+
{
73+
element: '#multi-tab',
74+
popover: {
75+
title: '多标签',
76+
description: '鼠标右键点击单个标签可以展开多个选项',
77+
position: 'bottom'
78+
}
79+
},
80+
]);
81+
driver.start();
82+
}
83+
}
Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
import { DOCUMENT } from '@angular/common';
2+
import { Inject, Injectable } from '@angular/core';
3+
import { BehaviorSubject, Observable } from 'rxjs';
4+
import { filter, share } from 'rxjs/operators';
5+
6+
import type { NzSafeAny } from 'ng-zorro-antd/core/types';
7+
8+
export interface LazyResult {
9+
path: string;
10+
status: 'ok' | 'error' | 'loading';
11+
error?: NzSafeAny;
12+
}
13+
// this.lazy.load(["https://unpkg.com/driver.js/dist/driver.min.js", "https://unpkg.com/driver.js/dist/driver.min.css"]).then(() => {
14+
15+
/**
16+
* 延迟加载资源(js 或 css)服务
17+
*/
18+
@Injectable({ providedIn: 'root' })
19+
export class LazyService {
20+
private list: { [key: string]: boolean } = {};
21+
private cached: { [key: string]: LazyResult } = {};
22+
private _notify: BehaviorSubject<LazyResult[]> = new BehaviorSubject<LazyResult[]>([]);
23+
24+
constructor(@Inject(DOCUMENT) private doc: NzSafeAny) {}
25+
26+
get change(): Observable<LazyResult[]> {
27+
return this._notify.asObservable().pipe(
28+
share(),
29+
filter(ls => ls.length !== 0)
30+
);
31+
}
32+
33+
clear(): void {
34+
this.list = {};
35+
this.cached = {};
36+
}
37+
38+
load(paths: string | string[]): Promise<LazyResult[]> {
39+
if (!Array.isArray(paths)) {
40+
paths = [paths];
41+
}
42+
43+
const promises: Array<Promise<LazyResult>> = [];
44+
paths.forEach(path => {
45+
if (path.endsWith('.js')) {
46+
promises.push(this.loadScript(path));
47+
} else {
48+
promises.push(this.loadStyle(path));
49+
}
50+
});
51+
52+
return Promise.all(promises).then(res => {
53+
this._notify.next(res);
54+
return Promise.resolve(res);
55+
});
56+
}
57+
58+
loadScript(path: string, innerContent?: string): Promise<LazyResult> {
59+
return new Promise(resolve => {
60+
if (this.list[path] === true) {
61+
resolve({ ...this.cached[path], status: 'loading' });
62+
return;
63+
}
64+
65+
this.list[path] = true;
66+
const onSuccess = (item: LazyResult) => {
67+
this.cached[path] = item;
68+
resolve(item);
69+
this._notify.next([item]);
70+
};
71+
72+
const node = this.doc.createElement('script') as NzSafeAny;
73+
node.type = 'text/javascript';
74+
node.src = path;
75+
node.charset = 'utf-8';
76+
if (innerContent) {
77+
node.innerHTML = innerContent;
78+
}
79+
if (node.readyState) {
80+
// IE
81+
node.onreadystatechange = () => {
82+
if (node.readyState === 'loaded' || node.readyState === 'complete') {
83+
node.onreadystatechange = null;
84+
onSuccess({
85+
path,
86+
status: 'ok'
87+
});
88+
}
89+
};
90+
} else {
91+
node.onload = () =>
92+
onSuccess({
93+
path,
94+
status: 'ok'
95+
});
96+
}
97+
node.onerror = (error: NzSafeAny) =>
98+
onSuccess({
99+
path,
100+
status: 'error',
101+
error
102+
});
103+
this.doc.getElementsByTagName('head')[0].appendChild(node);
104+
});
105+
}
106+
107+
loadStyle(path: string, rel: string = 'stylesheet', innerContent?: string): Promise<LazyResult> {
108+
return new Promise(resolve => {
109+
if (this.list[path] === true) {
110+
resolve(this.cached[path]);
111+
return;
112+
}
113+
114+
this.list[path] = true;
115+
116+
const node = this.doc.createElement('link') as HTMLLinkElement;
117+
node.rel = rel;
118+
node.type = 'text/css';
119+
node.href = path;
120+
if (innerContent) {
121+
node.innerHTML = innerContent;
122+
}
123+
this.doc.getElementsByTagName('head')[0].appendChild(node);
124+
const item: LazyResult = {
125+
path,
126+
status: 'ok'
127+
};
128+
this.cached[path] = item;
129+
resolve(item);
130+
});
131+
}
132+
}

src/app/layout/default/def-layout-content/def-layout-content.component.html

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212

1313
<!--非混合模式侧边栏-->
1414
<nz-sider
15+
id="menuNav"
1516
[class.left-nav-fixed]="isFixedLeftNav"
1617
*ngIf="!isMixiMode&&((themesOptions$|async)!.mode==='side')&&!(isOverMode$|async)&&(themesOptions$|async)!.hasNavArea"
1718
class="menu-sidebar"
@@ -31,7 +32,7 @@
3132

3233
<nz-layout [style]="{marginTop:isMixiMode&&themesOptions.hasTopArea?'48px':0}">
3334
<!--sider模式的 header-->
34-
<nz-header style="transition:width 0.2s"
35+
<nz-header style="transition:width 0.2s"
3536
*ngIf="!isMixiMode&&themesOptions.hasTopArea&&themesOptions.mode==='side'"
3637
[ngClass]="{
3738
'full-with':!themesOptions.hasNavArea,
@@ -89,7 +90,7 @@
8990

9091
<app-setting-drawer></app-setting-drawer>
9192

92-
<app-chat (changeShows)="showChats=false" *ngIf="showChats"></app-chat>
93+
<app-chat (changeShows)="showChats=false" *ngIf="showChats"></app-chat>
9394

9495
<ng-template #trigger>
9596
<ul nz-menu [nzTheme]="(isMixiMode&&!(isOverMode$|async))?'light':(themesOptions$|async)!.theme" nzMode="inline"

src/app/layout/default/def-layout-content/def-layout-content.component.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ export class DefLayoutContentComponent implements OnInit {
3636
mixiModeHasLeftNav = this.splitNavStoreService.getSplitLeftNavArrayStore();
3737
private destory$ = new Subject<void>();
3838

39-
constructor(private themesService: ThemeService, private splitNavStoreService: SplitNavStoreService) {
39+
constructor( private themesService: ThemeService, private splitNavStoreService: SplitNavStoreService) {
4040
}
4141

4242
changeCollapsed(isCollapsed: boolean): void {
@@ -53,6 +53,7 @@ export class DefLayoutContentComponent implements OnInit {
5353

5454
ngOnInit(): void {
5555
this.getThemeOptions();
56+
5657
}
5758

5859
ngOnDestroy(): void {

src/app/layout/default/default.component.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
<ng-template #headerTpl>
1919
<app-tool-bar>
2020
<ng-container left *ngIf="isOverMode||(themeOptions$|async)!.mode==='side';else topHeadTpl">
21-
<i class="trigger" nz-icon [nzType]="(isCollapsed$|async) ? 'menu-unfold' : 'menu-fold'"
21+
<i id="trigger" class="trigger" nz-icon [nzType]="(isCollapsed$|async) ? 'menu-unfold' : 'menu-fold'"
2222
(click)="changeCollapsed()"></i>
2323
</ng-container>
2424
<ng-template #topHeadTpl>

src/app/layout/default/default.component.ts

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
1-
import {Component, OnInit, ChangeDetectionStrategy, OnDestroy, ViewChild} from '@angular/core';
1+
import {Component, OnInit, ChangeDetectionStrategy, OnDestroy, ViewChild, AfterViewInit} from '@angular/core';
22
import {ThemeService} from "../../core/services/store/theme.service";
33
import {Subject} from "rxjs";
44
import {takeUntil} from "rxjs/operators";
55
import {NavDrawerComponent} from "./nav-drawer/nav-drawer.component";
66
import {RouterOutlet} from "@angular/router";
77
import {fadeRouteAnimation} from "../../animations/fade.animation";
8+
import {DriverService} from "../../core/services/common/driver.service";
9+
import {WindowService} from "../../core/services/common/window.service";
10+
import {IsFirstLogin} from "../../config/constant";
811

912
@Component({
1013
selector: 'app-default',
@@ -15,15 +18,26 @@ import {fadeRouteAnimation} from "../../animations/fade.animation";
1518
fadeRouteAnimation
1619
]
1720
})
18-
export class DefaultComponent implements OnInit, OnDestroy {
21+
export class DefaultComponent implements OnInit, OnDestroy, AfterViewInit {
1922
isCollapsed$ = this.themesService.getIsCollapsed();
2023
themeOptions$ = this.themesService.getThemesMode();
2124
isCollapsed = false;
2225
isOverMode = false; // 窗口变窄时,导航栏是否变成抽屉模式
2326
private destory$ = new Subject<void>();
2427
@ViewChild('navDrawer') navDrawer!: NavDrawerComponent
2528

26-
constructor(private themesService: ThemeService) {
29+
constructor(private themesService: ThemeService, private driverService: DriverService, private windowService: WindowService) {
30+
}
31+
32+
ngAfterViewInit(): void {
33+
setTimeout(() => {
34+
if (this.windowService.getStorage(IsFirstLogin) === "false") {
35+
return;
36+
}
37+
this.windowService.setStorage(IsFirstLogin, "false");
38+
this.driverService.load();
39+
}, 500)
40+
2741
}
2842

2943
changeCollapsed(): void {

0 commit comments

Comments
 (0)