diff --git a/packages/abc/onboarding/demo/basic.md b/packages/abc/onboarding/demo/basic.md
index 30d21950b2..170ed6357b 100644
--- a/packages/abc/onboarding/demo/basic.md
+++ b/packages/abc/onboarding/demo/basic.md
@@ -15,7 +15,8 @@ Simplest of usage.
```ts
import { Component } from '@angular/core';
-import { OnboardingService } from '@delon/abc/onboarding';
+
+import { OnboardingConfig, OnboardingService } from '@delon/abc/onboarding';
import { _HttpClient } from '@delon/theme';
import { NzMessageService } from 'ng-zorro-antd/message';
@@ -28,27 +29,49 @@ import { NzMessageService } from 'ng-zorro-antd/message';
+
-
+
onboarding.json
- `,
+ `
})
export class DemoComponent {
- constructor(private srv: OnboardingService, private msg: NzMessageService, private http: _HttpClient) {}
+ private def: OnboardingConfig = {
+ items: [
+ {
+ selectors: '.test1-1',
+ content: 'The user guidance is to help users better understand and use the product',
+ width: 300
+ },
+ {
+ selectors: '.test1-2',
+ title: 'Test2',
+ content: 'The user guidance is to help users better understand and use the product'
+ },
+ {
+ selectors: '.test1-3',
+ title: 'Test3',
+ content: 'The user guidance is to help users better understand and use the product'
+ }
+ ]
+ };
+ constructor(
+ private srv: OnboardingService,
+ private msg: NzMessageService,
+ private http: _HttpClient
+ ) {}
handleClick(): void {
this.msg.info(`click`);
}
start(): void {
- this.srv.start({
- items: [
- { selectors: '.test1-1', content: 'The user guidance is to help users better understand and use the product', width: 300 },
- { selectors: '.test1-2', title: 'Test2', content: 'The user guidance is to help users better understand and use the product' },
- { selectors: '.test1-3', title: 'Test3', content: 'The user guidance is to help users better understand and use the product' },
- ],
- });
+ this.srv.start({ ...this.def });
}
viaHttp(): void {
@@ -57,5 +80,9 @@ export class DemoComponent {
this.srv.start(res);
});
}
+
+ startOnce(): void {
+ this.srv.start({ ...this.def, key: 'obs-once' });
+ }
}
```
diff --git a/packages/abc/onboarding/index.en-US.md b/packages/abc/onboarding/index.en-US.md
index 32bcda5ba3..deeedfe21e 100644
--- a/packages/abc/onboarding/index.en-US.md
+++ b/packages/abc/onboarding/index.en-US.md
@@ -25,6 +25,8 @@ The components only support the use of `OnboardingService` service to build.
| Property | Description | Type | Default |
|----------|-------------|------|---------|
+| `[key]` | Storage identification Key, The default is `localStorage` local storage, allowing the use of `ONBOARDING_STORE_TOKEN` to change the storage method | `string` | - |
+| `[keyVersion]` | Current version | `unknown` | - |
| `[items]` | Onboarding items | `OnboardingItem[]` | `[]` |
| `[mask]` | Whether to show mask or not | `boolean` | `true` |
| `[maskClosable]` | Clicking on the mask (area outside the onboarding) to close the onboarding or not | `boolean` | `true` |
diff --git a/packages/abc/onboarding/index.zh-CN.md b/packages/abc/onboarding/index.zh-CN.md
index 4098b5e354..98977770a4 100644
--- a/packages/abc/onboarding/index.zh-CN.md
+++ b/packages/abc/onboarding/index.zh-CN.md
@@ -25,6 +25,8 @@ module: import { OnboardingModule } from '@delon/abc/onboarding';
| 成员 | 说明 | 类型 | 默认值 |
|----|----|----|-----|
+| `[key]` | 存储标识Key;默认 `localStorage` 本地存储,允许使用 `ONBOARDING_STORE_TOKEN` 变更存储方式 | `string` | - |
+| `[keyVersion]` | 当前版本 | `unknown` | - |
| `[items]` | 引导项列表 | `OnboardingItem[]` | `[]` |
| `[mask]` | 是否展示遮罩 | `boolean` | `true` |
| `[maskClosable]` | 点击蒙层是否允许关闭 | `boolean` | `true` |
diff --git a/packages/abc/onboarding/onboarding.service.ts b/packages/abc/onboarding/onboarding.service.ts
index d1f9bbbca3..b401721b3b 100644
--- a/packages/abc/onboarding/onboarding.service.ts
+++ b/packages/abc/onboarding/onboarding.service.ts
@@ -18,13 +18,14 @@ import { AlainConfigService } from '@delon/util/config';
import type { NzSafeAny } from 'ng-zorro-antd/core/types';
import { OnboardingComponent } from './onboarding.component';
+import { ONBOARDING_STORE_TOKEN, OnBoardingKeyStore } from './onboarding.storage';
import { OnboardingConfig, OnboardingItem, OnboardingOpType } from './onboarding.types';
@Injectable()
export class OnboardingService implements OnDestroy {
private compRef!: ComponentRef;
private op$!: Subscription;
- private config!: OnboardingConfig;
+ private config?: OnboardingConfig;
private active = 0;
private running$: Subscription | null = null;
private _running = false;
@@ -49,6 +50,7 @@ export class OnboardingService implements OnDestroy {
private router: Router,
@Inject(DOCUMENT) private doc: NzSafeAny,
private configSrv: AlainConfigService,
+ @Inject(ONBOARDING_STORE_TOKEN) private keyStoreSrv: OnBoardingKeyStore,
@Optional() private directionality: Directionality
) {}
@@ -96,6 +98,10 @@ export class OnboardingService implements OnDestroy {
}
private destroy(): void {
+ const storeKey = this.config?.key;
+ if (storeKey != null) {
+ this.keyStoreSrv.set(storeKey, this.config?.keyVersion);
+ }
this.cancelRunning();
if (this.compRef) {
this.appRef.detachView(this.compRef.hostView);
@@ -105,7 +111,7 @@ export class OnboardingService implements OnDestroy {
}
private showItem(isStart: boolean = false): void {
- const items = this.config.items!;
+ const items = this.config?.items!;
const item = {
position: 'bottomLeft',
before: of(true),
@@ -142,17 +148,23 @@ export class OnboardingService implements OnDestroy {
* 开启新的用户引导流程
*/
start(config: OnboardingConfig): void {
- if (this.running) {
- return;
- }
- this.destroy();
- this.config = {
+ const cog: OnboardingConfig = {
+ keyVersion: '',
items: [],
mask: true,
maskClosable: true,
showTotal: false,
...config
};
+ const storeKey = cog?.key;
+ if (storeKey != null && this.keyStoreSrv.get(storeKey) === cog.keyVersion) {
+ return;
+ }
+ if (this.running) {
+ return;
+ }
+ this.destroy();
+ this.config = cog;
this.active = 0;
this.type = null;
this.attach();
@@ -165,7 +177,7 @@ export class OnboardingService implements OnDestroy {
* 下一步
*/
next(): void {
- if (this._running || this.active + 1 >= this.config.items!.length) {
+ if (this._running || this.active + 1 >= this.config!.items!.length) {
this.done();
return;
}
diff --git a/packages/abc/onboarding/onboarding.spec.ts b/packages/abc/onboarding/onboarding.spec.ts
index 8044fcd989..22e9aa560e 100644
--- a/packages/abc/onboarding/onboarding.spec.ts
+++ b/packages/abc/onboarding/onboarding.spec.ts
@@ -10,6 +10,7 @@ import { NzSafeAny } from 'ng-zorro-antd/core/types';
import { OnboardingModule } from './onboarding.module';
import { OnboardingService } from './onboarding.service';
+import { ONBOARDING_STORE_TOKEN } from './onboarding.storage';
import { OnboardingConfig, OnboardingOpType } from './onboarding.types';
describe('abc: onboarding', () => {
@@ -42,6 +43,20 @@ describe('abc: onboarding', () => {
page.start().checkActive().click('next').checkDone(false).click('done').checkDone();
}));
+ it('#key', fakeAsync(() => {
+ const storeSrv = TestBed.inject(ONBOARDING_STORE_TOKEN);
+ let storeKeyVersion: unknown = '';
+ spyOn(storeSrv, 'get').and.callFake(() => {
+ return storeKeyVersion;
+ });
+ spyOn(storeSrv, 'set').and.callFake((_, value) => {
+ storeKeyVersion = value;
+ });
+ page.start({ key: 'a', keyVersion: '1' }).checkActive().click('next').checkDone(false).click('done').checkDone();
+ page.start({ key: 'a', keyVersion: '1' });
+ expect(page.el == null);
+ }));
+
it('#skip', fakeAsync(() => {
page.start().checkActive().click('skip').checkDone();
}));
diff --git a/packages/abc/onboarding/onboarding.storage.ts b/packages/abc/onboarding/onboarding.storage.ts
new file mode 100644
index 0000000000..857915bfa1
--- /dev/null
+++ b/packages/abc/onboarding/onboarding.storage.ts
@@ -0,0 +1,26 @@
+import { InjectionToken } from '@angular/core';
+
+export interface OnBoardingKeyStore {
+ get(key: string): unknown;
+
+ set(key: string, version: unknown): void;
+}
+
+export const ONBOARDING_STORE_TOKEN = new InjectionToken('ONBOARDING_STORE_TOKEN', {
+ providedIn: 'root',
+ factory: ONBOARDING_STORE_TOKEN_FACTORY
+});
+
+export function ONBOARDING_STORE_TOKEN_FACTORY(): OnBoardingKeyStore {
+ return new LocalStorageStore();
+}
+
+export class LocalStorageStore implements OnBoardingKeyStore {
+ get(key: string): unknown {
+ return localStorage.getItem(key);
+ }
+
+ set(key: string, version: unknown): void {
+ localStorage.setItem(key, `${version}`);
+ }
+}
diff --git a/packages/abc/onboarding/onboarding.types.ts b/packages/abc/onboarding/onboarding.types.ts
index 723f603c3b..4d9e0db218 100644
--- a/packages/abc/onboarding/onboarding.types.ts
+++ b/packages/abc/onboarding/onboarding.types.ts
@@ -7,6 +7,14 @@ import type { NzSafeAny } from 'ng-zorro-antd/core/types';
export type OnboardingOpType = 'next' | 'prev' | 'skip' | 'done';
export interface OnboardingConfig {
+ /**
+ * Storage identification Key, The default is `localStorage` local storage, allowing the use of `ONBOARDING_STORE_TOKEN` to change the storage method
+ */
+ key?: string;
+ /**
+ * Current version
+ */
+ keyVersion?: unknown;
/**
* Onboarding items
*/
diff --git a/packages/abc/onboarding/public_api.ts b/packages/abc/onboarding/public_api.ts
index 68bb531ecc..fa2269a8f0 100644
--- a/packages/abc/onboarding/public_api.ts
+++ b/packages/abc/onboarding/public_api.ts
@@ -1,5 +1,6 @@
export * from './onboarding.service';
export * from './onboarding.types';
export * from './onboarding.component';
+export * from './onboarding.storage';
export * from './onboarding.module';