权限管理优化

This commit is contained in:
shimingxy 2024-07-18 19:21:16 +08:00
parent 3f51aab687
commit 3f96dee6b6
13 changed files with 427 additions and 154 deletions

View File

@ -0,0 +1,125 @@
<page-header> </page-header>
<nz-card [nzBordered]="false">
<form nz-form [nzLayout]="'inline'" (ngSubmit)="onSearch()" class="search__form">
<div nz-row [nzGutter]="{ xs: 8, sm: 8, md: 24, lg: 24, xl: 48, xxl: 48 }">
<div nz-col nzMd="10" nzSm="24">
<nz-form-item>
<nz-form-label nzFor="appName">{{ 'mxk.apps.name' | i18n }}</nz-form-label>
<nz-form-control>
<input nz-input [(ngModel)]="query.params.appName" [ngModelOptions]="{ standalone: true }"
name="appName" placeholder="" id="appName" />
</nz-form-control>
</nz-form-item>
</div>
<div nz-col nzMd="10" nzSm="24">
<nz-form-item>
<nz-form-label nzFor="protocol">{{ 'mxk.apps.protocol' | i18n }}</nz-form-label>
<nz-form-control>
<nz-select [(ngModel)]="query.params.protocol" [ngModelOptions]="{ standalone: true }">
<nz-option nzValue="" nzLabel="ALL"></nz-option>
<nz-option nzValue="OAuth_v2.0" nzLabel="OAuth v2.0"></nz-option>
<nz-option nzValue="OAuth_v2.1" nzLabel="OAuth v2.1"></nz-option>
<nz-option nzValue="OpenID_Connect_v1.0" nzLabel="OpenID Connect v1.0"></nz-option>
<nz-option nzValue="SAML_v2.0" nzLabel="SAML v2.0"> </nz-option>
<nz-option nzValue="CAS" nzLabel="CAS"></nz-option>
<nz-option nzValue="JWT" nzLabel="JWT"></nz-option>
<nz-option nzValue="Token_Based" nzLabel="Token Based"></nz-option>
<nz-option nzValue="Form_Based" nzLabel="Form Based"></nz-option>
<nz-option nzValue="Extend_API" nzLabel="Extend API"></nz-option>
<nz-option nzValue="Basic" nzLabel="Basic"></nz-option>
</nz-select>
</nz-form-control>
</nz-form-item>
</div>
<div nz-col [nzSpan]="query.expandForm ? 24 : 4" [class.text-right]="query.expandForm">
<nz-form-item>
<button nz-button type="submit" [nzType]="'primary'" [nzLoading]="query.submitLoading">{{
'mxk.text.query' | i18n }}</button>
<button nz-button type="reset" (click)="onReset()" class="mx-sm" style="display: none">{{
'mxk.text.reset' | i18n }}</button>
<button nz-button (click)="query.expandForm = !query.expandForm" class="mx-sm"
style="display: none">
{{ query.expandForm ? ('mxk.text.collapse' | i18n) : ('mxk.text.expand' | i18n) }}</button>
</nz-form-item>
</div>
</div>
</form>
</nz-card>
<nz-card>
<div nz-col [nzSpan]="24" class="table-list-toolbar">
<nz-table #dynamicTable nzTableLayout="auto" nzSize="small" nzBordered nzShowSizeChanger
[nzData]="query.results.rows" [nzFrontPagination]="false" [nzTotal]="query.results.records"
[nzPageSizeOptions]="query.params.pageSizeOptions" [nzPageSize]="query.params.pageSize"
[nzPageIndex]="query.params.pageNumber" [nzLoading]="this.query.tableLoading"
(nzQueryParams)="onQueryParamsChange($event)" nzWidth="100%">
<thead>
<tr>
<th [nzChecked]="query.checked" [nzIndeterminate]="query.indeterminate"
(nzCheckedChange)="onTableAllChecked($event)"></th>
<th nzAlign="center">{{ 'mxk.apps.icon' | i18n }}</th>
<th nzAlign="center">{{ 'mxk.text.id' | i18n }}</th>
<th nzAlign="center">{{ 'mxk.apps.name' | i18n }}</th>
<th nzAlign="center">{{ 'mxk.apps.protocol' | i18n }}</th>
<th nzAlign="center">{{ 'mxk.apps.category' | i18n }}</th>
<th nzAlign="center">{{ 'mxk.text.sortIndex' | i18n }}</th>
<th nzAlign="center">{{ 'mxk.text.status' | i18n }}</th>
<th nzAlign="center" class="table_cell_action_2">{{ 'mxk.text.action' | i18n }}</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let data of query.results.rows">
<td [nzChecked]="query.tableCheckedId.has(data.id)" [nzDisabled]="data.disabled"
(nzCheckedChange)="onTableItemChecked(data.id, $event)"></td>
<td nzAlign="center"><img height="30" border="0px" src="{{ data.iconBase64 }}" /></td>
<td nzAlign="left"> {{ data.id }} </td>
<td nzAlign="left"> {{ data.appName }}</td>
<td nzAlign="left"> {{ data.protocol }}</td>
<td nzAlign="left">
<div *ngIf="data.category == 'none'">{{ 'mxk.apps.category.none' | i18n }}</div>
<div *ngIf="data.category == '1011'">{{ 'mxk.apps.category.1011' | i18n }}</div>
<div *ngIf="data.category == '1012'">{{ 'mxk.apps.category.1012' | i18n }}</div>
<div *ngIf="data.category == '1013'">{{ 'mxk.apps.category.1013' | i18n }}</div>
<div *ngIf="data.category == '1014'">{{ 'mxk.apps.category.1014' | i18n }}</div>
<div *ngIf="data.category == '1015'">{{ 'mxk.apps.category.1015' | i18n }}</div>
<div *ngIf="data.category == '1016'">{{ 'mxk.apps.category.1016' | i18n }}</div>
<div *ngIf="data.category == '1017'">{{ 'mxk.apps.category.1017' | i18n }}</div>
<div *ngIf="data.category == '1111'">{{ 'mxk.apps.category.1111' | i18n }}</div>
<div *ngIf="data.category == '1112'">{{ 'mxk.apps.category.1112' | i18n }}</div>
<div *ngIf="data.category == '1113'">{{ 'mxk.apps.category.1113' | i18n }}</div>
<div *ngIf="data.category == '1114'">{{ 'mxk.apps.category.1114' | i18n }}</div>
<div *ngIf="data.category == '1211'">{{ 'mxk.apps.category.1211' | i18n }}</div>
<div *ngIf="data.category == '1212'">{{ 'mxk.apps.category.1212' | i18n }}</div>
<div *ngIf="data.category == '1213'">{{ 'mxk.apps.category.1213' | i18n }}</div>
<div *ngIf="data.category == '1214'">{{ 'mxk.apps.category.1214' | i18n }}</div>
<div *ngIf="data.category == '1215'">{{ 'mxk.apps.category.1215' | i18n }}</div>
<div *ngIf="data.category == '1311'">{{ 'mxk.apps.category.1311' | i18n }}</div>
<div *ngIf="data.category == '1411'">{{ 'mxk.apps.category.1411' | i18n }}</div>
<div *ngIf="data.category == '1511'">{{ 'mxk.apps.category.1511' | i18n }}</div>
<div *ngIf="data.category == '1512'">{{ 'mxk.apps.category.1512' | i18n }}</div>
<div *ngIf="data.category == '1611'">{{ 'mxk.apps.category.1611' | i18n }}</div>
<div *ngIf="data.category == '1711'">{{ 'mxk.apps.category.1711' | i18n }}</div>
<div *ngIf="data.category == '1712'">{{ 'mxk.apps.category.1712' | i18n }}</div>
<div *ngIf="data.category == '1811'">{{ 'mxk.apps.category.1811' | i18n }}</div>
<div *ngIf="data.category == '1812'">{{ 'mxk.apps.category.1812' | i18n }}</div>
<div *ngIf="data.category == '1911'">{{ 'mxk.apps.category.1911' | i18n }}</div>
<div *ngIf="data.category == '1912'">{{ 'mxk.apps.category.1912' | i18n }}</div>
</td>
<td nzAlign="left"> {{ data.sortIndex }}</td>
<td nzAlign="center"> <i *ngIf="data.status == 1" nz-icon nzType="check-circle" nzTheme="fill"
style="color: green"></i></td>
<td nzAlign="center" nzBreakWord="false">
<button nz-button type="button" (click)="onEditPermission($event, data.id, data.appName)">{{
'mxk.apps.permission' | i18n
}}</button>
<button nz-button type="button" (click)="onEditResource($event, data.id, data.appName)">{{
'mxk.apps.resources' | i18n
}}</button>
</td>
</tr>
</tbody>
</nz-table>
</div>
</nz-card>

