当前位置: 首页 > news >正文

视频会议系统直播聊天网站开发自己做网站软件

视频会议系统直播聊天网站开发,自己做网站软件,网站下雪代码,绵阳做网站1. 项目结构 src/ ├── app/ │ ├── core/ │ │ ├── guards/ │ │ │ ├── auth.guard.ts │ │ │ └── role.guard.ts │ │ ├── interceptors/ │ │ │ └── auth.interceptor.ts │ │ └── services/ │ │ …
1. 项目结构
src/
├── app/
│   ├── core/
│   │   ├── guards/
│   │   │   ├── auth.guard.ts
│   │   │   └── role.guard.ts
│   │   ├── interceptors/
│   │   │   └── auth.interceptor.ts
│   │   └── services/
│   │       ├── auth.service.ts
│   │       └── token.service.ts
│   ├── modules/
│   │   ├── auth/
│   │   │   ├── login/
│   │   │   │   ├── login.component.ts
│   │   │   │   ├── login.component.html
│   │   │   │   └── login.component.scss
│   │   │   ├── register/
│   │   │   │   ├── register.component.ts
│   │   │   │   ├── register.component.html
│   │   │   │   └── register.component.scss
│   │   │   └── auth-routing.module.ts
│   │   └── dashboard/
│   ├── shared/
│   │   ├── components/
│   │   │   └── error-message/
│   │   ├── models/
│   │   │   ├── user.model.ts
│   │   │   └── api-response.model.ts
│   │   └── validators/
│   │       └── password.validator.ts
│   ├── app-routing.module.ts
│   ├── app.component.ts
│   ├── app.component.html
│   └── app.module.ts
├── environments/
2. 核心服务

auth.service.ts (认证服务):

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { BehaviorSubject, Observable, tap } from 'rxjs';
import { Router } from '@angular/router';
import { environment } from '../../../environments/environment';
import { User } from '../shared/models/user.model';
import { TokenService } from './token.service';@Injectable({ providedIn: 'root' })
export class AuthService {private apiUrl = `${environment.apiUrl}/auth`;private currentUserSubject = new BehaviorSubject<User | null>(null);public currentUser$ = this.currentUserSubject.asObservable();constructor(private http: HttpClient,private tokenService: TokenService,private router: Router) {const user = localStorage.getItem('currentUser');if (user) {this.currentUserSubject.next(JSON.parse(user));}}register(userData: {email: string;password: string;name?: string;}): Observable<any> {return this.http.post(`${this.apiUrl}/register`, userData);}login(credentials: { email: string; password: string }): Observable<any> {return this.http.post<{ token: string }>(`${this.apiUrl}/login`, credentials).pipe(tap(response => {this.tokenService.setToken(response.token);this.fetchCurrentUser();}));}fetchCurrentUser(): void {this.http.get<User>(`${environment.apiUrl}/users/me`).subscribe({next: user => {this.currentUserSubject.next(user);localStorage.setItem('currentUser', JSON.stringify(user));},error: () => this.logout()});}logout(): void {this.tokenService.removeToken();this.currentUserSubject.next(null);localStorage.removeItem('currentUser');this.router.navigate(['/login']);}get currentUserValue(): User | null {return this.currentUserSubject.value;}isAuthenticated(): boolean {return !!this.tokenService.getToken();}
}

token.service.ts (令牌服务):

import { Injectable } from '@angular/core';@Injectable({ providedIn: 'root' })
export class TokenService {private readonly TOKEN_KEY = 'auth_token';setToken(token: string): void {localStorage.setItem(this.TOKEN_KEY, token);}getToken(): string | null {return localStorage.getItem(this.TOKEN_KEY);}removeToken(): void {localStorage.removeItem(this.TOKEN_KEY);}decodeToken(token: string): any {try {const base64Url = token.split('.')[1];const base64 = base64Url.replace(/-/g, '+').replace(/_/g, '/');return JSON.parse(atob(base64));} catch (e) {return null;}}
}
3. HTTP拦截器

auth.interceptor.ts:

import { Injectable } from '@angular/core';
import {HttpRequest,HttpHandler,HttpEvent,HttpInterceptor,HttpErrorResponse
} from '@angular/common/http';
import { Observable, catchError, throwError } from 'rxjs';
import { Router } from '@angular/router';
import { TokenService } from '../services/token.service';
import { AuthService } from '../services/auth.service';@Injectable()
export class AuthInterceptor implements HttpInterceptor {constructor(private tokenService: TokenService,private authService: AuthService,private router: Router) {}intercept(request: HttpRequest<unknown>, next: HttpHandler): Observable<HttpEvent<unknown>> {const token = this.tokenService.getToken();let authReq = request;if (token) {authReq = request.clone({setHeaders: {Authorization: `Bearer ${token}`}});}return next.handle(authReq).pipe(catchError((error: HttpErrorResponse) => {if (error.status === 401) {this.authService.logout();this.router.navigate(['/login'], { queryParams: { expired: true } });}return throwError(() => error);}));}
}
4. 路由守卫

