19 changed files with 406 additions and 207 deletions
@ -1,120 +1,106 @@ |
|||||
{ |
{ |
||||
"$schema": "./node_modules/@angular/cli/lib/config/schema.json", |
"$schema": "./node_modules/@angular/cli/lib/config/schema.json", |
||||
"version": 1, |
"version": 1, |
||||
"newProjectRoot": "projects", |
"newProjectRoot": "projects", |
||||
"projects": { |
"projects": { |
||||
"license-web-app": { |
"license-web-app": { |
||||
"projectType": "application", |
"projectType": "application", |
||||
"schematics": { |
"schematics": { |
||||
"@schematics/angular:component": { |
"@schematics/angular:component": { |
||||
"style": "less" |
"style": "less" |
||||
} |
} |
||||
}, |
}, |
||||
"root": "", |
"root": "", |
||||
"sourceRoot": "src", |
"sourceRoot": "src", |
||||
"prefix": "app", |
"prefix": "app", |
||||
"architect": { |
"architect": { |
||||
"build": { |
"build": { |
||||
"builder": "@angular-devkit/build-angular:application", |
"builder": "@angular-devkit/build-angular:application", |
||||
"options": { |
"options": { |
||||
"outputPath": "dist/license-web-app", |
"outputPath": "dist/license-web-app", |
||||
"index": "src/index.html", |
"index": "src/index.html", |
||||
"browser": "src/main.ts", |
"browser": "src/main.ts", |
||||
"polyfills": [ |
"polyfills": ["zone.js"], |
||||
"zone.js" |
"tsConfig": "tsconfig.app.json", |
||||
], |
"inlineStyleLanguage": "less", |
||||
"tsConfig": "tsconfig.app.json", |
"assets": [ |
||||
"inlineStyleLanguage": "less", |
"src/favicon.ico", |
||||
"assets": [ |
"src/assets", |
||||
"src/favicon.ico", |
{ |
||||
"src/assets", |
"glob": "**/*", |
||||
{ |
"input": "./node_modules/@ant-design/icons-angular/src/inline-svg/", |
||||
"glob": "**/*", |
"output": "/assets/" |
||||
"input": "./node_modules/@ant-design/icons-angular/src/inline-svg/", |
}, |
||||
"output": "/assets/" |
{ |
||||
}, |
"glob": "**/*", |
||||
{ |
"input": "node_modules/tinymce", |
||||
"glob": "**/*", |
"output": "/assets/tinymce/" |
||||
"input": "node_modules/tinymce", |
} |
||||
"output": "/assets/tinymce/" |
], |
||||
} |
"styles": ["src/styles.less"], |
||||
], |
"scripts": ["node_modules/tinymce/tinymce.min.js"] |
||||
"styles": [ |
}, |
||||
"src/styles.less" |
"configurations": { |
||||
], |
"production": { |
||||
"scripts": [ |
"budgets": [ |
||||
"node_modules/tinymce/tinymce.min.js" |
{ |
||||
] |
"type": "initial", |
||||
}, |
"maximumWarning": "10mb", |
||||
"configurations": { |
"maximumError": "10mb" |
||||
"production": { |
}, |
||||
"budgets": [ |
{ |
||||
{ |
"type": "anyComponentStyle", |
||||
"type": "initial", |
"maximumWarning": "10mb", |
||||
"maximumWarning": "10mb", |
"maximumError": "10mb" |
||||
"maximumError": "10mb" |
} |
||||
}, |
], |
||||
{ |
"outputHashing": "all" |
||||
"type": "anyComponentStyle", |
}, |
||||
"maximumWarning": "10mb", |
"development": { |
||||
"maximumError": "10mb" |
"optimization": false, |
||||
} |
"extractLicenses": false, |
||||
], |
"sourceMap": true |
||||
"outputHashing": "all" |
} |
||||
}, |
}, |
||||
"development": { |
"defaultConfiguration": "production" |
||||
"optimization": false, |
}, |
||||
"extractLicenses": false, |
"serve": { |
||||
"sourceMap": true |
"builder": "@angular-devkit/build-angular:dev-server", |
||||
} |
"configurations": { |
||||
}, |
"production": { |
||||
"defaultConfiguration": "production" |
"buildTarget": "license-web-app:build:production" |
||||
}, |
}, |
||||
"serve": { |
"development": { |
||||
"builder": "@angular-devkit/build-angular:dev-server", |
"buildTarget": "license-web-app:build:development" |
||||
"configurations": { |
} |
||||
"production": { |
}, |
||||
"buildTarget": "license-web-app:build:production" |
"defaultConfiguration": "development", |
||||
}, |
"options": { |
||||
"development": { |
"port": 7001, |
||||
"buildTarget": "license-web-app:build:development" |
"host": "0.0.0.0" |
||||
} |
} |
||||
}, |
}, |
||||
"defaultConfiguration": "development", |
"extract-i18n": { |
||||
"options": { |
"builder": "@angular-devkit/build-angular:extract-i18n", |
||||
"port": 6001, |
"options": { |
||||
"host": "0.0.0.0" |
"buildTarget": "license-web-app:build" |
||||
} |
} |
||||
}, |
}, |
||||
"extract-i18n": { |
"test": { |
||||
"builder": "@angular-devkit/build-angular:extract-i18n", |
"builder": "@angular-devkit/build-angular:karma", |
||||
"options": { |
"options": { |
||||
"buildTarget": "license-web-app:build" |
"polyfills": ["zone.js", "zone.js/testing"], |
||||
} |
"tsConfig": "tsconfig.spec.json", |
||||
}, |
"inlineStyleLanguage": "less", |
||||
"test": { |
"assets": ["src/favicon.ico", "src/assets"], |
||||
"builder": "@angular-devkit/build-angular:karma", |
"styles": ["src/styles.less"], |
||||
"options": { |
"scripts": [] |
||||
"polyfills": [ |
} |
||||
"zone.js", |
} |
||||
"zone.js/testing" |
} |
||||
], |
} |
||||
"tsConfig": "tsconfig.spec.json", |
}, |
||||
"inlineStyleLanguage": "less", |
"cli": { |
||||
"assets": [ |
"analytics": false |
||||
"src/favicon.ico", |
} |
||||
"src/assets" |
} |
||||
], |
|
||||
"styles": [ |
|
||||
"src/styles.less" |
|
||||
], |
|
||||
"scripts": [] |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
}, |
|
||||
"cli": { |
|
||||
"analytics": false |
|
||||
} |
|
||||
} |
|
||||
|
@ -0,0 +1,30 @@ |
|||||
|
<div cl> |
||||
|
<nz-checkbox-wrapper> |
||||
|
<div class="checkAll mb-3"> |
||||
|
<label |
||||
|
nz-checkbox |
||||
|
[(ngModel)]="checkAll" |
||||
|
(ngModelChange)="onCheckAll($event)" |
||||
|
[nzIndeterminate]="indeterminate" |
||||
|
> |
||||
|
全选/取消 |
||||
|
</label> |
||||
|
</div> |
||||
|
<div class="h-64 overflow-y-auto p-3"> |
||||
|
<div nz-row [nzGutter]="[12, 12]"> |
||||
|
@for (item of menus; track $index) { |
||||
|
<div nz-col nzSpan="8"> |
||||
|
<label |
||||
|
nz-checkbox |
||||
|
[nzValue]="item.menuId" |
||||
|
(nzCheckedChange)="onMenuChange($event, item)" |
||||
|
[nzChecked]="value.has(item.menuId)" |
||||
|
> |
||||
|
{{ item.menuName }} |
||||
|
</label> |
||||
|
</div> |
||||
|
} |
||||
|
</div> |
||||
|
</div> |
||||
|
</nz-checkbox-wrapper> |
||||
|
</div> |
@ -0,0 +1,4 @@ |
|||||
|
.checkAll { |
||||
|
padding: 12px 0; |
||||
|
border-bottom: 1px solid #e8e8e8; |
||||
|
} |
@ -0,0 +1,98 @@ |
|||||
|
import { CommonModule } from '@angular/common' |
||||
|
import { ChangeDetectorRef, Component, Input, OnInit, TemplateRef, forwardRef } from '@angular/core' |
||||
|
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms' |
||||
|
import { NzCardModule } from 'ng-zorro-antd/card' |
||||
|
import { NzSafeAny } from 'ng-zorro-antd/core/types' |
||||
|
import { NzModalModule, NzModalService } from 'ng-zorro-antd/modal' |
||||
|
|
||||
|
import { ApiService } from 'app/services' |
||||
|
import { NzMessageModule, NzMessageService } from 'ng-zorro-antd/message' |
||||
|
|
||||
|
import { SharedModule } from 'app/shared/shared.module' |
||||
|
|
||||
|
@Component({ |
||||
|
selector: 'app-permissions-select', |
||||
|
standalone: true, |
||||
|
imports: [SharedModule], |
||||
|
templateUrl: './permissions-select.component.html', |
||||
|
styleUrl: './permissions-select.component.less', |
||||
|
providers: [ |
||||
|
{ |
||||
|
provide: NG_VALUE_ACCESSOR, |
||||
|
multi: true, |
||||
|
useExisting: forwardRef(() => PermissionsSelectComponent), |
||||
|
}, |
||||
|
], |
||||
|
}) |
||||
|
export class PermissionsSelectComponent { |
||||
|
constructor( |
||||
|
private modal: NzModalService, |
||||
|
private api: ApiService, |
||||
|
private msg: NzMessageService, |
||||
|
private cdr: ChangeDetectorRef, |
||||
|
) {} |
||||
|
|
||||
|
value = new Set<NzSafeAny>() |
||||
|
|
||||
|
disabled = false |
||||
|
|
||||
|
menus: NzSafeAny[] = [] |
||||
|
|
||||
|
checkAll = false |
||||
|
|
||||
|
indeterminate = false |
||||
|
|
||||
|
ngOnInit(): void { |
||||
|
this.api.getMenus().subscribe((res) => { |
||||
|
this.menus = res.body |
||||
|
this.refreashCheckStatus() |
||||
|
}) |
||||
|
} |
||||
|
|
||||
|
onTouched = () => {} |
||||
|
|
||||
|
onCheckAll(checked: any) { |
||||
|
if (checked) { |
||||
|
this.value = new Set(this.menus.map((i) => i.menuId)) |
||||
|
} else { |
||||
|
this.value.clear() |
||||
|
} |
||||
|
this.refreashCheckStatus() |
||||
|
} |
||||
|
|
||||
|
onMenuChange(checked: NzSafeAny, item: NzSafeAny) { |
||||
|
if (checked) { |
||||
|
this.value.add(item.menuId) |
||||
|
} else { |
||||
|
this.value.delete(item.menuId) |
||||
|
} |
||||
|
this.refreashCheckStatus() |
||||
|
} |
||||
|
|
||||
|
refreashCheckStatus() { |
||||
|
this.indeterminate = this.menus.length !== 0 && this.value.size > 0 && this.menus.length !== this.value.size |
||||
|
this.checkAll = this.menus.length === this.value.size |
||||
|
this.onChange(Array.from(this.value)) |
||||
|
} |
||||
|
|
||||
|
onChange(v: NzSafeAny[]) {} |
||||
|
|
||||
|
writeValue(v: NzSafeAny[]): void { |
||||
|
if (Array.isArray(v) && v.length > 0) { |
||||
|
this.value = new Set(v) |
||||
|
this.refreashCheckStatus() |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
registerOnChange(fn: any): void { |
||||
|
this.onChange = fn |
||||
|
} |
||||
|
|
||||
|
registerOnTouched(fn: any): void { |
||||
|
this.onTouched = fn |
||||
|
} |
||||
|
|
||||
|
setDisabledState?(isDisabled: boolean): void { |
||||
|
this.disabled = isDisabled |
||||
|
} |
||||
|
} |
@ -1,19 +1,18 @@ |
|||||
import { inject } from '@angular/core' |
import { inject } from '@angular/core' |
||||
import { CanActivateFn, Router, UrlTree } from '@angular/router' |
import { CanActivateFn, Router, UrlTree } from '@angular/router' |
||||
import { ApiService, LocalHttpInterceptorService } from 'app/services' |
import { ApiService } from 'app/services' |
||||
import { map } from 'rxjs' |
import { PermissionService } from 'app/shared/permission/permission.service' |
||||
|
|
||||
export const authGuard: CanActivateFn = (route, state) => { |
export const authGuard: CanActivateFn = (route, state) => { |
||||
// const local = inject(LocalHttpInterceptorService)
|
|
||||
// const accessData = local.getAccess()
|
|
||||
// let token = accessData?.access_token
|
|
||||
// if (token) {
|
|
||||
// return true
|
|
||||
// }
|
|
||||
const router = inject(Router) |
const router = inject(Router) |
||||
|
const permission = inject(PermissionService) |
||||
const api = inject(ApiService) |
const api = inject(ApiService) |
||||
|
const authInfo = api.authInfo |
||||
if (!api.authInfo) { |
if (!api.authInfo) { |
||||
return router.createUrlTree(['/login']) |
return router.createUrlTree(['/login']) |
||||
} |
} |
||||
|
permission.loadPermission(authInfo?.permissions ?? []) |
||||
|
permission.isRoot = Boolean(authInfo?.roles.includes('admin')) |
||||
|
// console.log('authInfo', authInfo, Boolean(authInfo?.roles.includes('admin')), permission)
|
||||
return true |
return true |
||||
} |
} |
||||
|
@ -0,0 +1 @@ |
|||||
|
<p>home works!</p> |
@ -0,0 +1,27 @@ |
|||||
|
import { Component } from '@angular/core' |
||||
|
import { Router } from '@angular/router' |
||||
|
import { PermissionService } from 'app/shared/permission/permission.service' |
||||
|
import { NzMessageService } from 'ng-zorro-antd/message' |
||||
|
|
||||
|
@Component({ |
||||
|
selector: 'app-home', |
||||
|
standalone: true, |
||||
|
imports: [], |
||||
|
templateUrl: './home.component.html', |
||||
|
styleUrl: './home.component.less', |
||||
|
}) |
||||
|
export class HomeComponent { |
||||
|
constructor( |
||||
|
private permission: PermissionService, |
||||
|
private router: Router, |
||||
|
private msg: NzMessageService, |
||||
|
) {} |
||||
|
|
||||
|
ngOnInit(): void { |
||||
|
if (this.permission.hasPermission('dashboard:view') || this.permission.isRoot) { |
||||
|
this.router.navigate(['/dashboard']) |
||||
|
return |
||||
|
} |
||||
|
this.router.navigate(['/profile/basic']) |
||||
|
} |
||||
|
} |
Loading…
Reference in new issue