其實Menu的控制項取決於登入者的權限。
以Demo來說,所有的頁面種類有以下:
其他前面兩個為開放權限,
也就是不論誰登入都會看到首頁
跟用戶資訊
。
後面四個權限實際上都會放在 Database,
也會紀錄某個人有哪些可以觀看跟操作。
當登入者驗證身分後進來,
前端送token拿登入者User資料,
傳回登入者資料會呈現:
而Menu會根據此User的權限,
也就是holds:[...]
來渲染畫面。
-src
|-app
...
|-core
|-menu
|-menu.component.css
|-menu.component.html
|-menu.component.ts
|-menu.ts
...
menu.ts
:export interface IMenu {
name: string;
path: string;
check?: boolean;
}
export const Menu: IMenu[] = [
{ name: "index", path: "/index", check: true },
{ name: "user", path: "/user", check: false }
];
之後拿到此登入者的權限後,
Menu: IMenu[]
會再加進去。
menu.component.ts
:export class MenuComponent implements OnInit {
LOGOURL = LOGOURL;
LANG = LANG;
TOGGLELANG = TOGGLELANG;
menu: IMenu[] = Menu;
isDevice = "";
constructor(
private coreService: CoreService,
private breakpointObserver: BreakpointObserver,
private tabService: TabService,
private dataService: DataService,
private userService: UserService
) {}
ngOnInit() {
this.breakpointObserver.observe("(max-width: 1199px)")
.subscribe(r => {
this.isDevice = r.matches ? "mb" : "pc";
this.filterMenu();
});
this.setMenu();
}
setMenu() {
let url = this.dataService.setUrl("powers");
this.dataService.getData(url).subscribe((data: IData) => {
if (!!data && !!data.res) {
let powers = <IPower[]>data.res;
powers.forEach((power: IPower) => {
this.userService.getUser().holds.forEach((hold: IHold) => {
if (hold.powerId === power.id) {
let obj = <IMenu>{
name: `${power.name}`,
path: `/${power.name}`,
check: false
};
this.menu.push(obj);
}
});
});
}
});
this.filterMenu();
}
filterMenu() {
let index = this.menu
.map(item => {
return item.name;
})
.indexOf("user");
if (this.isDevice === "pc" && index !== -1) {
this.menu.splice(index, 1);
}
if (this.isDevice === "mb" && index === -1) {
this.menu.splice(1, 0, {
name: "user",
path: "/user",
check: false
});
}
}
toggleMenuInfo(menuInfo: IMenu) {
menuInfo.check = !menuInfo.check;
this.setListTab(menuInfo);
}
setListTab(menuInfo: IMenu) {
this.coreService.nextHamburger("next");
let tab = <ITabBase>{
tag: `${menuInfo.name}_list`,
path: "cms" + menuInfo.path
};
let tabMain = <ITabMain>{
request: "insert",
content: tab
};
this.tabService.nextTabMain(tabMain);
}
logout() {
this.coreService.logout();
}
useLanguage($event?) {
if (!!$event) {
this.coreService.useLanguage($event);
}
}
getNowLang() {
return this.coreService.getNowLang();
}
}
setMenu()
:加入此使用者權限已便完成 menu: IMenu[]。
filterMenu()
:根據目前的螢幕尺寸,
來判斷 多語系 跟 用戶資訊 是否要放在Menu裡,
因 mb版 的右上角多語系跟用戶資訊會消失。
toggleMenuInfo()
:點擊了頁面大標題後,
會觸發 setListTab() 會讓右邊出現功能頁,
Tab這部分之後會提及。
此Demo比較小,很多情況應該都會有次選單。
其實Menu複雜度要看專案大小,
比較龐大的系統,不僅僅是所有頁面控制項,
恐怕連list裡的按鈕都會有權限控制。
menu.component.html
:<div class="side-box">
<div class="side-container">
<div class="logo"
[style.background-image]="'url(' + LOGOURL + ')'">
</div>
<div class="menu" *ngIf="!!menu">
<div class="menu-items">
<ng-container *ngFor="let m of menu">
<div class="menu-item" (click)="toggleMenuInfo(m)">
<div class="icon" [ngSwitch]="m.name">
<mat-icon *ngSwitchCase="'index'" svgIcon="index">
</mat-icon>
<mat-icon *ngSwitchCase="'user'" svgIcon="user">
</mat-icon>
<mat-icon *ngSwitchCase="'admin'" svgIcon="admin">
</mat-icon>
<mat-icon *ngSwitchCase="'customer'" svgIcon="customer">
</mat-icon>
<mat-icon *ngSwitchCase="'product'" svgIcon="product">
</mat-icon>
<mat-icon *ngSwitchCase="'order'" svgIcon="order">
</mat-icon>
</div>
<div class="content">
<span class="b">
{{ m.name + "_manage" | translate }}
</span>
</div>
</div>
</ng-container>
</div>
</div>
<div class="menu-other">
<div class="lang" *ngIf="TOGGLELANG && isDevice === 'mb'">
<div class="menu-item">
<div class="icon">
<mat-icon svgIcon="global" (click)="select.open()">
</mat-icon>
</div>
<div class="content">
<mat-select
#select
[value]="getNowLang()"
(valueChange)="useLanguage($event)"
[panelClass]="'font-white'"
class="b"
>
<mat-option *ngFor="let lang of LANG"
[value]="lang.short" class="b">
{{lang.long | translate}}
</mat-option>
</mat-select>
</div>
</div>
</div>
<div class="logout" (click)="logout()">
<div class="menu-item">
<div class="icon">
<mat-icon>exit_to_app</mat-icon>
</div>
<div class="content">
<span class="b">{{ "logout" | translate }}</span>
</div>
</div>
</div>
</div>
</div>
</div>
menu.component.css
:樣式請參照下方#範例網。
https://stackblitz.com/edit/ngcms-corecomp
一開始會跳出提示視窗顯示fail為正常,
請先從範例專案裡下載或是複製db.json
到本地端,
並下指令:
json-server db.json
json-server開啟成功後請連結此網址:
https://ngcms-corecomp.stackblitz.io/cms?token=bc6e113d26ce620066237d5e43f14690