From 7bc5588b28d314ed64d7f834aeec8a694857d2a2 Mon Sep 17 00:00:00 2001 From: AlexBob Date: Thu, 17 Oct 2024 14:06:53 +0800 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20feat(`ng-web/src/app/pages/home/gro?= =?UTF-8?q?ups`):=20=E6=96=B0=E5=A2=9E=E8=A7=92=E8=89=B2=E7=AE=A1=E7=90=86?= =?UTF-8?q?=E5=8A=9F=E8=83=BD=EF=BC=8C=E5=8C=85=E6=8B=AC=E6=9C=8D=E5=8A=A1?= =?UTF-8?q?=E3=80=81=E7=B1=BB=E5=9E=8B=E5=AE=9A=E4=B9=89=E3=80=81=E7=BB=84?= =?UTF-8?q?=E4=BB=B6=E5=92=8C=E6=A0=B7=E5=BC=8F=E6=96=87=E4=BB=B6=E3=80=82?= =?UTF-8?q?=20=E2=9C=A8=20feat(`ng-web/src/app/pages/home/users`):=20?= =?UTF-8?q?=E6=96=B0=E5=A2=9E=E7=94=A8=E6=88=B7=E7=AE=A1=E7=90=86=E5=8A=9F?= =?UTF-8?q?=E8=83=BD=EF=BC=8C=E5=8C=85=E6=8B=AC=E7=BB=84=E4=BB=B6=E3=80=81?= =?UTF-8?q?=E6=A0=B7=E5=BC=8F=E6=96=87=E4=BB=B6=E5=92=8C=E8=B7=AF=E7=94=B1?= =?UTF-8?q?=E9=85=8D=E7=BD=AE=E3=80=82=20=E2=9C=A8=20feat(`ng-web/src/app/?= =?UTF-8?q?pages/home/menus/menu.types.ts`):=20=E4=BC=98=E5=8C=96=E8=8F=9C?= =?UTF-8?q?=E5=8D=95=E7=B1=BB=E5=9E=8B=E5=AE=9A=E4=B9=89=EF=BC=8C=E7=A7=BB?= =?UTF-8?q?=E9=99=A4=E9=87=8D=E5=A4=8D=E7=9A=84=E7=94=A8=E6=88=B7=E5=AE=A1?= =?UTF-8?q?=E8=AE=A1=E8=80=85=E6=8E=A5=E5=8F=A3=E3=80=82=20=E2=9C=A8=20fea?= =?UTF-8?q?t(`ng-web/src/app/pages/login/login.component.ts`):=20=E4=BC=98?= =?UTF-8?q?=E5=8C=96=E7=99=BB=E5=BD=95=E7=BB=84=E4=BB=B6=EF=BC=8C=E4=BF=AE?= =?UTF-8?q?=E5=A4=8D=E5=86=85=E5=AD=98=E6=B3=84=E6=BC=8F=E9=97=AE=E9=A2=98?= =?UTF-8?q?=E3=80=82=20=E2=9C=A8=20feat(`ng-web/src/app/core/auth.service.?= =?UTF-8?q?ts`):=20=E4=BC=98=E5=8C=96=E8=AE=A4=E8=AF=81=E6=9C=8D=E5=8A=A1?= =?UTF-8?q?=EF=BC=8C=E5=A2=9E=E5=8A=A0=E8=B7=AF=E7=94=B1=E5=AE=88=E5=8D=AB?= =?UTF-8?q?=E5=8A=9F=E8=83=BD=E3=80=82=20=E2=9C=A8=20feat(`ng-web/src/app/?= =?UTF-8?q?pages/home/home.routes.ts`):=20=E6=9B=B4=E6=96=B0=E9=A6=96?= =?UTF-8?q?=E9=A1=B5=E8=B7=AF=E7=94=B1=E9=85=8D=E7=BD=AE=EF=BC=8C=E6=B7=BB?= =?UTF-8?q?=E5=8A=A0=E8=A7=92=E8=89=B2=E7=AE=A1=E7=90=86=E5=92=8C=E7=94=A8?= =?UTF-8?q?=E6=88=B7=E7=AE=A1=E7=90=86=E8=B7=AF=E5=BE=84=E3=80=82=20?= =?UTF-8?q?=E2=9C=A8=20feat(`ng-web/src/types.ts`):=20=E6=96=B0=E5=A2=9E?= =?UTF-8?q?=E7=94=A8=E6=88=B7=E5=AE=A1=E8=AE=A1=E8=80=85=E6=8E=A5=E5=8F=A3?= =?UTF-8?q?=E5=AE=9A=E4=B9=89=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ng-web/src/app/core/auth.service.ts | 3 +- .../pages/home/groups/groups.component.html | 42 +++++++++++++++++++ .../pages/home/groups/groups.component.scss | 3 ++ .../app/pages/home/groups/groups.component.ts | 41 ++++++++++++++++++ .../app/pages/home/groups/groups.service.ts | 17 ++++++++ .../src/app/pages/home/groups/groups.types.ts | 13 ++++++ ng-web/src/app/pages/home/home.routes.ts | 16 +++++++ ng-web/src/app/pages/home/menus/menu.types.ts | 8 +--- .../app/pages/home/users/users.component.html | 42 +++++++++++++++++++ .../app/pages/home/users/users.component.scss | 3 ++ .../app/pages/home/users/users.component.ts | 41 ++++++++++++++++++ ng-web/src/app/pages/login/login.component.ts | 17 ++++---- ng-web/src/types.ts | 5 +++ 13 files changed, 236 insertions(+), 15 deletions(-) create mode 100644 ng-web/src/app/pages/home/groups/groups.component.html create mode 100644 ng-web/src/app/pages/home/groups/groups.component.scss create mode 100644 ng-web/src/app/pages/home/groups/groups.component.ts create mode 100644 ng-web/src/app/pages/home/groups/groups.service.ts create mode 100644 ng-web/src/app/pages/home/groups/groups.types.ts create mode 100644 ng-web/src/app/pages/home/users/users.component.html create mode 100644 ng-web/src/app/pages/home/users/users.component.scss create mode 100644 ng-web/src/app/pages/home/users/users.component.ts create mode 100644 ng-web/src/types.ts diff --git a/ng-web/src/app/core/auth.service.ts b/ng-web/src/app/core/auth.service.ts index ad772287..02654198 100644 --- a/ng-web/src/app/core/auth.service.ts +++ b/ng-web/src/app/core/auth.service.ts @@ -1,6 +1,6 @@ import { HttpErrorResponse } from '@angular/common/http'; import { inject, Injectable, signal } from '@angular/core'; -import { CanActivateChildFn, CanActivateFn, CanMatchFn, Router } from '@angular/router'; +import { ActivatedRoute, CanActivateChildFn, CanActivateFn, CanMatchFn, Router } from '@angular/router'; import dayjs from 'dayjs'; import { SessionStorageService } from './storage/session-storage'; @@ -16,6 +16,7 @@ export interface Authentication { export const authGuard: CanMatchFn | CanActivateFn | CanActivateChildFn = () => { const auth = inject(AuthService); const router = inject(Router); + const state = inject(ActivatedRoute); if (auth.isLogged()) { return true; } diff --git a/ng-web/src/app/pages/home/groups/groups.component.html b/ng-web/src/app/pages/home/groups/groups.component.html new file mode 100644 index 00000000..749ed3ca --- /dev/null +++ b/ng-web/src/app/pages/home/groups/groups.component.html @@ -0,0 +1,42 @@ +
+
+ +
+
+ +
+
+ + + + 编码 + 名称 + 操作 + + + + @for (data of expandTable.data; track $index) { + + + + {{ data.code }} + + {{ data.name }} + + 编辑 | 删除 + + + + } + + diff --git a/ng-web/src/app/pages/home/groups/groups.component.scss b/ng-web/src/app/pages/home/groups/groups.component.scss new file mode 100644 index 00000000..5d4e87f3 --- /dev/null +++ b/ng-web/src/app/pages/home/groups/groups.component.scss @@ -0,0 +1,3 @@ +:host { + display: block; +} diff --git a/ng-web/src/app/pages/home/groups/groups.component.ts b/ng-web/src/app/pages/home/groups/groups.component.ts new file mode 100644 index 00000000..5c4c0896 --- /dev/null +++ b/ng-web/src/app/pages/home/groups/groups.component.ts @@ -0,0 +1,41 @@ +import { CommonModule } from '@angular/common'; +import { ChangeDetectionStrategy, Component, OnDestroy, type OnInit, signal, WritableSignal } from '@angular/core'; +import { Group } from './groups.types'; +import { GroupsService } from './groups.service'; +import { Subject, takeUntil } from 'rxjs'; +import { NzTableModule } from 'ng-zorro-antd/table'; + +@Component({ + selector: 'app-groups', + standalone: true, + imports: [CommonModule, NzTableModule], + templateUrl: './groups.component.html', + styleUrl: './groups.component.scss', + changeDetection: ChangeDetectionStrategy.OnPush, +}) +export class GroupsComponent implements OnInit, OnDestroy { + groupsList: WritableSignal = signal([]); + private _subject: Subject = new Subject(); + + constructor(private groupService: GroupsService) { + } + + ngOnInit(): void { + this.refresh(); + } + + refresh() { + const groupRequest: Group = { + tenantCode: '0', + }; + this.groupService + .getGroups(groupRequest) + .pipe(takeUntil(this._subject)) + .subscribe(result => this.groupsList.set(result)); + } + + ngOnDestroy(): void { + this._subject.next(); + this._subject.complete(); + } +} diff --git a/ng-web/src/app/pages/home/groups/groups.service.ts b/ng-web/src/app/pages/home/groups/groups.service.ts new file mode 100644 index 00000000..58738a81 --- /dev/null +++ b/ng-web/src/app/pages/home/groups/groups.service.ts @@ -0,0 +1,17 @@ +import { HttpClient, HttpParams } from '@angular/common/http'; +import { Injectable } from '@angular/core'; +import { Group } from './groups.types'; +import { Observable, retry } from 'rxjs'; + +@Injectable({ + providedIn: 'root', +}) +export class GroupsService { + constructor(private http: HttpClient) { + } + + getGroups(request: Group): Observable { + const params = new HttpParams({ fromObject: request as never }); + return this.http.get('/menus/search', { params: params }).pipe(retry(3)); + } +} diff --git a/ng-web/src/app/pages/home/groups/groups.types.ts b/ng-web/src/app/pages/home/groups/groups.types.ts new file mode 100644 index 00000000..0ae164bb --- /dev/null +++ b/ng-web/src/app/pages/home/groups/groups.types.ts @@ -0,0 +1,13 @@ +import { UserAuditor } from '../../../../types'; + +export interface Group { + id?: number; + code?: string; + tenantCode: string; + name?: string; + extend?: any; + creator?: UserAuditor; + updater?: UserAuditor; + createdTime?: Date; + updatedTime?: Date; +} diff --git a/ng-web/src/app/pages/home/home.routes.ts b/ng-web/src/app/pages/home/home.routes.ts index 448399b0..167157c7 100644 --- a/ng-web/src/app/pages/home/home.routes.ts +++ b/ng-web/src/app/pages/home/home.routes.ts @@ -2,6 +2,8 @@ import { Routes } from '@angular/router'; import { HomeComponent } from './home.component'; import { MenusComponent } from './menus/menus.component'; import { authGuard } from '../../core/auth.service'; +import { UsersComponent } from './users/users.component'; +import { GroupsComponent } from './groups/groups.component'; export const HOME_ROUTES: Routes = [ { @@ -12,6 +14,20 @@ export const HOME_ROUTES: Routes = [ title: '管理后台', }, children: [ + { + path: 'roles', + data: { + title: '角色管理', + }, + component: GroupsComponent, + }, + { + path: 'users', + data: { + title: '用户管理', + }, + component: UsersComponent, + }, { path: 'menus', data: { diff --git a/ng-web/src/app/pages/home/menus/menu.types.ts b/ng-web/src/app/pages/home/menus/menu.types.ts index d3472bb0..2a172df1 100644 --- a/ng-web/src/app/pages/home/menus/menu.types.ts +++ b/ng-web/src/app/pages/home/menus/menu.types.ts @@ -1,3 +1,5 @@ +import { UserAuditor } from '../../../../types'; + export interface Menu { id?: number; code?: string; @@ -21,12 +23,6 @@ export interface Menu { parent?: Menu; } -export interface UserAuditor { - code: string; - username: string; - name?: string; -} - export enum MenuType { FOLDER = 'FOLDER', MENU = 'MENU', diff --git a/ng-web/src/app/pages/home/users/users.component.html b/ng-web/src/app/pages/home/users/users.component.html new file mode 100644 index 00000000..e31270eb --- /dev/null +++ b/ng-web/src/app/pages/home/users/users.component.html @@ -0,0 +1,42 @@ +
+
+ +
+
+ +
+
+ + + + 编码 + 名称 + 操作 + + + + @for (data of expandTable.data; track $index) { + + + + {{ data.code }} + + {{ data.name }} + + 编辑 | 删除 + + + + } + + diff --git a/ng-web/src/app/pages/home/users/users.component.scss b/ng-web/src/app/pages/home/users/users.component.scss new file mode 100644 index 00000000..5d4e87f3 --- /dev/null +++ b/ng-web/src/app/pages/home/users/users.component.scss @@ -0,0 +1,3 @@ +:host { + display: block; +} diff --git a/ng-web/src/app/pages/home/users/users.component.ts b/ng-web/src/app/pages/home/users/users.component.ts new file mode 100644 index 00000000..da658bcf --- /dev/null +++ b/ng-web/src/app/pages/home/users/users.component.ts @@ -0,0 +1,41 @@ +import { CommonModule } from '@angular/common'; +import { ChangeDetectionStrategy, Component, OnDestroy, type OnInit, signal, WritableSignal } from '@angular/core'; +import { NzTableModule } from 'ng-zorro-antd/table'; +import { Subject, takeUntil } from 'rxjs'; +import { GroupsService } from '../groups/groups.service'; +import { Group } from '../groups/groups.types'; + +@Component({ + selector: 'app-users', + standalone: true, + imports: [CommonModule, NzTableModule], + templateUrl: './users.component.html', + styleUrl: './users.component.scss', + changeDetection: ChangeDetectionStrategy.OnPush, +}) +export class UsersComponent implements OnInit, OnDestroy { + groupsList: WritableSignal = signal([]); + private _subject: Subject = new Subject(); + + constructor(private groupService: GroupsService) { + } + + ngOnInit(): void { + this.refresh(); + } + + refresh() { + const groupRequest: Group = { + tenantCode: '0', + }; + this.groupService + .getGroups(groupRequest) + .pipe(takeUntil(this._subject)) + .subscribe(result => this.groupsList.set(result)); + } + + ngOnDestroy(): void { + this._subject.next(); + this._subject.complete(); + } +} diff --git a/ng-web/src/app/pages/login/login.component.ts b/ng-web/src/app/pages/login/login.component.ts index 9653c10a..6f38570b 100644 --- a/ng-web/src/app/pages/login/login.component.ts +++ b/ng-web/src/app/pages/login/login.component.ts @@ -14,8 +14,10 @@ import { NzNotificationModule, NzNotificationService } from 'ng-zorro-antd/notif styleUrls: ['./login.component.scss'], }) export class LoginComponent implements OnInit, OnDestroy { + private _subject$: Subject = new Subject(); private _loginSer = inject(LoginService); private _message = inject(NzNotificationService); + loginForm = new FormGroup({ username: new FormControl('', [ Validators.required, @@ -29,7 +31,6 @@ export class LoginComponent implements OnInit, OnDestroy { ]), remember: new FormControl(false), }); - private componentDestroyed$: Subject = new Subject(); constructor(private router: Router, private route: ActivatedRoute) { } @@ -50,20 +51,20 @@ export class LoginComponent implements OnInit, OnDestroy { } const credentials = this._loginSer.getRememberMe(); if (credentials && Object.keys(credentials).length !== 0) { - this._message.success('自动登录成功', '记住我系统自动登录成功!'); this.login(credentials); + this._message.success('自动登录成功', '记住我系统自动登录成功!'); } } - ngOnDestroy(): void { - this.componentDestroyed$.next(); - this.componentDestroyed$.complete(); - } - login(credentials: Credentials) { this._loginSer .login(credentials) - .pipe(takeUntil(this.componentDestroyed$), debounceTime(100), distinctUntilChanged()) + .pipe(takeUntil(this._subject$), debounceTime(100), distinctUntilChanged()) .subscribe(res => this.router.navigate(['/home'], { relativeTo: this.route }).then()); } + + ngOnDestroy(): void { + this._subject$.next(); + this._subject$.complete(); + } } diff --git a/ng-web/src/types.ts b/ng-web/src/types.ts new file mode 100644 index 00000000..86eaee48 --- /dev/null +++ b/ng-web/src/types.ts @@ -0,0 +1,5 @@ +export interface UserAuditor { + code: string; + username: string | null; + name: string | null; +}