Files
bbq/src/app/layout/pro/pro.component.ts
2021-11-26 16:34:35 +08:00

168 lines
5.2 KiB
TypeScript

import { BreakpointObserver, MediaMatcher } from '@angular/cdk/layout';
import { DOCUMENT } from '@angular/common';
import {
AfterViewInit,
Component,
ComponentFactoryResolver,
Inject,
OnDestroy,
OnInit,
Renderer2,
ViewChild,
ViewContainerRef
} from '@angular/core';
import { NavigationEnd, NavigationError, RouteConfigLoadStart, Router } from '@angular/router';
import { ReuseTabService } from '@delon/abc/reuse-tab';
import { RTL, RTLService } from '@delon/theme';
import { ScrollService, updateHostClass } from '@delon/util/browser';
import { environment } from '@env/environment';
import { NzMessageService } from 'ng-zorro-antd/message';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import { BrandService } from './pro.service';
import { ProSettingDrawerComponent } from './setting-drawer/setting-drawer.component';
@Component({
selector: 'layout-pro',
templateUrl: './pro.component.html'
// NOTICE: If all pages using OnPush mode, you can turn it on and all `cdr.detectChanges()` codes
// changeDetection: ChangeDetectionStrategy.OnPush
})
export class LayoutProComponent implements OnInit, AfterViewInit, OnDestroy {
private destroy$ = new Subject<void>();
private queryCls?: string;
@ViewChild('settingHost', { read: ViewContainerRef, static: false }) private settingHost!: ViewContainerRef;
isFetching = false;
get isMobile(): boolean {
return this.pro.isMobile;
}
get getLayoutStyle(): { [key: string]: string } | null {
const { isMobile, fixSiderbar, collapsed, menu, width, widthInCollapsed } = this.pro;
if (fixSiderbar && menu !== 'top' && !isMobile) {
return {
[this.rtl.dir === RTL ? 'paddingRight' : 'paddingLeft']: `${collapsed ? widthInCollapsed : width}px`
};
}
return null;
}
get getContentStyle(): { [key: string]: string } {
const { fixedHeader, headerHeight } = this.pro;
return {
margin: '24px 24px 0',
'padding-top': `${fixedHeader ? headerHeight : 0}px`
};
}
private get body(): HTMLElement {
return this.doc.body;
}
constructor(
bm: BreakpointObserver,
mediaMatcher: MediaMatcher,
router: Router,
msg: NzMessageService,
scroll: ScrollService,
reuseTabSrv: ReuseTabService,
private resolver: ComponentFactoryResolver,
private renderer: Renderer2,
public pro: BrandService,
@Inject(DOCUMENT) private doc: any,
// private cdr: ChangeDetectorRef
private rtl: RTLService
) {
// scroll to top in change page
router.events.pipe(takeUntil(this.destroy$)).subscribe(evt => {
if (!this.isFetching && evt instanceof RouteConfigLoadStart) {
this.isFetching = true;
scroll.scrollToTop();
}
if (evt instanceof NavigationError) {
this.isFetching = false;
msg.error(`无法加载${evt.url}路由`, { nzDuration: 1000 * 3 });
return;
}
if (!(evt instanceof NavigationEnd)) {
return;
}
this.isFetching = false;
// If have already cached router, should be don't need scroll to top
if (!reuseTabSrv.exists(evt.url)) {
scroll.scrollToTop();
}
});
// media
const query: { [key: string]: string } = {
'screen-xs': '(max-width: 575px)',
'screen-sm': '(min-width: 576px) and (max-width: 767px)',
'screen-md': '(min-width: 768px) and (max-width: 991px)',
'screen-lg': '(min-width: 992px) and (max-width: 1199px)',
'screen-xl': '(min-width: 1200px)'
};
bm.observe([
'(min-width: 1200px)',
'(min-width: 992px) and (max-width: 1199px)',
'(min-width: 768px) and (max-width: 991px)',
'(min-width: 576px) and (max-width: 767px)',
'(max-width: 575px)'
]).subscribe(() => {
this.queryCls = Object.keys(query).find(key => mediaMatcher.matchMedia(query[key]).matches);
this.setClass();
});
}
private setClass(): void {
const { body, renderer, queryCls, pro } = this;
updateHostClass(body, renderer, {
['color-weak']: pro.layout.colorWeak,
[`layout-fixed`]: pro.layout.fixed,
[`aside-collapsed`]: pro.collapsed,
['alain-pro']: true,
[queryCls!]: true,
[`alain-pro__content-${pro.layout.contentWidth}`]: true,
[`alain-pro__fixed`]: pro.layout.fixedHeader,
[`alain-pro__wide`]: pro.isFixed,
[`alain-pro__dark`]: pro.theme === 'dark',
[`alain-pro__light`]: pro.theme === 'light',
[`alain-pro__menu-side`]: pro.isSideMenu,
[`alain-pro__menu-top`]: pro.isTopMenu
});
}
ngAfterViewInit(): void {
// Setting componet for only developer
if (!environment.production) {
setTimeout(() => {
const settingFactory = this.resolver.resolveComponentFactory(ProSettingDrawerComponent);
this.settingHost.createComponent(settingFactory);
}, 22);
}
}
ngOnInit(): void {
const { pro, destroy$ } = this;
pro.notify.pipe(takeUntil(destroy$)).subscribe(() => {
this.setClass();
});
}
ngOnDestroy(): void {
const { destroy$, body, pro } = this;
destroy$.next();
destroy$.complete();
body.classList.remove(
`alain-pro__content-${pro.layout.contentWidth}`,
`alain-pro__fixed`,
`alain-pro__wide`,
`alain-pro__dark`,
`alain-pro__light`
);
}
}