diff --git a/web-admin-app/angular.json b/web-admin-app/angular.json index 47a75a9..8f829e0 100644 --- a/web-admin-app/angular.json +++ b/web-admin-app/angular.json @@ -1,120 +1,106 @@ { - "$schema": "./node_modules/@angular/cli/lib/config/schema.json", - "version": 1, - "newProjectRoot": "projects", - "projects": { - "license-web-app": { - "projectType": "application", - "schematics": { - "@schematics/angular:component": { - "style": "less" - } - }, - "root": "", - "sourceRoot": "src", - "prefix": "app", - "architect": { - "build": { - "builder": "@angular-devkit/build-angular:application", - "options": { - "outputPath": "dist/license-web-app", - "index": "src/index.html", - "browser": "src/main.ts", - "polyfills": [ - "zone.js" - ], - "tsConfig": "tsconfig.app.json", - "inlineStyleLanguage": "less", - "assets": [ - "src/favicon.ico", - "src/assets", - { - "glob": "**/*", - "input": "./node_modules/@ant-design/icons-angular/src/inline-svg/", - "output": "/assets/" - }, - { - "glob": "**/*", - "input": "node_modules/tinymce", - "output": "/assets/tinymce/" - } - ], - "styles": [ - "src/styles.less" - ], - "scripts": [ - "node_modules/tinymce/tinymce.min.js" - ] - }, - "configurations": { - "production": { - "budgets": [ - { - "type": "initial", - "maximumWarning": "10mb", - "maximumError": "10mb" - }, - { - "type": "anyComponentStyle", - "maximumWarning": "10mb", - "maximumError": "10mb" - } - ], - "outputHashing": "all" - }, - "development": { - "optimization": false, - "extractLicenses": false, - "sourceMap": true - } - }, - "defaultConfiguration": "production" - }, - "serve": { - "builder": "@angular-devkit/build-angular:dev-server", - "configurations": { - "production": { - "buildTarget": "license-web-app:build:production" - }, - "development": { - "buildTarget": "license-web-app:build:development" - } - }, - "defaultConfiguration": "development", - "options": { - "port": 6001, - "host": "0.0.0.0" - } - }, - "extract-i18n": { - "builder": "@angular-devkit/build-angular:extract-i18n", - "options": { - "buildTarget": "license-web-app:build" - } - }, - "test": { - "builder": "@angular-devkit/build-angular:karma", - "options": { - "polyfills": [ - "zone.js", - "zone.js/testing" - ], - "tsConfig": "tsconfig.spec.json", - "inlineStyleLanguage": "less", - "assets": [ - "src/favicon.ico", - "src/assets" - ], - "styles": [ - "src/styles.less" - ], - "scripts": [] - } - } - } - } - }, - "cli": { - "analytics": false - } -} \ No newline at end of file + "$schema": "./node_modules/@angular/cli/lib/config/schema.json", + "version": 1, + "newProjectRoot": "projects", + "projects": { + "license-web-app": { + "projectType": "application", + "schematics": { + "@schematics/angular:component": { + "style": "less" + } + }, + "root": "", + "sourceRoot": "src", + "prefix": "app", + "architect": { + "build": { + "builder": "@angular-devkit/build-angular:application", + "options": { + "outputPath": "dist/license-web-app", + "index": "src/index.html", + "browser": "src/main.ts", + "polyfills": ["zone.js"], + "tsConfig": "tsconfig.app.json", + "inlineStyleLanguage": "less", + "assets": [ + "src/favicon.ico", + "src/assets", + { + "glob": "**/*", + "input": "./node_modules/@ant-design/icons-angular/src/inline-svg/", + "output": "/assets/" + }, + { + "glob": "**/*", + "input": "node_modules/tinymce", + "output": "/assets/tinymce/" + } + ], + "styles": ["src/styles.less"], + "scripts": ["node_modules/tinymce/tinymce.min.js"] + }, + "configurations": { + "production": { + "budgets": [ + { + "type": "initial", + "maximumWarning": "10mb", + "maximumError": "10mb" + }, + { + "type": "anyComponentStyle", + "maximumWarning": "10mb", + "maximumError": "10mb" + } + ], + "outputHashing": "all" + }, + "development": { + "optimization": false, + "extractLicenses": false, + "sourceMap": true + } + }, + "defaultConfiguration": "production" + }, + "serve": { + "builder": "@angular-devkit/build-angular:dev-server", + "configurations": { + "production": { + "buildTarget": "license-web-app:build:production" + }, + "development": { + "buildTarget": "license-web-app:build:development" + } + }, + "defaultConfiguration": "development", + "options": { + "port": 7001, + "host": "0.0.0.0" + } + }, + "extract-i18n": { + "builder": "@angular-devkit/build-angular:extract-i18n", + "options": { + "buildTarget": "license-web-app:build" + } + }, + "test": { + "builder": "@angular-devkit/build-angular:karma", + "options": { + "polyfills": ["zone.js", "zone.js/testing"], + "tsConfig": "tsconfig.spec.json", + "inlineStyleLanguage": "less", + "assets": ["src/favicon.ico", "src/assets"], + "styles": ["src/styles.less"], + "scripts": [] + } + } + } + } + }, + "cli": { + "analytics": false + } +} diff --git a/web-admin-app/src/app/app.routes.ts b/web-admin-app/src/app/app.routes.ts index d68e08a..492094d 100644 --- a/web-admin-app/src/app/app.routes.ts +++ b/web-admin-app/src/app/app.routes.ts @@ -59,6 +59,7 @@ import { FlowMyTodoComponent } from './pages/flow/flow-my-todo/flow-my-todo.comp import { FlowLayoutComponent } from './pages/flow/flow-layout/flow-layout.component' import { FlowMyFinishedComponent } from './pages/flow/flow-my-finished/flow-my-finished.component' import { FixedAssetStorageComponent } from './pages/fixed-asset/ledger/fixed-asset-storage/fixed-asset-storage.component' +import { HomeComponent } from './pages/home/home.component' export const routes: Routes = [ { @@ -77,7 +78,11 @@ export const routes: Routes = [ { path: '', pathMatch: 'full', - redirectTo: 'dashboard', + redirectTo: 'home', + }, + { + path: 'home', + component: HomeComponent, }, { path: 'dashboard', diff --git a/web-admin-app/src/app/components/index.ts b/web-admin-app/src/app/components/index.ts index 970170d..2591bf1 100644 --- a/web-admin-app/src/app/components/index.ts +++ b/web-admin-app/src/app/components/index.ts @@ -1,3 +1,5 @@ +export * from './permissions-select/permissions-select.component' + export * from './component-org-tree/component-org-tree.component' export * from './component-basic-category-tree/component-basic-category-tree.component' export * from './select-user-by-org/select-user-by-org.component' diff --git a/web-admin-app/src/app/components/permissions-select/permissions-select.component.html b/web-admin-app/src/app/components/permissions-select/permissions-select.component.html new file mode 100644 index 0000000..95bdd5f --- /dev/null +++ b/web-admin-app/src/app/components/permissions-select/permissions-select.component.html @@ -0,0 +1,30 @@ +
+ +
+ +
+
+
+ @for (item of menus; track $index) { +
+ +
+ } +
+
+
+
diff --git a/web-admin-app/src/app/components/permissions-select/permissions-select.component.less b/web-admin-app/src/app/components/permissions-select/permissions-select.component.less new file mode 100644 index 0000000..5a93cbd --- /dev/null +++ b/web-admin-app/src/app/components/permissions-select/permissions-select.component.less @@ -0,0 +1,4 @@ +.checkAll { + padding: 12px 0; + border-bottom: 1px solid #e8e8e8; +} \ No newline at end of file diff --git a/web-admin-app/src/app/components/permissions-select/permissions-select.component.ts b/web-admin-app/src/app/components/permissions-select/permissions-select.component.ts new file mode 100644 index 0000000..6c11318 --- /dev/null +++ b/web-admin-app/src/app/components/permissions-select/permissions-select.component.ts @@ -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() + + 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 + } +} diff --git a/web-admin-app/src/app/guards/auth.guard.ts b/web-admin-app/src/app/guards/auth.guard.ts index 11ea492..78bdefd 100644 --- a/web-admin-app/src/app/guards/auth.guard.ts +++ b/web-admin-app/src/app/guards/auth.guard.ts @@ -1,19 +1,18 @@ import { inject } from '@angular/core' import { CanActivateFn, Router, UrlTree } from '@angular/router' -import { ApiService, LocalHttpInterceptorService } from 'app/services' -import { map } from 'rxjs' +import { ApiService } from 'app/services' +import { PermissionService } from 'app/shared/permission/permission.service' 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 permission = inject(PermissionService) const api = inject(ApiService) + const authInfo = api.authInfo if (!api.authInfo) { 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 } diff --git a/web-admin-app/src/app/pages/home/home.component.html b/web-admin-app/src/app/pages/home/home.component.html new file mode 100644 index 0000000..5f2c53f --- /dev/null +++ b/web-admin-app/src/app/pages/home/home.component.html @@ -0,0 +1 @@ +

home works!

diff --git a/web-admin-app/src/app/pages/home/home.component.less b/web-admin-app/src/app/pages/home/home.component.less new file mode 100644 index 0000000..e69de29 diff --git a/web-admin-app/src/app/pages/home/home.component.ts b/web-admin-app/src/app/pages/home/home.component.ts new file mode 100644 index 0000000..85e02f7 --- /dev/null +++ b/web-admin-app/src/app/pages/home/home.component.ts @@ -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']) + } +} diff --git a/web-admin-app/src/app/pages/org-setting/org-setting.component.html b/web-admin-app/src/app/pages/org-setting/org-setting.component.html index 1cd0bbe..b136e80 100644 --- a/web-admin-app/src/app/pages/org-setting/org-setting.component.html +++ b/web-admin-app/src/app/pages/org-setting/org-setting.component.html @@ -146,6 +146,14 @@ + + 角色 + + + + + + 状态 diff --git a/web-admin-app/src/app/pages/org-setting/org-setting.component.ts b/web-admin-app/src/app/pages/org-setting/org-setting.component.ts index 5fbbd66..9e4addc 100644 --- a/web-admin-app/src/app/pages/org-setting/org-setting.component.ts +++ b/web-admin-app/src/app/pages/org-setting/org-setting.component.ts @@ -10,8 +10,10 @@ import { NzSafeAny } from 'ng-zorro-antd/core/types' import { NzModalService } from 'ng-zorro-antd/modal' import { NzMessageService } from 'ng-zorro-antd/message' import { NzDrawerRef, NzDrawerService } from 'ng-zorro-antd/drawer' -import { lastValueFrom } from 'rxjs' +import { Subject, lastValueFrom, switchMap } from 'rxjs' import { FormValidators } from 'app/utils' +import { MAX_PAGE_SIZE } from 'app/constants' +import { Observable } from 'tinymce' @Component({ selector: 'app-org-setting', @@ -27,9 +29,19 @@ export class OrgSettingComponent implements OnInit { private drawer: NzDrawerService, private api: ApiService, private fb: FormBuilder, - ) {} + ) { + this.requestSubject + .pipe(switchMap((p: NzSafeAny, q: NzSafeAny) => this.fetchData(p, q))) + .subscribe((response) => { + console.log(response) + }) + } + + private requestSubject = new Subject() - table = new TableOption(this.fetchData.bind(this)) + table = new TableOption(this.fetchData.bind(this), { + manual: true, + }) queryForm!: FormGroup @@ -43,6 +55,8 @@ export class OrgSettingComponent implements OnInit { uploadLoading = false + roles: NzSafeAny[] = [] + @ViewChild('drawerFooterTpl') drawerFooterTpl!: TemplateRef @ViewChild('formContentTpl') formContentTpl!: TemplateRef @@ -94,21 +108,23 @@ export class OrgSettingComponent implements OnInit { ]) this.initQueryForm() this.initCreateForm() + this.api.getRolePage({ pageSize: MAX_PAGE_SIZE, pageNum: 1 }).subscribe((res) => { + this.roles = res.body.rows + }) } fetchData(p: {}, q: AnyObject) { - return this.api.getUserPage({ ...p, ...q, organizationId: this.organization?.organizationId }) + return this.api.getUserPage({ ...p, ...q, organizationId: this.organization?.organizationId }).pipe() } onOrgSelectedChange(org: NzSafeAny) { - console.log('org', org) this.organization = org this.table.ref.search() } onCreate(data?: NzSafeAny) { if (data) { - this.createForm.patchValue(data) + this.createForm.patchValue({ ...data, roleId: data._umsRole.roleId }) } this.drawerRef = this.drawer.create({ nzTitle: data ? '编辑员工' : '新增员工', diff --git a/web-admin-app/src/app/pages/system/system-role/system-role.component.html b/web-admin-app/src/app/pages/system/system-role/system-role.component.html index b73b302..c2781e1 100644 --- a/web-admin-app/src/app/pages/system/system-role/system-role.component.html +++ b/web-admin-app/src/app/pages/system/system-role/system-role.component.html @@ -60,7 +60,9 @@ 权限菜单 - 《权限菜单》 + + + - - - +
diff --git a/web-admin-app/src/app/shared/components/server-paginated-table/server-paginated-table.component.ts b/web-admin-app/src/app/shared/components/server-paginated-table/server-paginated-table.component.ts index 1640456..81dac91 100644 --- a/web-admin-app/src/app/shared/components/server-paginated-table/server-paginated-table.component.ts +++ b/web-admin-app/src/app/shared/components/server-paginated-table/server-paginated-table.component.ts @@ -17,7 +17,7 @@ import { TableColumnsInterface, persistKey, } from './server-paginated-table.service' -import { finalize, map } from 'rxjs' +import { Subject, finalize, map, switchMap } from 'rxjs' import { FormGroup } from '@angular/forms' import { TableFormDirective } from './table-form.directive' import { Router } from '@angular/router' @@ -153,7 +153,35 @@ export class ServerPaginatedTableComponent implements OnInit, OnChanges { private pageTable: ServerPaginatedTableService, private router: Router, private drawer: NzDrawerService, - ) {} + ) { + this.trigger$ + .pipe( + switchMap(() => { + const { pageIndex, pageSize } = this.pagination + const page = this.pageTable.globalConfig.formatPaginationData({ pageIndex, pageSize }) + const query = this.formGroup?.value ?? {} + + this.pagination.loading = true + + return this.options.fetchData(page, query).pipe( + map(this.pageTable.globalConfig.formatServiceData), + finalize(() => { + this.saveCacheState() + this.pagination.loading = false + }), + ) + }), + ) + .subscribe((res) => { + this.pagination = { + ...this.pagination, + ...res, + } + // 不允许跨页选择 + this.selected.clear() + this.onSelectChange() + }) + } @Input() options!: TableOption @@ -276,30 +304,10 @@ export class ServerPaginatedTableComponent implements OnInit, OnChanges { return persistKey + this.router.url.replaceAll('/', '_') } - private run() { - const { pageIndex, pageSize } = this.pagination - const page = this.pageTable.globalConfig.formatPaginationData({ pageIndex, pageSize }) - const query = this.formGroup?.value ?? {} + trigger$ = new Subject() - this.pagination.loading = true - this.options - .fetchData(page, query) - .pipe( - map(this.pageTable.globalConfig.formatServiceData), - finalize(() => { - this.saveCacheState() - this.pagination.loading = false - }), - ) - .subscribe((res) => { - this.pagination = { - ...this.pagination, - ...res, - } - // 不允许跨页选择 - this.selected.clear() - this.onSelectChange() - }) + private run() { + this.trigger$.next(null) } reload() { diff --git a/web-admin-app/src/app/shared/permission/permission.directive.ts b/web-admin-app/src/app/shared/permission/permission.directive.ts index b5211af..4ecddbf 100644 --- a/web-admin-app/src/app/shared/permission/permission.directive.ts +++ b/web-admin-app/src/app/shared/permission/permission.directive.ts @@ -19,7 +19,9 @@ export class PermissionDirective { } private checkPermission(): void { - const hasPermission = this.permissionService.hasPermission(this.requiredPermission) + const hasPermission = + this.permissionService.isRoot || this.permissionService.hasPermission(this.requiredPermission) + console.log('hasPermission', this.permissionService) if (hasPermission) { this.viewContainerRef.createEmbeddedView(this.templateRef) } else { diff --git a/web-admin-app/src/app/shared/permission/permission.service.ts b/web-admin-app/src/app/shared/permission/permission.service.ts index 36beeff..3159cab 100644 --- a/web-admin-app/src/app/shared/permission/permission.service.ts +++ b/web-admin-app/src/app/shared/permission/permission.service.ts @@ -4,7 +4,7 @@ import { Injectable } from '@angular/core' export class PermissionService { constructor() {} - private permissons: string[] = [] + permissons: string[] = [] isRoot = false