[web-app] ng-alain模版工程初始化

This commit is contained in:
tomsun28
2021-11-27 22:21:52 +08:00
parent 39a9a8eb7c
commit cdee4add2a
113 changed files with 9004 additions and 28649 deletions

View File

@@ -0,0 +1 @@
[Document](https://ng-alain.com/theme/default)

View File

@@ -0,0 +1,85 @@
import { Component } from '@angular/core';
import { SettingsService, User } from '@delon/theme';
import { LayoutDefaultOptions } from '@delon/theme/layout-default';
import { environment } from '@env/environment';
@Component({
selector: 'layout-basic',
template: `
<layout-default [options]="options" [asideUser]="asideUserTpl" [content]="contentTpl" [customError]="null">
<layout-default-header-item direction="left">
<a layout-default-header-item-trigger href="//github.com/usthe" target="_blank">
<i nz-icon nzType="github"></i>
</a>
</layout-default-header-item>
<layout-default-header-item direction="left" hidden="mobile">
<a layout-default-header-item-trigger routerLink="/passport/lock">
<i nz-icon nzType="lock"></i>
</a>
</layout-default-header-item>
<layout-default-header-item direction="left" hidden="pc">
<div layout-default-header-item-trigger (click)="searchToggleStatus = !searchToggleStatus">
<i nz-icon nzType="search"></i>
</div>
</layout-default-header-item>
<layout-default-header-item direction="middle">
<header-search class="alain-default__search" [toggleChange]="searchToggleStatus"></header-search>
</layout-default-header-item>
<layout-default-header-item direction="right" hidden="mobile">
<div layout-default-header-item-trigger nz-dropdown [nzDropdownMenu]="settingsMenu" nzTrigger="click" nzPlacement="bottomRight">
<i nz-icon nzType="setting"></i>
</div>
<nz-dropdown-menu #settingsMenu="nzDropdownMenu">
<div nz-menu style="width: 200px;">
<div nz-menu-item>
<header-fullscreen></header-fullscreen>
</div>
<div nz-menu-item>
<header-clear-storage></header-clear-storage>
</div>
<div nz-menu-item>
<header-i18n></header-i18n>
</div>
</div>
</nz-dropdown-menu>
</layout-default-header-item>
<layout-default-header-item direction="right">
<header-user></header-user>
</layout-default-header-item>
<ng-template #asideUserTpl>
<div nz-dropdown nzTrigger="click" [nzDropdownMenu]="userMenu" class="alain-default__aside-user">
<nz-avatar class="alain-default__aside-user-avatar" [nzSrc]="user.avatar"></nz-avatar>
<div class="alain-default__aside-user-info">
<strong>{{ user.name }}</strong>
<p class="mb0">{{ user.email }}</p>
</div>
</div>
<nz-dropdown-menu #userMenu="nzDropdownMenu">
<ul nz-menu>
<li nz-menu-item routerLink="/pro/account/center">{{ 'menu.account.center' | i18n }}</li>
<li nz-menu-item routerLink="/pro/account/settings">{{ 'menu.account.settings' | i18n }}</li>
</ul>
</nz-dropdown-menu>
</ng-template>
<ng-template #contentTpl>
<router-outlet></router-outlet>
</ng-template>
</layout-default>
<setting-drawer *ngIf="showSettingDrawer"></setting-drawer>
<theme-btn></theme-btn>
`,
})
export class LayoutBasicComponent {
options: LayoutDefaultOptions = {
logoExpanded: `./assets/logo-color.svg`,
logoCollapsed: `./assets/logo.svg`,
};
searchToggleStatus = false;
showSettingDrawer = !environment.production;
get user(): User {
return this.settings.user;
}
constructor(private settings: SettingsService) {}
}

View File

@@ -0,0 +1,29 @@
import { ChangeDetectionStrategy, Component, HostListener } from '@angular/core';
import { NzMessageService } from 'ng-zorro-antd/message';
import { NzModalService } from 'ng-zorro-antd/modal';
@Component({
selector: 'header-clear-storage',
template: `
<i nz-icon nzType="tool"></i>
{{ 'menu.clear.local.storage' | i18n }}
`,
host: {
'[class.d-block]': 'true'
},
changeDetection: ChangeDetectionStrategy.OnPush
})
export class HeaderClearStorageComponent {
constructor(private modalSrv: NzModalService, private messageSrv: NzMessageService) {}
@HostListener('click')
_click(): void {
this.modalSrv.confirm({
nzTitle: 'Make sure clear all local storage?',
nzOnOk: () => {
localStorage.clear();
this.messageSrv.success('Clear Finished!');
}
});
}
}

View File

@@ -0,0 +1,32 @@
import { ChangeDetectionStrategy, Component, HostListener } from '@angular/core';
import * as screenfull from 'screenfull';
@Component({
selector: 'header-fullscreen',
template: `
<i nz-icon [nzType]="status ? 'fullscreen-exit' : 'fullscreen'"></i>
{{ (status ? 'menu.fullscreen.exit' : 'menu.fullscreen') | i18n }}
`,
host: {
'[class.d-block]': 'true'
},
changeDetection: ChangeDetectionStrategy.OnPush
})
export class HeaderFullScreenComponent {
status = false;
private get sf(): screenfull.Screenfull {
return screenfull as screenfull.Screenfull;
}
@HostListener('window:resize')
_resize(): void {
this.status = this.sf.isFullscreen;
}
@HostListener('click')
_click(): void {
if (this.sf.isEnabled) {
this.sf.toggle();
}
}
}

View File

@@ -0,0 +1,54 @@
import { DOCUMENT } from '@angular/common';
import { ChangeDetectionStrategy, Component, Inject, Input } from '@angular/core';
import { I18NService } from '@core';
import { ALAIN_I18N_TOKEN, SettingsService } from '@delon/theme';
import { BooleanInput, InputBoolean } from '@delon/util/decorator';
@Component({
selector: 'header-i18n',
template: `
<div *ngIf="showLangText" nz-dropdown [nzDropdownMenu]="langMenu" nzPlacement="bottomRight">
<i nz-icon nzType="global"></i>
{{ 'menu.lang' | i18n }}
<i nz-icon nzType="down"></i>
</div>
<i *ngIf="!showLangText" nz-dropdown [nzDropdownMenu]="langMenu" nzPlacement="bottomRight" nz-icon nzType="global"></i>
<nz-dropdown-menu #langMenu="nzDropdownMenu">
<ul nz-menu>
<li nz-menu-item *ngFor="let item of langs" [nzSelected]="item.code === curLangCode" (click)="change(item.code)">
<span role="img" [attr.aria-label]="item.text" class="pr-xs">{{ item.abbr }}</span>
{{ item.text }}
</li>
</ul>
</nz-dropdown-menu>
`,
changeDetection: ChangeDetectionStrategy.OnPush
})
export class HeaderI18nComponent {
static ngAcceptInputType_showLangText: BooleanInput;
/** Whether to display language text */
@Input() @InputBoolean() showLangText = true;
get langs(): Array<{ code: string; text: string; abbr: string }> {
return this.i18n.getLangs();
}
get curLangCode(): string {
return this.settings.layout.lang;
}
constructor(private settings: SettingsService, @Inject(ALAIN_I18N_TOKEN) private i18n: I18NService, @Inject(DOCUMENT) private doc: any) {}
change(lang: string): void {
const spinEl = this.doc.createElement('div');
spinEl.setAttribute('class', `page-loading ant-spin ant-spin-lg ant-spin-spinning`);
spinEl.innerHTML = `<span class="ant-spin-dot ant-spin-dot-spin"><i></i><i></i><i></i><i></i></span>`;
this.doc.body.appendChild(spinEl);
this.i18n.loadLangData(lang).subscribe(res => {
this.i18n.use(lang, res);
this.settings.setLayout('lang', lang);
setTimeout(() => this.doc.location.reload());
});
}
}

View File

@@ -0,0 +1,108 @@
import {
AfterViewInit,
ChangeDetectionStrategy,
ChangeDetectorRef,
Component,
ElementRef,
EventEmitter,
HostBinding,
Input,
OnDestroy,
Output
} from '@angular/core';
import { BehaviorSubject } from 'rxjs';
import { debounceTime, distinctUntilChanged, tap } from 'rxjs/operators';
@Component({
selector: 'header-search',
template: `
<nz-input-group [nzPrefix]="iconTpl" [nzSuffix]="loadingTpl">
<ng-template #iconTpl>
<i nz-icon [nzType]="focus ? 'arrow-down' : 'search'"></i>
</ng-template>
<ng-template #loadingTpl>
<i *ngIf="loading" nz-icon nzType="loading"></i>
</ng-template>
<input
type="text"
nz-input
[(ngModel)]="q"
[nzAutocomplete]="auto"
(input)="search($event)"
(focus)="qFocus()"
(blur)="qBlur()"
[attr.placeholder]="'menu.search.placeholder' | i18n"
/>
</nz-input-group>
<nz-autocomplete nzBackfill #auto>
<nz-auto-option *ngFor="let i of options" [nzValue]="i">{{ i }}</nz-auto-option>
</nz-autocomplete>
`,
changeDetection: ChangeDetectionStrategy.OnPush
})
export class HeaderSearchComponent implements AfterViewInit, OnDestroy {
q = '';
qIpt: HTMLInputElement | null = null;
options: string[] = [];
search$ = new BehaviorSubject('');
loading = false;
@HostBinding('class.alain-default__search-focus')
focus = false;
@HostBinding('class.alain-default__search-toggled')
searchToggled = false;
@Input()
set toggleChange(value: boolean) {
if (typeof value === 'undefined') {
return;
}
this.searchToggled = value;
this.focus = value;
if (value) {
setTimeout(() => this.qIpt!.focus());
}
}
@Output() readonly toggleChangeChange = new EventEmitter<boolean>();
constructor(private el: ElementRef<HTMLElement>, private cdr: ChangeDetectorRef) {}
ngAfterViewInit(): void {
this.qIpt = this.el.nativeElement.querySelector('.ant-input') as HTMLInputElement;
this.search$
.pipe(
debounceTime(500),
distinctUntilChanged(),
tap({
complete: () => {
this.loading = true;
}
})
)
.subscribe(value => {
this.options = value ? [value, value + value, value + value + value] : [];
this.loading = false;
this.cdr.detectChanges();
});
}
qFocus(): void {
this.focus = true;
}
qBlur(): void {
this.focus = false;
this.searchToggled = false;
this.options.length = 0;
this.toggleChangeChange.emit(false);
}
search(ev: Event): void {
this.search$.next((ev.target as HTMLInputElement).value);
}
ngOnDestroy(): void {
this.search$.complete();
this.search$.unsubscribe();
}
}

View File

@@ -0,0 +1,48 @@
import { ChangeDetectionStrategy, Component, Inject } from '@angular/core';
import { Router } from '@angular/router';
import { DA_SERVICE_TOKEN, ITokenService } from '@delon/auth';
import { SettingsService, User } from '@delon/theme';
@Component({
selector: 'header-user',
template: `
<div class="alain-default__nav-item d-flex align-items-center px-sm" nz-dropdown nzPlacement="bottomRight" [nzDropdownMenu]="userMenu">
<nz-avatar [nzSrc]="user.avatar" nzSize="small" class="mr-sm"></nz-avatar>
{{ user.name }}
</div>
<nz-dropdown-menu #userMenu="nzDropdownMenu">
<div nz-menu class="width-sm">
<div nz-menu-item routerLink="/pro/account/center">
<i nz-icon nzType="user" class="mr-sm"></i>
{{ 'menu.account.center' | i18n }}
</div>
<div nz-menu-item routerLink="/pro/account/settings">
<i nz-icon nzType="setting" class="mr-sm"></i>
{{ 'menu.account.settings' | i18n }}
</div>
<div nz-menu-item routerLink="/exception/trigger">
<i nz-icon nzType="close-circle" class="mr-sm"></i>
{{ 'menu.account.trigger' | i18n }}
</div>
<li nz-menu-divider></li>
<div nz-menu-item (click)="logout()">
<i nz-icon nzType="logout" class="mr-sm"></i>
{{ 'menu.account.logout' | i18n }}
</div>
</div>
</nz-dropdown-menu>
`,
changeDetection: ChangeDetectionStrategy.OnPush
})
export class HeaderUserComponent {
get user(): User {
return this.settings.user;
}
constructor(private settings: SettingsService, private router: Router, @Inject(DA_SERVICE_TOKEN) private tokenService: ITokenService) {}
logout(): void {
this.tokenService.clear();
this.router.navigateByUrl(this.tokenService.login_url!);
}
}