auth.guard.ts:

import { Injectable } from '@angular/core';
import {CanActivate,ActivatedRouteSnapshot,RouterStateSnapshot,UrlTree,Router
} from '@angular/router';
import { Observable } from 'rxjs';
import { AuthService } from '../services/auth.service';@Injectable({ providedIn: 'root' })
export class AuthGuard implements CanActivate {constructor(private authService: AuthService, private router: Router) {}canActivate(route: ActivatedRouteSnapshot,state: RouterStateSnapshot): boolean | UrlTree | Observable<boolean | UrlTree> | Promise<boolean | UrlTree> {if (this.authService.isAuthenticated()) {return true;}// 保存目标URL以便登录后重定向this.router.navigate(['/login'], {queryParams: { returnUrl: state.url }});return false;}
}
5. 登录组件

login.component.ts:

import { Component, OnInit } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { ActivatedRoute, Router } from '@angular/router';
import { AuthService } from '../../core/services/auth.service';@Component({selector: 'app-login',templateUrl: './login.component.html',styleUrls: ['./login.component.scss']
})
export class LoginComponent implements OnInit {loginForm: FormGroup;isLoading = false;errorMessage: string | null = null;returnUrl: string | null = null;showPassword = false;constructor(private fb: FormBuilder,private authService: AuthService,private router: Router,private route: ActivatedRoute) {this.loginForm = this.fb.group({email: ['', [Validators.required, Validators.email]],password: ['', Validators.required],rememberMe: [false]});}ngOnInit(): void {this.returnUrl = this.route.snapshot.queryParams['returnUrl'] || '/dashboard';// 检查是否会话过期if (this.route.snapshot.queryParams['expired']) {this.errorMessage = '您的会话已过期,请重新登录';}}onSubmit(): void {if (this.loginForm.invalid) return;this.isLoading = true;this.errorMessage = null;const { email, password } = this.loginForm.value;this.authService.login({ email, password }).subscribe({next: () => {this.router.navigateByUrl(this.returnUrl!);},error: (err) => {this.errorMessage = err.error?.message || '登录失败,请检查您的凭据';this.isLoading = false;}});}togglePasswordVisibility(): void {this.showPassword = !this.showPassword;}
}

login.component.html:

<div class="login-container"><mat-card class="login-card"><mat-card-header><mat-card-title class="text-center">欢迎回来</mat-card-title><mat-card-subtitle class="text-center">请登录您的账户</mat-card-subtitle></mat-card-header><mat-card-content><form [formGroup]="loginForm" (ngSubmit)="onSubmit()"><mat-form-field appearance="outline" class="full-width"><mat-label>电子邮箱</mat-label><input matInput formControlName="email" type="email"><mat-icon matSuffix>mail</mat-icon><mat-error *ngIf="loginForm.get('email')?.hasError('required')">邮箱为必填项</mat-error><mat-error *ngIf="loginForm.get('email')?.hasError('email')">请输入有效的邮箱地址</mat-error></mat-form-field><mat-form-field appearance="outline" class="full-width"><mat-label>密码</mat-label><input matInput [type]="showPassword ? 'text' : 'password'" formControlName="password"><button type="button" mat-icon-button matSuffix(click)="togglePasswordVisibility()"><mat-icon>{{ showPassword ? 'visibility_off' : 'visibility' }}</mat-icon></button><mat-error *ngIf="loginForm.get('password')?.hasError('required')">密码为必填项</mat-error></mat-form-field><div class="remember-forgot"><mat-checkbox formControlName="rememberMe">记住我</mat-checkbox><a routerLink="/forgot-password">忘记密码?</a></div><app-error-message [message]="errorMessage"></app-error-message><button mat-raised-button color="primary" class="full-width" type="submit"[disabled]="loginForm.invalid || isLoading"><span *ngIf="!isLoading">登录</span><mat-spinner *ngIf="isLoading" diameter="20"></mat-spinner></button></form></mat-card-content><mat-card-actions class="text-center"><p>还没有账户? <a routerLink="/register">立即注册</a></p></mat-card-actions></mat-card>
</div>

login.component.scss:

.login-container {display: flex;justify-content: center;align-items: center;min-height: 100vh;background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);padding: 1rem;
}.login-card {width: 100%;max-width: 450px;padding: 2rem;box-shadow: 0 10px 30px rgba(0, 0, 0, 0.1);border-radius: 10px;
}.full-width {width: 100%;margin-bottom: 1.5rem;
}.remember-forgot {display: flex;justify-content: space-between;align-items: center;margin-bottom: 1.5rem;
}.text-center {text-align: center;
}
6. 注册组件

register.component.ts:

import { Component } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { Router } from '@angular/router';
import { AuthService } from '../../core/services/auth.service';
import { passwordValidator } from '../../../shared/validators/password.validator';@Component({selector: 'app-register',templateUrl: './register.component.html',styleUrls: ['./register.component.scss']
})
export class RegisterComponent {registerForm: FormGroup;isLoading = false;errorMessage: string | null = null;successMessage: string | null = null;showPassword = false;showConfirmPassword = false;constructor(private fb: FormBuilder,private authService: AuthService,private router: Router) {this.registerForm = this.fb.group({name: ['', [Validators.required, Validators.minLength(2)]],email: ['', [Validators.required, Validators.email]],password: ['', [Validators.required, passwordValidator()]],confirmPassword: ['', Validators.required],agreeTerms: [false, Validators.requiredTrue]}, {validators: this.passwordMatchValidator});}passwordMatchValidator(group: FormGroup) {const password = group.get('password')?.value;const confirmPassword = group.get('confirmPassword')?.value;return password === confirmPassword ? null : { mismatch: true };}onSubmit(): void {if (this.registerForm.invalid) return;this.isLoading = true;this.errorMessage = null;this.successMessage = null;const { name, email, password } = this.registerForm.value;this.authService.register({ name, email, password }).subscribe({next: () => {this.successMessage = '注册成功!正在跳转到登录页面...';setTimeout(() => {this.router.navigate(['/login'], {queryParams: { registered: true }});}, 2000);},error: (err) => {this.errorMessage = err.error?.message || '注册失败,请重试';this.isLoading = false;}});}togglePasswordVisibility(field: 'password' | 'confirmPassword'): void {if (field === 'password') {this.showPassword = !this.showPassword;} else {this.showConfirmPassword = !this.showConfirmPassword;}}
}

password.validator.ts:

import { AbstractControl, ValidatorFn } from '@angular/forms';export function passwordValidator(): ValidatorFn {return (control: AbstractControl): { [key: string]: any } | null => {const value = control.value || '';if (!value) {return null;}const errors: any = {};// 检查长度if (value.length < 8) {errors.minLength = { requiredLength: 8 };}// 检查大写字母if (!/[A-Z]/.test(value)) {errors.missingUpperCase = true;}// 检查数字if (!/\d/.test(value)) {errors.missingNumber = true;}// 检查特殊字符if (!/[!@#$%^&*(),.?":{}|<>]/.test(value)) {errors.missingSpecialChar = true;}return Object.keys(errors).length > 0 ? { passwordRequirements: errors } : null;};
}
7. 错误消息组件

error-message.component.ts:

import { Component, Input } from '@angular/core';@Component({selector: 'app-error-message',template: `<div class="error-message" *ngIf="message"><mat-icon>error</mat-icon><span>{{ message }}</span></div>`,styles: [`.error-message {display: flex;align-items: center;color: #f44336;background-color: #ffebee;padding: 10px 15px;border-radius: 4px;margin-bottom: 20px;font-size: 14px;mat-icon {margin-right: 8px;font-size: 18px;}}`]
})
export class ErrorMessageComponent {@Input() message: string | null = null;
}
8. 路由配置

auth-routing.module.ts:

import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { LoginComponent } from './login/login.component';
import { RegisterComponent } from './register/register.component';const routes: Routes = [{ path: 'login', component: LoginComponent },{ path: 'register', component: RegisterComponent },{ path: 'forgot-password', loadChildren: () => import('./forgot-password/forgot-password.module').then(m => m.ForgotPasswordModule) }
];@NgModule({imports: [RouterModule.forChild(routes)],exports: [RouterModule]
})
export class AuthRoutingModule { }

app-routing.module.ts:

import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { AuthGuard } from './core/guards/auth.guard';const routes: Routes = [{ path: '', redirectTo: '/dashboard', pathMatch: 'full' },{path: 'dashboard',loadChildren: () => import('./modules/dashboard/dashboard.module').then(m => m.DashboardModule),canActivate: [AuthGuard]},{path: 'auth',loadChildren: () => import('./modules/auth/auth.module').then(m => m.AuthModule)},{ path: '**', redirectTo: '/dashboard' }
];@NgModule({imports: [RouterModule.forRoot(routes, { scrollPositionRestoration: 'top' })],exports: [RouterModule]
})
export class AppRoutingModule { }
9. 主模块配置

app.module.ts:

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { HttpClientModule, HTTP_INTERCEPTORS } from '@angular/common/http';
import { ReactiveFormsModule } from '@angular/forms';import { MatInputModule } from '@angular/material/input';
import { MatButtonModule } from '@angular/material/button';
import { MatCardModule } from '@angular/material/card';
import { MatIconModule } from '@angular/material/icon';
import { MatCheckboxModule } from '@angular/material/checkbox';
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
import { MatSnackBarModule } from '@angular/material/snack-bar';import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { AuthInterceptor } from './core/interceptors/auth.interceptor';
import { ErrorMessageComponent } from './shared/components/error-message/error-message.component';@NgModule({declarations: [AppComponent,ErrorMessageComponent],imports: [BrowserModule,BrowserAnimationsModule,HttpClientModule,ReactiveFormsModule,AppRoutingModule,// Material ModulesMatInputModule,MatButtonModule,MatCardModule,MatIconModule,MatCheckboxModule,MatProgressSpinnerModule,MatSnackBarModule],providers: [{ provide: HTTP_INTERCEPTORS, useClass: AuthInterceptor, multi: true }],bootstrap: [AppComponent]
})
export class AppModule { }
10. 环境配置

environment.ts:

export const environment = {production: false,apiUrl: 'http://localhost:8080/api',appName: 'Auth Demo'
};

功能亮点说明

  1. 响应式表单验证

    • 自定义密码验证器(长度、大小写、数字、特殊字符)
    • 实时表单错误反馈
    • 密码匹配验证
  2. 用户体验优化

    • 密码可见性切换
    • 加载状态指示器
    • 错误和成功消息提示
    • 记住我功能
    • 登录后重定向
  3. 安全特性

    • JWT自动附加到请求头
    • Token过期处理(401错误自动跳转)
    • 本地存储加密考虑(实际项目应使用更安全的方式)
  4. 状态管理

    • BehaviorSubject管理用户状态
    • 自动获取当前用户信息
    • 本地存储持久化
  5. 路由保护

    • 未认证用户自动重定向
    • 登录后返回原始请求页面
    • 模块懒加载
  6. 错误处理

    • 统一HTTP错误拦截
    • 友好的错误消息展示
    • 表单验证错误提示

使用说明

  1. 安装依赖:
npm install @angular/material @angular/cdk @angular/flex-layout
  1. styles.scss中添加:
@import '@angular/material/prebuilt-themes/indigo-pink.css';
html, body { height: 100%; }
body { margin: 0; font-family: Roboto, "Helvetica Neue", sans-serif; }
  1. 运行应用:
ng serve --port 4200

这个实现提供了完整的认证流程,包括:

  • 用户注册(带密码强度验证)
  • 登录/注销功能
  • JWT令牌管理
  • 路由保护
  • 响应式UI设计
  • 完善的错误处理

实际项目中,你还可以添加:

  • 密码重置功能
  • 双因素认证
  • 社交登录(Google/Facebook)
  • 用户资料管理
  • 权限控制(基于角色)
http://www.dtcms.com/a/468518.html

相关文章:

  • 58做网站联系电话wordpress极客学院
  • 成都广告公司名单企业网站排名提升软件能优化
  • 西宁企业网站建设WordPress使用两个模板
  • 怎么做网站手机版网站开发怎么接单
  • 个体工商户网站备案流程内蒙古自治区工程建设网站
  • 做微信网站公司建设一个购物网站需要什么
  • 陕西手机网站建设公司排名张家口建设局网站
  • 企业为什么要做建站wordpress插件安装目录下
  • 五个常见的电子商务网站网址wordpress语言包插件
  • html5网站app开发在哪个彩票网站是小黄人做头像的
  • 沈阳做网站公司哪家好wordpress需要付费才能看某些页面
  • 济南网站建设行知科技不错h5手机制作软件app有哪些
  • 设计素材网站排行榜百度云手机登录入口
  • 做特卖的网站爱库存wordpress管理信息系统
  • 做视频网站 买带宽网站 东莞长安
  • 企业门户平台设计方案淘宝seo搜索引擎优化
  • 陕西公司网站建设湘潭网站建设有名磐石网络
  • 专业的顺的网站建设如何查询网站注册信息
  • 室内设计师常用网站服务品牌策划方案
  • wordpress网站 华为业务员用什么软件找客户
  • 新网站如何做排名东莞建网站找哪里
  • 网站上那些兼职网页怎么做昆明专业做网站多少钱
  • 策划的网站购物网站页面设计思路
  • 如果做网站运营网站构架图怎么做
  • 西部空间怎样上传网站2019建一个什么网站最好
  • 如何登录网站备案网站建设办公软件销售技巧
  • 建一个网站需要哪些东西三合一网站什么意思
  • 重庆房产信息网官网外贸seo网站制作
  • 商城建设网站开发住房和城乡建设部网站31号文
  • 北京城建设计集团网站深圳鹏洲建设工程有限公司网站