View File

@ -0,0 +1,25 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { AppsComponent } from './apps.component';
describe('AppsComponent', () => {
let component: AppsComponent;
let fixture: ComponentFixture<AppsComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ AppsComponent ]
})
.compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(AppsComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -0,0 +1,164 @@
/*
* Copyright [2022] [MaxKey of copyright http://www.maxkey.top]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { ChangeDetectionStrategy, ViewContainerRef, ChangeDetectorRef, Component, OnInit, Inject } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { Router } from '@angular/router';
import { I18NService } from '@core';
import { _HttpClient, ALAIN_I18N_TOKEN, SettingsService } from '@delon/theme';
import { format, addDays } from 'date-fns';
import { NzSafeAny } from 'ng-zorro-antd/core/types';
import { NzMessageService } from 'ng-zorro-antd/message';
import { NzModalRef, NzModalService } from 'ng-zorro-antd/modal';
import { NzTableQueryParams } from 'ng-zorro-antd/table';
import { AppsService } from '../../../service/apps.service';
import { set2String } from '../../../shared/index';
@Component({
selector: 'app-apps',
templateUrl: './apps.component.html',
styleUrls: ['./apps.component.less']
})
export class AppsComponent implements OnInit {
query: {
params: {
appName: String;
displayName: String;
protocol: String;
startDate: String;
endDate: String;
startDatePicker: Date;
endDatePicker: Date;
pageSize: number;
pageNumber: number;
pageSizeOptions: number[];
};
results: {
records: number;
rows: NzSafeAny[];
};
expandForm: Boolean;
submitLoading: boolean;
tableLoading: boolean;
tableCheckedId: Set<String>;
indeterminate: boolean;
checked: boolean;
} = {
params: {
appName: '',
displayName: '',
protocol: '',
startDate: '',
endDate: '',
startDatePicker: addDays(new Date(), -30),
endDatePicker: new Date(),
pageSize: 10,
pageNumber: 1,
pageSizeOptions: [10, 20, 50]
},
results: {
records: 0,
rows: []
},
expandForm: false,
submitLoading: false,
tableLoading: false,
tableCheckedId: new Set<String>(),
indeterminate: false,
checked: false
};
constructor(
private modalService: NzModalService,
private viewContainerRef: ViewContainerRef,
private appsService: AppsService,
private fb: FormBuilder,
private msg: NzMessageService,
@Inject(ALAIN_I18N_TOKEN) private i18n: I18NService,
private router: Router,
private cdr: ChangeDetectorRef
) { }
ngOnInit(): void {
this.fetch();
}
onQueryParamsChange(tableQueryParams: NzTableQueryParams): void {
this.query.params.pageNumber = tableQueryParams.pageIndex;
this.query.params.pageSize = tableQueryParams.pageSize;
this.fetch();
}
onSearch(): void {
this.fetch();
}
onReset(): void { }
onEditPermission(e: MouseEvent, appId: String, appName: String): void {
this.router.navigateByUrl(`/permissions/privileges?appId=${appId}&appName=${appName}`);
}
onEditResource(e: MouseEvent, appId: String, appName: String): void {
this.router.navigateByUrl(`/permissions/resources?appId=${appId}&appName=${appName}`);
}
fetch(): void {
this.query.submitLoading = true;
this.query.tableLoading = true;
this.query.indeterminate = false;
this.query.checked = false;
this.query.tableCheckedId.clear();
if (this.query.expandForm) {
this.query.params.endDate = format(this.query.params.endDatePicker, 'yyyy-MM-dd HH:mm:ss');
this.query.params.startDate = format(this.query.params.startDatePicker, 'yyyy-MM-dd HH:mm:ss');
} else {
this.query.params.endDate = '';
this.query.params.startDate = '';
}
this.appsService.fetch(this.query.params).subscribe(res => {
this.query.results = res.data;
this.query.submitLoading = false;
this.query.tableLoading = false;
this.cdr.detectChanges();
});
}
updateTableCheckedSet(id: String, checked: boolean): void {
if (checked) {
this.query.tableCheckedId.add(id);
} else {
this.query.tableCheckedId.delete(id);
}
}
refreshTableCheckedStatus(): void {
const listOfEnabledData = this.query.results.rows.filter(({ disabled }) => !disabled);
this.query.checked = listOfEnabledData.every(({ id }) => this.query.tableCheckedId.has(id));
this.query.indeterminate = listOfEnabledData.some(({ id }) => this.query.tableCheckedId.has(id)) && !this.query.checked;
}
onTableItemChecked(id: String, checked: boolean): void {
this.updateTableCheckedSet(id, checked);
this.refreshTableCheckedStatus();
}
onTableAllChecked(checked: boolean): void {
this.query.results.rows.filter(({ disabled }) => !disabled).forEach(({ id }) => this.updateTableCheckedSet(id, checked));
this.refreshTableCheckedStatus();
}
}

View File

@ -20,10 +20,15 @@ import { RouterModule, Routes } from '@angular/router';
import { SharedModule } from '@shared'; import { SharedModule } from '@shared';
import { NzIconModule } from 'ng-zorro-antd/icon'; import { NzIconModule } from 'ng-zorro-antd/icon';
import { AppsComponent } from './apps/apps.component';
import { PrivilegesComponent } from './privileges/privileges.component'; import { PrivilegesComponent } from './privileges/privileges.component';
import { ResourceEditerComponent } from './resources/resource-editer/resource-editer.component'; import { ResourceEditerComponent } from './resources/resource-editer/resource-editer.component';
import { ResourcesComponent } from './resources/resources.component'; import { ResourcesComponent } from './resources/resources.component';
const routes: Routes = [ const routes: Routes = [
{
path: 'apps',
component: AppsComponent
},
{ {
path: 'resources', path: 'resources',
component: ResourcesComponent component: ResourcesComponent
@ -37,8 +42,8 @@ const routes: Routes = [
const COMPONENTS = [ResourcesComponent, PrivilegesComponent, ResourceEditerComponent]; const COMPONENTS = [ResourcesComponent, PrivilegesComponent, ResourceEditerComponent];
@NgModule({ @NgModule({
declarations: [...COMPONENTS], declarations: [...COMPONENTS, AppsComponent],
imports: [NzIconModule, SharedModule, CommonModule, RouterModule.forChild(routes)], imports: [NzIconModule, SharedModule, CommonModule, RouterModule.forChild(routes)],
exports: [RouterModule] exports: [RouterModule]
}) })
export class PermissionsModule {} export class PermissionsModule { }

View File

@ -5,46 +5,26 @@
<div nz-row [nzGutter]="{ xs: 8, sm: 8, md: 8, lg: 24, xl: 48, xxl: 48 }"> <div nz-row [nzGutter]="{ xs: 8, sm: 8, md: 8, lg: 24, xl: 48, xxl: 48 }">
<div nz-col nzMd="10" nzSm="24"> <div nz-col nzMd="10" nzSm="24">
<nz-form-item> <nz-form-item>
<nz-form-label nzFor="groupName">{{ 'mxk.roles.name' | i18n }}</nz-form-label> <nz-form-label nzFor="name">{{ 'mxk.resources.appName' | i18n }}</nz-form-label>
<nz-form-control> <input nz-input [(ngModel)]="query.params.appName" [ngModelOptions]="{ standalone: true }" disabled />
<input
nz-input
[(ngModel)]="query.params.groupName"
[ngModelOptions]="{ standalone: true }"
name="groupName"
placeholder=""
id="groupName"
/>
</nz-form-control>
</nz-form-item> </nz-form-item>
</div> </div>
<div nz-col nzMd="10" nzSm="24"> <div nz-col nzMd="10" nzSm="24">
<nz-form-item> <nz-form-item>
<nz-form-label nzFor="name">{{ 'mxk.resources.appName' | i18n }}</nz-form-label> <nz-form-label nzFor="groupName">{{ 'mxk.roles.name' | i18n }}</nz-form-label>
<nz-form-control> <nz-form-control>
<nz-input-group nzSearch [nzAddOnAfter]="suffixButton"> <input nz-input [(ngModel)]="query.params.groupName" [ngModelOptions]="{ standalone: true }"
<input name="groupName" placeholder="" id="groupName" />
nz-input
[(ngModel)]="query.params.appName"
[ngModelOptions]="{ standalone: true }"
name="appName"
readonly
placeholder=""
id="appName"
/>
</nz-input-group>
<ng-template #suffixButton>
<button nz-button nzType="primary" (click)="onSelect($event)" nzSearch>{{ 'mxk.text.select' | i18n }}</button>
</ng-template>
</nz-form-control> </nz-form-control>
</nz-form-item> </nz-form-item>
</div> </div>
<div nz-col [nzSpan]="query.expandForm ? 24 : 4" [class.text-right]="query.expandForm"> <div nz-col [nzSpan]="query.expandForm ? 24 : 4" [class.text-right]="query.expandForm">
<button nz-button type="submit" [nzType]="'primary'" [nzLoading]="query.submitLoading">{{ 'mxk.text.query' | i18n }}</button> <button nz-button type="submit" [nzType]="'primary'" [nzLoading]="query.submitLoading">{{ 'mxk.text.query' |
<button nz-button type="reset" (click)="onReset()" class="mx-sm" style="display: none">{{ 'mxk.text.reset' | i18n }}</button> i18n }}</button>
<button nz-button type="reset" (click)="onReset()" class="mx-sm" style="display: none">{{ 'mxk.text.reset' |
i18n }}</button>
<button nz-button (click)="query.expandForm = !query.expandForm" class="mx-sm" style="display: none"> <button nz-button (click)="query.expandForm = !query.expandForm" class="mx-sm" style="display: none">
{{ query.expandForm ? ('mxk.text.collapse' | i18n) : ('mxk.text.expand' | i18n) }}</button {{ query.expandForm ? ('mxk.text.collapse' | i18n) : ('mxk.text.expand' | i18n) }}</button>
>
</div> </div>
</div> </div>
</form> </form>
@ -55,21 +35,11 @@
</div> </div>
<div nz-row [nzGutter]="{ xs: 8, sm: 8, md: 8, lg: 24, xl: 48, xxl: 48 }"> <div nz-row [nzGutter]="{ xs: 8, sm: 8, md: 8, lg: 24, xl: 48, xxl: 48 }">
<div nz-col [nzSpan]="10" class="grid-border"> <div nz-col [nzSpan]="10" class="grid-border">
<nz-table <nz-table #dynamicTable nzTableLayout="auto" nzSize="small" nzBordered nzShowSizeChanger
#dynamicTable [nzData]="query.results.rows" [nzFrontPagination]="false" [nzTotal]="query.results.records"
nzTableLayout="auto" [nzPageSizeOptions]="query.params.pageSizeOptions" [nzPageSize]="query.params.pageSize"
nzSize="small" [nzPageIndex]="query.params.pageNumber" [nzLoading]="this.query.tableLoading"
nzBordered (nzQueryParams)="onQueryParamsChange($event)">
nzShowSizeChanger
[nzData]="query.results.rows"
[nzFrontPagination]="false"
[nzTotal]="query.results.records"
[nzPageSizeOptions]="query.params.pageSizeOptions"
[nzPageSize]="query.params.pageSize"
[nzPageIndex]="query.params.pageNumber"
[nzLoading]="this.query.tableLoading"
(nzQueryParams)="onQueryParamsChange($event)"
>
<thead> <thead>
<tr> <tr>
<!--<th [nzChecked]="query.checked" [nzIndeterminate]="query.indeterminate" (nzCheckedChange)="onTableAllChecked($event)"></th> <!--<th [nzChecked]="query.checked" [nzIndeterminate]="query.indeterminate" (nzCheckedChange)="onTableAllChecked($event)"></th>
@ -82,11 +52,8 @@
</thead> </thead>
<tbody> <tbody>
<tr *ngFor="let data of query.results.rows"> <tr *ngFor="let data of query.results.rows">
<td <td [nzChecked]="query.tableCheckedId.has(data.id)" [nzDisabled]="data.disabled"
[nzChecked]="query.tableCheckedId.has(data.id)" (nzCheckedChange)="onTableItemChecked(data.id, $event)"></td>
[nzDisabled]="data.disabled"
(nzCheckedChange)="onTableItemChecked(data.id, $event)"
></td>
<td nzAlign="left" style="display: none"> <td nzAlign="left" style="display: none">
<span>{{ data.id }}</span> <span>{{ data.id }}</span>
</td> </td>
@ -98,16 +65,9 @@
</nz-table> </nz-table>
</div> </div>
<div nz-col [nzSpan]="14" class="grid-border"> <div nz-col [nzSpan]="14" class="grid-border">
<nz-tree <nz-tree #nzTreeComponent nzShowLine="false" [nzCheckable]="treeNodes.checkable"
#nzTreeComponent [nzCheckedKeys]="treeNodes.checkedKeys" nzBlockNode [nzData]="treeNodes.nodes" (nzDblClick)="openFolder($event)"
nzShowLine="false" [nzTreeTemplate]="nzTreeTemplate"></nz-tree>
[nzCheckable]="treeNodes.checkable"
[nzCheckedKeys]="treeNodes.checkedKeys"
nzBlockNode
[nzData]="treeNodes.nodes"
(nzDblClick)="openFolder($event)"
[nzTreeTemplate]="nzTreeTemplate"
></nz-tree>
<ng-template #nzTreeTemplate let-node let-origin="origin"> <ng-template #nzTreeTemplate let-node let-origin="origin">
<span class="custom-node"> <span class="custom-node">
<span *ngIf="!node.isLeaf"> <span *ngIf="!node.isLeaf">

View File

@ -25,6 +25,7 @@ import {
Inject Inject
} from '@angular/core'; } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms'; import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { ActivatedRoute, Router } from '@angular/router';
import { I18NService } from '@core'; import { I18NService } from '@core';
import { _HttpClient, ALAIN_I18N_TOKEN, SettingsService } from '@delon/theme'; import { _HttpClient, ALAIN_I18N_TOKEN, SettingsService } from '@delon/theme';
import { format, addDays } from 'date-fns'; import { format, addDays } from 'date-fns';
@ -36,8 +37,8 @@ import { NzTableQueryParams } from 'ng-zorro-antd/table';
import { NzFormatEmitEvent, NzTreeNode, NzTreeNodeOptions, NzTreeComponent } from 'ng-zorro-antd/tree'; import { NzFormatEmitEvent, NzTreeNode, NzTreeNodeOptions, NzTreeComponent } from 'ng-zorro-antd/tree';
import { TreeNodes } from '../../../entity/TreeNodes'; import { TreeNodes } from '../../../entity/TreeNodes';
import { GroupsService } from '../../../service/groups.service';
import { GroupPrivilegesService } from '../../../service/group-privileges.service'; import { GroupPrivilegesService } from '../../../service/group-privileges.service';
import { GroupsService } from '../../../service/groups.service';
import { ResourcesService } from '../../../service/resources.service'; import { ResourcesService } from '../../../service/resources.service';
import { set2String } from '../../../shared/index'; import { set2String } from '../../../shared/index';
import { SelectAppsComponent } from '../../apps/select-apps/select-apps.component'; import { SelectAppsComponent } from '../../apps/select-apps/select-apps.component';
@ -109,6 +110,7 @@ export class PrivilegesComponent implements OnInit {
private resourcesService: ResourcesService, private resourcesService: ResourcesService,
private groupsService: GroupsService, private groupsService: GroupsService,
private viewContainerRef: ViewContainerRef, private viewContainerRef: ViewContainerRef,
private route: ActivatedRoute,
private fb: FormBuilder, private fb: FormBuilder,
private msg: NzMessageService, private msg: NzMessageService,
@Inject(ALAIN_I18N_TOKEN) private i18n: I18NService, @Inject(ALAIN_I18N_TOKEN) private i18n: I18NService,
@ -117,6 +119,12 @@ export class PrivilegesComponent implements OnInit {
) { } ) { }
ngOnInit(): void { ngOnInit(): void {
if (this.route.snapshot.queryParams['appId']) {
this.query.params.appId = this.route.snapshot.queryParams['appId'];
this.query.params.appName = this.route.snapshot.queryParams['appName'];
this.fetch();
this.tree();
}
this.fetch(); this.fetch();
} }

View File

@ -6,16 +6,8 @@
<div nz-col nzMd="10" nzSm="24"> <div nz-col nzMd="10" nzSm="24">
<nz-form-item> <nz-form-item>
<nz-form-label nzFor="name">{{ 'mxk.resources.appName' | i18n }}</nz-form-label> <nz-form-label nzFor="name">{{ 'mxk.resources.appName' | i18n }}</nz-form-label>
<nz-form-control> <input nz-input [(ngModel)]="query.params.appName" [ngModelOptions]="{ standalone: true }" disabled
<nz-input-group nzSearch [nzAddOnAfter]="suffixButton"> placeholder="" />
<input nz-input [(ngModel)]="query.params.appName" [ngModelOptions]="{ standalone: true }" name="appName"
readonly placeholder="" id="appName" />
</nz-input-group>
<ng-template #suffixButton>
<button nz-button nzType="primary" (click)="onSelect($event)" nzSearch>{{ 'mxk.text.select' | i18n
}}</button>
</ng-template>
</nz-form-control>
</nz-form-item> </nz-form-item>
</div> </div>
<div nz-col nzMd="10" nzSm="24"> <div nz-col nzMd="10" nzSm="24">
@ -23,7 +15,7 @@
<nz-form-label nzFor="resourceName">{{ 'mxk.resources.name' | i18n }}</nz-form-label> <nz-form-label nzFor="resourceName">{{ 'mxk.resources.name' | i18n }}</nz-form-label>
<nz-form-control> <nz-form-control>
<input nz-input [(ngModel)]="query.params.resourceName" [ngModelOptions]="{ standalone: true }" <input nz-input [(ngModel)]="query.params.resourceName" [ngModelOptions]="{ standalone: true }"
name="resourceName" placeholder="" id="resourceName" /> name="resourceName" placeholder="" id="resourceName" />
</nz-form-control> </nz-form-control>
</nz-form-item> </nz-form-item>
</div> </div>
@ -48,7 +40,7 @@
</div> </div>
<div nz-col nzMd="6" nzSm="24" class="grid-border"> <div nz-col nzMd="6" nzSm="24" class="grid-border">
<nz-tree nzShowLine="false" [nzCheckable]="treeNodes.checkable" nzBlockNode [nzData]="treeNodes.nodes" <nz-tree nzShowLine="false" [nzCheckable]="treeNodes.checkable" nzBlockNode [nzData]="treeNodes.nodes"
(nzClick)="activeNode($event)" (nzDblClick)="openFolder($event)" [nzTreeTemplate]="nzTreeTemplate"></nz-tree> (nzClick)="activeNode($event)" (nzDblClick)="openFolder($event)" [nzTreeTemplate]="nzTreeTemplate"></nz-tree>
<ng-template #nzTreeTemplate let-node let-origin="origin"> <ng-template #nzTreeTemplate let-node let-origin="origin">
<span class="custom-node"> <span class="custom-node">
<span *ngIf="!node.isLeaf" (contextmenu)="contextMenu($event, menu)"> <span *ngIf="!node.isLeaf" (contextmenu)="contextMenu($event, menu)">
@ -69,43 +61,43 @@
</nz-dropdown-menu> </nz-dropdown-menu>
</div> </div>
<div nz-col nzMd="18" nzSm="24" class="grid-border"> <div nz-col nzMd="18" nzSm="24" class="grid-border">
<nz-table #dynamicTable nzTableLayout="auto" nzSize="small" nzBordered nzShowSizeChanger [nzData]="query.results.rows" <nz-table #dynamicTable nzTableLayout="auto" nzSize="small" nzBordered nzShowSizeChanger
[nzFrontPagination]="false" [nzTotal]="query.results.records" [nzPageSizeOptions]="query.params.pageSizeOptions" [nzData]="query.results.rows" [nzFrontPagination]="false" [nzTotal]="query.results.records"
[nzPageSize]="query.params.pageSize" [nzPageIndex]="query.params.pageNumber" [nzPageSizeOptions]="query.params.pageSizeOptions" [nzPageSize]="query.params.pageSize"
[nzLoading]="this.query.tableLoading" (nzQueryParams)="onQueryParamsChange($event)" nzWidth="100%"> [nzPageIndex]="query.params.pageNumber" [nzLoading]="this.query.tableLoading"
(nzQueryParams)="onQueryParamsChange($event)" nzWidth="100%">
<thead> <thead>
<tr> <tr>
<th [nzChecked]="query.checked" [nzIndeterminate]="query.indeterminate" <th [nzChecked]="query.checked" [nzIndeterminate]="query.indeterminate"
(nzCheckedChange)="onTableAllChecked($event)"></th> (nzCheckedChange)="onTableAllChecked($event)"></th>
<th nzAlign="center">{{ 'mxk.resources.appName' | i18n }}</th> <th nzAlign="center">{{ 'mxk.resources.appName' | i18n }}</th>
<th nzAlign="center">{{ 'mxk.resources.name' | i18n }}</th> <th nzAlign="center">{{ 'mxk.resources.name' | i18n }}</th>
<th nzAlign="center">{{ 'mxk.resources.resourceType' | i18n }}</th> <th nzAlign="center">{{ 'mxk.resources.resourceType' | i18n }}</th>
<th nzAlign="center">{{ 'mxk.text.sortIndex' | i18n }}</th> <th nzAlign="center">{{ 'mxk.text.sortIndex' | i18n }}</th>
<th nzAlign="center">{{ 'mxk.text.status' | i18n }}</th> <th nzAlign="center">{{ 'mxk.text.status' | i18n }}</th>
<th nzAlign="center" class="table_cell_action_2">{{ 'mxk.text.action' | i18n }}</th> <th nzAlign="center" class="table_cell_action_2">{{ 'mxk.text.action' | i18n }}</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
<tr *ngFor="let data of query.results.rows"> <tr *ngFor="let data of query.results.rows">
<td [nzChecked]="query.tableCheckedId.has(data.id)" [nzDisabled]="data.disabled" <td [nzChecked]="query.tableCheckedId.has(data.id)" [nzDisabled]="data.disabled"
(nzCheckedChange)="onTableItemChecked(data.id, $event)"></td> (nzCheckedChange)="onTableItemChecked(data.id, $event)"></td>
<td nzAlign="center"> <td nzAlign="center">
{{ data.appName }} {{ data.appName }}
</td> </td>
<td nzAlign="left"> {{ data.resourceName }}</td> <td nzAlign="left"> {{ data.resourceName }}</td>
<td nzAlign="left"> {{ data.resourceType }}</td> <td nzAlign="left"> {{ data.resourceType }}</td>
<td nzAlign="center"> {{ data.sortIndex }}</td> <td nzAlign="center"> {{ data.sortIndex }}</td>
<td nzAlign="center"> <i *ngIf="data.status == 1" nz-icon nzType="check-circle" nzTheme="fill" <td nzAlign="center"> <i *ngIf="data.status == 1" nz-icon nzType="check-circle" nzTheme="fill"
style="color: green"></i></td> style="color: green"></i></td>
<td nzAlign="center" nzBreakWord="false"> <td nzAlign="center" nzBreakWord="false">
<div nz-col> <div nz-col>
<button nz-button type="button" (click)="onEdit($event, data.id)">{{ 'mxk.text.edit' <button nz-button type="button" (click)="onEdit($event, data.id)">{{ 'mxk.text.edit' | i18n }}</button>
| i18n }}</button> <button nz-button type="button" (click)="onDelete($event, data.id)" nzDanger>{{ 'mxk.text.delete' | i18n
<button nz-button type="button" (click)="onDelete($event, data.id)" nzDanger>{{ 'mxk.text.delete' | i18n }}</button>
}}</button> </div>
</div> </td>
</td> </tr>
</tr>
</tbody> </tbody>
</nz-table> </nz-table>
</div> </div>

View File

@ -1,16 +1,7 @@
<ng-template #icon let-i> <ng-template #icon let-i>
<ng-container *ngIf="i" [ngSwitch]="i.type"> <ng-container *ngIf="i" [ngSwitch]="i.type">
<i <i *ngSwitchCase="'icon'" class="sidebar-nav__item-icon" nz-icon [nzType]="i.value" [nzTheme]="i.theme"
*ngSwitchCase="'icon'" [nzSpin]="i.spin" [nzTwotoneColor]="i.twoToneColor" [nzIconfont]="i.iconfont" [nzRotate]="i.rotate"></i>
class="sidebar-nav__item-icon"
nz-icon
[nzType]="i.value"
[nzTheme]="i.theme"
[nzSpin]="i.spin"
[nzTwotoneColor]="i.twoToneColor"
[nzIconfont]="i.iconfont"
[nzRotate]="i.rotate"
></i>
<i *ngSwitchCase="'iconfont'" class="sidebar-nav__item-icon" nz-icon [nzIconfont]="i.iconfont"></i> <i *ngSwitchCase="'iconfont'" class="sidebar-nav__item-icon" nz-icon [nzIconfont]="i.iconfont"></i>
<img *ngSwitchCase="'img'" [src]="i.value" class="sidebar-nav__item-icon sidebar-nav__item-img" /> <img *ngSwitchCase="'img'" [src]="i.value" class="sidebar-nav__item-icon sidebar-nav__item-img" />
<span *ngSwitchCase="'svg'" class="sidebar-nav__item-icon sidebar-nav__item-svg" [innerHTML]="i.value"></span> <span *ngSwitchCase="'svg'" class="sidebar-nav__item-icon sidebar-nav__item-svg" [innerHTML]="i.value"></span>
@ -19,21 +10,12 @@
</ng-template> </ng-template>
<ng-template #tree let-ls> <ng-template #tree let-ls>
<ng-container *ngFor="let i of ls"> <ng-container *ngFor="let i of ls">
<li <li class="sidebar-nav__item" [class.sidebar-nav__selected]="i._selected" [class.sidebar-nav__open]="i._open"
*ngIf="i._hidden !== true" style="display: {{ i._hidden ? 'none;' : 'block' }}">
class="sidebar-nav__item"
[class.sidebar-nav__selected]="i._selected"
[class.sidebar-nav__open]="i._open"
>
<!-- link --> <!-- link -->
<a <a *ngIf="i.children.length === 0 || i.link !== ''" (click)="to(i)" [attr.data-id]="i._id"
*ngIf="i.children.length === 0" class="sidebar-nav__item-link" [ngClass]="{ 'sidebar-nav__item-disabled': i.disabled }"
(click)="to(i)" (mouseenter)="closeSubMenu()">
[attr.data-id]="i._id"
class="sidebar-nav__item-link"
[ngClass]="{ 'sidebar-nav__item-disabled': i.disabled }"
(mouseenter)="closeSubMenu()"
>
<ng-container *ngIf="i._needIcon"> <ng-container *ngIf="i._needIcon">
<ng-container *ngIf="!collapsed"> <ng-container *ngIf="!collapsed">
<ng-template [ngTemplateOutlet]="icon" [ngTemplateOutletContext]="{ $implicit: i.icon }"></ng-template> <ng-template [ngTemplateOutlet]="icon" [ngTemplateOutletContext]="{ $implicit: i.icon }"></ng-template>
@ -45,7 +27,8 @@
<span class="sidebar-nav__item-text" [innerHTML]="i._text" [attr.title]="i.text"></span> <span class="sidebar-nav__item-text" [innerHTML]="i._text" [attr.title]="i.text"></span>
</a> </a>
<!-- has children link --> <!-- has children link -->
<a *ngIf="i.children.length > 0" (click)="toggleOpen(i)" (mouseenter)="showSubMenu($event, i)" class="sidebar-nav__item-link"> <a *ngIf="i.children.length > 0 && i.link === ''" (click)="toggleOpen(i)" (mouseenter)="showSubMenu($event, i)"
class="sidebar-nav__item-link">
<ng-template [ngTemplateOutlet]="icon" [ngTemplateOutletContext]="{ $implicit: i.icon }"></ng-template> <ng-template [ngTemplateOutlet]="icon" [ngTemplateOutletContext]="{ $implicit: i.icon }"></ng-template>
<span class="sidebar-nav__item-text" [innerHTML]="i._text" [attr.title]="i.text"></span> <span class="sidebar-nav__item-text" [innerHTML]="i._text" [attr.title]="i.text"></span>
<i class="sidebar-nav__sub-arrow"></i> <i class="sidebar-nav__sub-arrow"></i>
@ -60,11 +43,13 @@
</ng-template> </ng-template>
<ul class="sidebar-nav"> <ul class="sidebar-nav">
<ng-container *ngFor="let group of list"> <ng-container *ngFor="let group of list">
<li class="sidebar-nav__item sidebar-nav__group-title" *ngIf="group.group"> <span [innerHTML]="group._text"></span> </li> <li class="sidebar-nav__item sidebar-nav__group-title" *ngIf="group.group"> <span [innerHTML]="group._text"></span>
</li>
<ng-template [ngTemplateOutlet]="tree" [ngTemplateOutletContext]="{ $implicit: group.children }"></ng-template> <ng-template [ngTemplateOutlet]="tree" [ngTemplateOutletContext]="{ $implicit: group.children }"></ng-template>
</ng-container> </ng-container>
<li> <li>
<div class="alain-default__nav-item alain-default__nav-item--collapse alain-default__nav-item_collapsed" (click)="toggleCollapsed()"> <div class="alain-default__nav-item alain-default__nav-item--collapse alain-default__nav-item_collapsed"
(click)="toggleCollapsed()">
<i nz-icon [nzType]="collapsedIcon"></i> <i nz-icon [nzType]="collapsedIcon"></i>
</div> </div>
</li> </li>

View File

@ -20,7 +20,6 @@
{ {
"text": "身份管理", "text": "身份管理",
"i18n": "mxk.menu.identities", "i18n": "mxk.menu.identities",
"link": "/organizations",
"icon": "anticon-user", "icon": "anticon-user",
"children": [ "children": [
{ {
@ -64,7 +63,6 @@
{ {
"text": "访问控制", "text": "访问控制",
"i18n": "mxk.menu.access", "i18n": "mxk.menu.access",
"link": "/access",
"icon": "anticon-safety", "icon": "anticon-safety",
"children": [ "children": [
{ {
@ -86,29 +84,38 @@
{ {
"text": "权限管理", "text": "权限管理",
"i18n": "mxk.menu.permissions", "i18n": "mxk.menu.permissions",
"link": "/permissions",
"icon": "anticon-radar-chart", "icon": "anticon-radar-chart",
"children": [ "children": [
{ {
"text": "资源管理", "text": "应用列表",
"i18n": "mxk.menu.permissions.resources", "i18n": "mxk.menu.permissions",
"link": "/permissions/resources", "link": "/permissions/apps",
"icon": "anticon-read", "icon": "anticon-read",
"children": [] "children": [
}, {
{ "text": "资源管理",
"text": "权限管理", "i18n": "mxk.menu.permissions.resources",
"i18n": "mxk.menu.permissions.privileges", "link": "/permissions/resources",
"link": "/permissions/privileges", "icon": "anticon-read",
"icon": "anticon-carry-out", "hide":true,
"children": [] "children": []
},
{
"text": "权限管理",
"i18n": "mxk.menu.permissions.privileges",
"link": "/permissions/privileges",
"icon": "anticon-carry-out",
"hide":true,
"children": []
}
]
} }
] ]
}, },
{ {
"text": "配置管理", "text": "配置管理",
"i18n": "mxk.menu.config", "i18n": "mxk.menu.config",
"link": "/config",
"icon": "anticon-setting", "icon": "anticon-setting",
"children": [ "children": [
{ {
@ -179,7 +186,6 @@
{ {
"text": "日志审计", "text": "日志审计",
"i18n": "mxk.menu.audit", "i18n": "mxk.menu.audit",
"link": "/audit",
"icon": "anticon-history", "icon": "anticon-history",
"children": [ "children": [
{ {

View File

@ -274,6 +274,7 @@
"tab.custom": "Custom", "tab.custom": "Custom",
"extendapi.tab": "API", "extendapi.tab": "API",
"resources":"Resources", "resources":"Resources",
"permission":"Permission",
"id": "App Id", "id": "App Id",
"name": "App Name", "name": "App Name",
"icon": "Icon", "icon": "Icon",

View File

@ -275,6 +275,7 @@
"tab.custom": "自定义属性", "tab.custom": "自定义属性",
"extendapi.tab": "API配置", "extendapi.tab": "API配置",
"resources":"资源", "resources":"资源",
"permission":"权限",
"id": "应用编码", "id": "应用编码",
"name": "应用名称", "name": "应用名称",
"icon": "图标", "icon": "图标",

View File

@ -276,6 +276,7 @@
"tab.custom": "自訂屬性", "tab.custom": "自訂屬性",
"extendapi.tab": "API配置", "extendapi.tab": "API配置",
"resources":"資源", "resources":"資源",
"permission":"權限",
"id": "應用編碼", "id": "應用編碼",
"name": "應用名稱", "name": "應用名稱",
"icon": "圖標", "icon": "圖標",