You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
129 lines
3.1 KiB
129 lines
3.1 KiB
5 months ago
|
import { Injectable } from '@angular/core';
|
||
|
import { Router, NavigationEnd } from '@angular/router';
|
||
|
|
||
|
export interface RouterItem {
|
||
|
id: number;
|
||
|
parent: number;
|
||
|
header: string;
|
||
|
icon?: string;
|
||
|
url?: string;
|
||
|
children?: RouterItem[];
|
||
|
level?: number;
|
||
|
focus?: boolean;
|
||
|
active?: boolean;
|
||
|
height?: number;
|
||
|
}
|
||
|
|
||
|
@Injectable({
|
||
|
providedIn: 'root'
|
||
|
})
|
||
|
export class RouterService {
|
||
|
|
||
|
constructor(
|
||
|
private _router: Router
|
||
|
) {
|
||
|
_router.events.subscribe(result => {
|
||
|
if (result instanceof NavigationEnd) {
|
||
|
this._active.forEach(i => this._items[i].active = false);
|
||
|
this._active.length = 0;
|
||
|
this._path[result.url]?.forEach(i => {
|
||
|
this._items[i].active = true;
|
||
|
this._active.push(i);
|
||
|
});
|
||
|
}
|
||
|
});
|
||
|
}
|
||
|
|
||
|
private _root: RouterItem[] = [];
|
||
|
|
||
|
private _items: { [key: number]: RouterItem; } = {};
|
||
|
|
||
|
private _path: { [key: string]: number[]; } = {};
|
||
|
|
||
|
private _active: number[] = [];
|
||
|
|
||
|
public init(items: RouterItem[]): RouterItem[] {
|
||
|
items.forEach(item => {
|
||
|
this._items[item.id] = item;
|
||
|
if (!item.parent) {
|
||
|
this._root.push(item);
|
||
|
}
|
||
|
});
|
||
|
const tree = [];
|
||
|
const path = (url: string, item: RouterItem) => {
|
||
|
this._path[url].unshift(item.id);
|
||
|
if (this._items[item.parent]) {
|
||
|
path(url, this._items[item.parent]);
|
||
|
}
|
||
|
};
|
||
|
items.forEach(item => {
|
||
|
if (item.parent == 0) {
|
||
|
tree.push(item);
|
||
|
}
|
||
|
else {
|
||
|
const parent = this._items[item.parent];
|
||
|
if (parent) {
|
||
|
if (!parent.children) {
|
||
|
parent.children = [];
|
||
|
}
|
||
|
parent.children.push(item);
|
||
|
}
|
||
|
}
|
||
|
if (item.url) {
|
||
|
this._path[item.url] = [];
|
||
|
path(item.url, item);
|
||
|
}
|
||
|
});
|
||
|
const level = (items: RouterItem[], value: number) => {
|
||
|
items?.forEach(item => {
|
||
|
item.level = value;
|
||
|
if (item.children) {
|
||
|
level(item.children, value + 1);
|
||
|
}
|
||
|
});
|
||
|
};
|
||
|
level(tree, 0);
|
||
|
const height = (ancestor: RouterItem, descendant: RouterItem) => {
|
||
|
descendant.children?.forEach(child => {
|
||
|
ancestor.height += 48;
|
||
|
height(ancestor, child);
|
||
|
});
|
||
|
};
|
||
|
items.forEach(item => {
|
||
|
item.height = 0;
|
||
|
height(item, item);
|
||
|
});
|
||
|
this._path[this._router.url]?.forEach(i => {
|
||
|
this._items[i].active = true;
|
||
|
this._active.push(i);
|
||
|
});
|
||
|
return tree;
|
||
|
}
|
||
|
|
||
|
public focus(item: RouterItem): void {
|
||
|
if (item.focus) {
|
||
|
item.focus = false;
|
||
|
item.children.forEach(child => child.focus = false);
|
||
|
}
|
||
|
else {
|
||
|
const children = (item: RouterItem[]) => {
|
||
|
item.forEach(child => {
|
||
|
child.focus = false;
|
||
|
if (child.children) {
|
||
|
children(child.children);
|
||
|
}
|
||
|
});
|
||
|
};
|
||
|
children(this._items[item.parent] ? this._items[item.parent].children : this._root);
|
||
|
item.focus = true;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public navigate(url: string | any[], params?: { [key: string]: any }): Promise<boolean> {
|
||
|
return this._router.navigate(
|
||
|
typeof url == 'string' ? [url] : url,
|
||
|
params ? { queryParams: params } : undefined
|
||
|
);
|
||
|
}
|
||
|
}
|