ohayolibs
Version:
Ohayo is a set of essential modules for ohayojp.
212 lines (190 loc) • 6.29 kB
text/typescript
import { Platform } from '@angular/cdk/platform';
import {
AfterViewInit,
ChangeDetectionStrategy,
ChangeDetectorRef,
Component,
ElementRef,
Inject,
Input,
OnChanges,
OnDestroy,
OnInit,
Optional,
Renderer2,
TemplateRef,
ViewChild,
ViewEncapsulation,
} from '@angular/core';
import { NavigationEnd, Router } from '@angular/router';
import { ReuseTabService } from '@ohayo/components/reuse-tab';
import { OhayoI18NService, OHAYO_I18N_TOKEN, Menu, MenuService, SettingsService, TitleService } from '@ohayo/theme';
import { OhayoConfigService, BooleanInput, InputBoolean, InputNumber, isEmpty, NumberInput } from '@ohayo/util';
import { NzAffixComponent } from 'ng-zorro-antd/affix';
import { merge, Subject } from 'rxjs';
import { filter, takeUntil } from 'rxjs/operators';
interface PageHeaderPath {
title?: string;
link?: string[];
}
export class PageHeaderComponent implements OnInit, OnChanges, AfterViewInit, OnDestroy {
static ngAcceptInputType_loading: BooleanInput;
static ngAcceptInputType_wide: BooleanInput;
static ngAcceptInputType_autoBreadcrumb: BooleanInput;
static ngAcceptInputType_autoTitle: BooleanInput;
static ngAcceptInputType_syncTitle: BooleanInput;
static ngAcceptInputType_fixed: BooleanInput;
static ngAcceptInputType_fixedOffsetTop: NumberInput;
static ngAcceptInputType_recursiveBreadcrumb: BooleanInput;
inited = false;
private unsubscribe$ = new Subject<void>();
private conTpl: ElementRef;
private affix: NzAffixComponent;
isBrowser = true;
private get menus(): Menu[] {
return this.menuSrv.getPathByUrl(this.router.url, this.recursiveBreadcrumb);
}
_titleVal: string = '';
paths: PageHeaderPath[] = [];
// #region fields
_title: string | null;
_titleTpl: TemplateRef<void>;
set title(value: string | TemplateRef<void>) {
if (value instanceof TemplateRef) {
this._title = null;
this._titleTpl = value;
this._titleVal = '';
} else {
this._title = value;
this._titleVal = this._title;
}
}
loading = false;
wide = false;
home: string;
homeLink: string;
homeI18n: string;
autoBreadcrumb: boolean;
autoTitle: boolean;
syncTitle: boolean;
fixed: boolean;
fixedOffsetTop: number;
breadcrumb: TemplateRef<void>;
recursiveBreadcrumb: boolean;
logo: TemplateRef<void>;
action: TemplateRef<void>;
content: TemplateRef<void>;
extra: TemplateRef<void>;
tab: TemplateRef<void>;
// #endregion
constructor(
settings: SettingsService,
private renderer: Renderer2,
private router: Router,
private menuSrv: MenuService,
private i18nSrv: OhayoI18NService,
private titleSrv: TitleService,
private reuseSrv: ReuseTabService,
private cdr: ChangeDetectorRef,
configSrv: OhayoConfigService,
platform: Platform,
) {
this.isBrowser = platform.isBrowser;
configSrv.attach(this, 'pageHeader', {
home: '首页',
homeLink: '/',
autoBreadcrumb: true,
recursiveBreadcrumb: false,
autoTitle: true,
syncTitle: true,
fixed: false,
fixedOffsetTop: 64,
});
settings.notify
.pipe(
takeUntil(this.unsubscribe$),
filter(w => this.affix && w.type === 'layout' && w.name === 'collapsed'),
)
.subscribe(() => this.affix.updatePosition({} as any));
merge(menuSrv.change.pipe(filter(() => this.inited)), router.events.pipe(filter(ev => ev instanceof NavigationEnd)), i18nSrv.change)
.pipe(takeUntil(this.unsubscribe$))
.subscribe(() => this.refresh());
}
refresh(): void {
this.setTitle().genBreadcrumb();
this.cdr.detectChanges();
}
private genBreadcrumb(): void {
if (this.breadcrumb || !this.autoBreadcrumb || this.menus.length <= 0) {
this.paths = [];
return;
}
const paths: PageHeaderPath[] = [];
this.menus.forEach(item => {
if (typeof item.hideInBreadcrumb !== 'undefined' && item.hideInBreadcrumb) return;
let title = item.text;
if (item.i18n && this.i18nSrv) title = this.i18nSrv.fanyi(item.i18n);
paths.push({ title, link: (item.link && [item.link]) as string[] });
});
// add home
if (this.home) {
paths.splice(0, 0, {
title: (this.homeI18n && this.i18nSrv && this.i18nSrv.fanyi(this.homeI18n)) || this.home,
link: [this.homeLink],
});
}
this.paths = paths;
}
private setTitle(): this {
if (this._title == null && this._titleTpl == null && this.autoTitle && this.menus.length > 0) {
const item = this.menus[this.menus.length - 1];
let title = item.text;
if (item.i18n && this.i18nSrv) {
title = this.i18nSrv.fanyi(item.i18n);
}
this._titleVal = title!;
}
if (this._titleVal && this.syncTitle) {
if (this.titleSrv) {
this.titleSrv.setTitle(this._titleVal);
}
if (!this.inited && this.reuseSrv) {
this.reuseSrv.title = this._titleVal;
}
}
return this;
}
checkContent(): void {
if (isEmpty(this.conTpl.nativeElement)) {
this.renderer.setAttribute(this.conTpl.nativeElement, 'hidden', '');
} else {
this.renderer.removeAttribute(this.conTpl.nativeElement, 'hidden');
}
}
ngOnInit(): void {
this.refresh();
this.inited = true;
}
ngAfterViewInit(): void {
this.checkContent();
}
ngOnChanges(): void {
if (this.inited) {
this.refresh();
}
}
ngOnDestroy(): void {
const { unsubscribe$ } = this;
unsubscribe$.next();
unsubscribe$.complete();
}
}