Skip to content

Commit

Permalink
✨ feat(ng-web/src/app/pages/home/groups): 新增角色管理功能,包括服务、类型定义、组件和样式文件。
Browse files Browse the repository at this point in the history
✨ feat(`ng-web/src/app/pages/home/users`): 新增用户管理功能,包括组件、样式文件和路由配置。
✨ feat(`ng-web/src/app/pages/home/menus/menu.types.ts`): 优化菜单类型定义,移除重复的用户审计者接口。
✨ feat(`ng-web/src/app/pages/login/login.component.ts`): 优化登录组件,修复内存泄漏问题。
✨ feat(`ng-web/src/app/core/auth.service.ts`): 优化认证服务,增加路由守卫功能。
✨ feat(`ng-web/src/app/pages/home/home.routes.ts`): 更新首页路由配置,添加角色管理和用户管理路径。
✨ feat(`ng-web/src/types.ts`): 新增用户审计者接口定义。
  • Loading branch information
vnobo committed Oct 17, 2024
1 parent 40a4db0 commit 7bc5588
Show file tree
Hide file tree
Showing 13 changed files with 236 additions and 15 deletions.
3 changes: 2 additions & 1 deletion ng-web/src/app/core/auth.service.ts
Original file line number Diff line number Diff line change
@@ -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';

Expand All @@ -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;
}
Expand Down
42 changes: 42 additions & 0 deletions ng-web/src/app/pages/home/groups/groups.component.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<div class="row justify-content-between mb-2">
<div class="col-1">
<button class="btn btn-primary btn-sm" type="button">
<i class="bi bi-plus me-1"></i>新增
</button>
</div>
<div class="col-auto float-end">
<button (click)="refresh()" class="btn btn-success btn-sm mx-2" type="button">刷新</button>
</div>
</div>
<nz-table
#expandTable
[nzData]="groupsList()"
[nzPageIndex]="0"
[nzScroll]="{ x: '100%' }"
nzFrontPagination="false"
nzNoResult="无数据"
nzTableLayout="auto"
nzTitle="角色管理管理">
<thead>
<tr>
<th nzLeft>编码</th>
<th nzLeft>名称</th>
<th nzRight>操作</th>
</tr>
</thead>
<tbody>
@for (data of expandTable.data; track $index) {
<ng-container>
<tr>
<td [(nzExpand)]="data.extend" nzLeft>
{{ data.code }}
</td>
<td nzLeft>{{ data.name }}</td>
<td nzRight>
<a href="javascript:void(0)">编辑</a> | <a href="javascript:void(0)">删除</a>
</td>
</tr>
</ng-container>
}
</tbody>
</nz-table>
3 changes: 3 additions & 0 deletions ng-web/src/app/pages/home/groups/groups.component.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
:host {
display: block;
}
41 changes: 41 additions & 0 deletions ng-web/src/app/pages/home/groups/groups.component.ts
Original file line number Diff line number Diff line change
@@ -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<Group[]> = signal([]);
private _subject: Subject<void> = new Subject<void>();

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();
}
}
17 changes: 17 additions & 0 deletions ng-web/src/app/pages/home/groups/groups.service.ts
Original file line number Diff line number Diff line change
@@ -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<Group[]> {
const params = new HttpParams({ fromObject: request as never });
return this.http.get<Group[]>('/menus/search', { params: params }).pipe(retry(3));
}
}
13 changes: 13 additions & 0 deletions ng-web/src/app/pages/home/groups/groups.types.ts
Original file line number Diff line number Diff line change
@@ -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;
}
16 changes: 16 additions & 0 deletions ng-web/src/app/pages/home/home.routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 = [
{
Expand All @@ -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: {
Expand Down
8 changes: 2 additions & 6 deletions ng-web/src/app/pages/home/menus/menu.types.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { UserAuditor } from '../../../../types';

export interface Menu {
id?: number;
code?: string;
Expand All @@ -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',
Expand Down
42 changes: 42 additions & 0 deletions ng-web/src/app/pages/home/users/users.component.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<div class="row justify-content-between mb-2">
<div class="col-1">
<button class="btn btn-primary btn-sm" type="button">
<i class="bi bi-plus me-1"></i>新增
</button>
</div>
<div class="col-auto float-end">
<button (click)="refresh()" class="btn btn-success btn-sm mx-2" type="button">刷新</button>
</div>
</div>
<nz-table
#expandTable
[nzData]="groupsList()"
[nzPageIndex]="0"
[nzScroll]="{ x: '100%' }"
nzFrontPagination="false"
nzNoResult="无数据"
nzTableLayout="auto"
nzTitle="菜单管理">
<thead>
<tr>
<th nzLeft>编码</th>
<th nzLeft>名称</th>
<th nzRight>操作</th>
</tr>
</thead>
<tbody>
@for (data of expandTable.data; track $index) {
<ng-container>
<tr>
<td [(nzExpand)]="data.extend" nzLeft>
{{ data.code }}
</td>
<td nzLeft>{{ data.name }}</td>
<td nzRight>
<a href="javascript:void(0)">编辑</a> | <a href="javascript:void(0)">删除</a>
</td>
</tr>
</ng-container>
}
</tbody>
</nz-table>
3 changes: 3 additions & 0 deletions ng-web/src/app/pages/home/users/users.component.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
:host {
display: block;
}
41 changes: 41 additions & 0 deletions ng-web/src/app/pages/home/users/users.component.ts
Original file line number Diff line number Diff line change
@@ -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<Group[]> = signal([]);
private _subject: Subject<void> = new Subject<void>();

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();
}
}
17 changes: 9 additions & 8 deletions ng-web/src/app/pages/login/login.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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<void> = new Subject<void>();
private _loginSer = inject(LoginService);
private _message = inject(NzNotificationService);

loginForm = new FormGroup({
username: new FormControl('', [
Validators.required,
Expand All @@ -29,7 +31,6 @@ export class LoginComponent implements OnInit, OnDestroy {
]),
remember: new FormControl(false),
});
private componentDestroyed$: Subject<void> = new Subject<void>();

constructor(private router: Router, private route: ActivatedRoute) {
}
Expand All @@ -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();
}
}
5 changes: 5 additions & 0 deletions ng-web/src/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export interface UserAuditor {
code: string;
username: string | null;
name: string | null;
}

0 comments on commit 7bc5588

Please sign in to comment.