修改路径
This commit is contained in:
@@ -0,0 +1,30 @@
|
||||
<div class="bruce flex-ct-x">
|
||||
<form class="bubble-distribution">
|
||||
<h3>登录</h3>
|
||||
<div class="emailDiv">
|
||||
<input type="email" name="email" [(ngModel)]="loginReq.email" placeholder="请输入邮箱"
|
||||
pattern="^[\w-]+(\.[\w-]+)*@[\w-]+(\.[\w-]+)+$"
|
||||
required>
|
||||
<img class="img" src="https://oss.celess.cn/web/greeting.1415c1c.png" alt="">
|
||||
</div>
|
||||
<div class="pwdDiv">
|
||||
<input type="password" [(ngModel)]="loginReq.password" name="pwd" placeholder="请输入密码(6到16位字符)"
|
||||
pattern="^[\w_-]{6,16}$"
|
||||
required>
|
||||
<img class="img" src="https://oss.celess.cn/web/blindfold.58ce423.png" alt="">
|
||||
</div>
|
||||
<br>
|
||||
<input type="checkbox" id="isRemember" name="isRemember" [(ngModel)]="loginReq.isRememberMe"> <label
|
||||
for="isRemember"> 记住密码</label>
|
||||
<span id="sendEmail" *ngIf="showSendEmail" (click)="sendEmail()">找回密码</span>
|
||||
|
||||
<span [style]="{display: showSendEmail?'block':'inline',float:showSendEmail?null:'right'}" class="to-reg">还没有账号,去
|
||||
<a [routerLink]="'/user/registration'"
|
||||
(click)="loginStatus.emit(true)">注册</a>
|
||||
</span>
|
||||
<img class="img" src="https://oss.celess.cn/web/normal.0447fe9.png" alt="">
|
||||
|
||||
<button nz-button nzType="primary" (click)="doLogin()" [nzLoading]="submitting">登录</button>
|
||||
|
||||
</form>
|
||||
</div>
|
||||
@@ -0,0 +1,9 @@
|
||||
@import "../../login-registration.component.less";
|
||||
|
||||
#sendEmail {
|
||||
float: right;
|
||||
}
|
||||
|
||||
.to-reg {
|
||||
line-height: 40px;
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { LoginComponent } from './login.component';
|
||||
|
||||
describe('LoginComponent', () => {
|
||||
let component: LoginComponent;
|
||||
let fixture: ComponentFixture<LoginComponent>;
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ LoginComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(LoginComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,81 @@
|
||||
import {Component, EventEmitter, Input, OnInit, Output} from '@angular/core';
|
||||
import {NzMessageService} from 'ng-zorro-antd';
|
||||
import {LoginReq} from '../../../../class/User';
|
||||
import {ActivatedRoute, Router} from '@angular/router';
|
||||
import {LoginRegistrationService} from '../../service/login-registration.service';
|
||||
import {Title} from '@angular/platform-browser';
|
||||
import {GlobalUserService} from '../../../../services/global-user.service';
|
||||
|
||||
@Component({
|
||||
selector: 'c-login',
|
||||
templateUrl: './login.component.html',
|
||||
styleUrls: ['./login.component.less']
|
||||
})
|
||||
export class LoginComponent implements OnInit {
|
||||
|
||||
constructor(private nzMessageService: NzMessageService,
|
||||
private userService: GlobalUserService,
|
||||
private activatedRoute: ActivatedRoute,
|
||||
private router: Router,
|
||||
private loginRegistrationService: LoginRegistrationService,
|
||||
private title: Title) {
|
||||
this.title.setTitle('小海博客 | 登录 ');
|
||||
}
|
||||
|
||||
submitting: boolean = false;
|
||||
|
||||
loginReq: LoginReq = new LoginReq(null, true, null);
|
||||
@Output() loginStatus = new EventEmitter<boolean>();
|
||||
@Input() showSendEmail: boolean = true;
|
||||
|
||||
private url: string;
|
||||
|
||||
ngOnInit() {
|
||||
this.url = this.activatedRoute.snapshot.queryParamMap.get('url');
|
||||
this.loginReq.email = localStorage.getItem('e');
|
||||
this.loginReq.password = localStorage.getItem('p');
|
||||
localStorage.removeItem('e');
|
||||
localStorage.removeItem('p');
|
||||
}
|
||||
|
||||
doLogin() {
|
||||
this.submitting = true;
|
||||
const emailReg = /^[\w-]+(\.[\w-]+)*@[\w-]+(\.[\w-]+)+$/;
|
||||
const pwdReg = /^[\w_-]{6,16}$/;
|
||||
if (!this.loginReq.email || !emailReg.test(this.loginReq.email)) {
|
||||
this.submitting = false;
|
||||
this.nzMessageService.error('邮箱格式不正确');
|
||||
return;
|
||||
}
|
||||
if (!this.loginReq.password || !pwdReg.test(this.loginReq.password)) {
|
||||
this.submitting = false;
|
||||
this.nzMessageService.error('密码格式不正确');
|
||||
return;
|
||||
}
|
||||
|
||||
this.userService.login(this.loginReq, {
|
||||
complete: () => null,
|
||||
error: (err) => {
|
||||
this.nzMessageService.error(err.msg);
|
||||
this.submitting = false;
|
||||
this.loginStatus.emit(false);
|
||||
},
|
||||
next: data => {
|
||||
this.submitting = false;
|
||||
this.nzMessageService.success('登录成功,欢迎你' + data.result.displayName);
|
||||
this.loginStatus.emit(true);
|
||||
if (this.url) {
|
||||
this.router.navigateByUrl(this.url);
|
||||
} else {
|
||||
// window.location.href = '/admin/';
|
||||
this.router.navigateByUrl('/admin')
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
sendEmail() {
|
||||
this.loginRegistrationService.showModal = true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
<div class="bruce flex-ct-x">
|
||||
<form class="bubble-distribution">
|
||||
<h3>注册</h3>
|
||||
<div class="emailDiv">
|
||||
<input type="email" name="email" [(ngModel)]="email" placeholder="请输入邮箱"
|
||||
pattern="^[\w-]+(\.[\w-]+)*@[\w-]+(\.[\w-]+)+$"
|
||||
required>
|
||||
<img class="img" src="https://oss.celess.cn/web/greeting.1415c1c.png" alt="">
|
||||
</div>
|
||||
<div class="pwdDiv">
|
||||
<input type="password" [(ngModel)]="pwd" name="pwd" placeholder="请输入密码(6到16位字符)"
|
||||
pattern="^[\w_-]{6,16}$"
|
||||
required>
|
||||
<img class="img" src="https://oss.celess.cn/web/blindfold.58ce423.png" alt="">
|
||||
</div>
|
||||
<div class="codeDiv">
|
||||
<input type="text" name="code" placeholder="请输入验证码" pattern="^[\w]{4}$" maxLength="4"
|
||||
[(ngModel)]="imgCode" required>
|
||||
<img [src]="imgCodeUrl" id="imgCode" alt="imgcode" (click)="changeImg()" title="点击更换验证码">
|
||||
<img class="img" src="https://oss.celess.cn/web/greeting.1415c1c.png" alt="">
|
||||
</div>
|
||||
<img class="img" src="https://oss.celess.cn/web/normal.0447fe9.png" alt="">
|
||||
<br>
|
||||
<button nz-button nzType="primary" (click)="doRegistration()" [nzLoading]="submitting">注册</button>
|
||||
</form>
|
||||
</div>
|
||||
@@ -0,0 +1 @@
|
||||
@import "../../login-registration.component.less";
|
||||
@@ -0,0 +1,25 @@
|
||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { RegistrationComponent } from './registration.component';
|
||||
|
||||
describe('RegistrationComponent', () => {
|
||||
let component: RegistrationComponent;
|
||||
let fixture: ComponentFixture<RegistrationComponent>;
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ RegistrationComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(RegistrationComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,104 @@
|
||||
import {Component, EventEmitter, OnInit, Output} from '@angular/core';
|
||||
import {environment} from '../../../../../environments/environment';
|
||||
import {ApiService} from '../../../../api/api.service';
|
||||
import {NzMessageService} from 'ng-zorro-antd';
|
||||
import {Router} from '@angular/router';
|
||||
import {ErrDispatch} from '../../../../class/ErrDispatch';
|
||||
import {RequestObj} from '../../../../class/HttpReqAndResp';
|
||||
import {LoginReq} from '../../../../class/User';
|
||||
import {Title} from '@angular/platform-browser';
|
||||
|
||||
@Component({
|
||||
selector: 'c-registration',
|
||||
templateUrl: './registration.component.html',
|
||||
styleUrls: ['./registration.component.less'],
|
||||
providers: [ApiService]
|
||||
})
|
||||
export class RegistrationComponent implements OnInit, ErrDispatch {
|
||||
|
||||
constructor(private apiService: ApiService,
|
||||
private nzMessageService: NzMessageService,
|
||||
private router: Router,
|
||||
private title: Title) {
|
||||
apiService.setErrDispatch(this);
|
||||
this.title.setTitle('小海博客 | 注册');
|
||||
}
|
||||
|
||||
imgCodeUrl: string;
|
||||
|
||||
imgCode: string;
|
||||
|
||||
email: string;
|
||||
pwd: string;
|
||||
|
||||
submitting: boolean;
|
||||
@Output() regStatus = new EventEmitter<boolean>();
|
||||
@Output() regAccount = new EventEmitter<LoginReq>();
|
||||
|
||||
ngOnInit() {
|
||||
this.imgCodeUrl = environment.host + '/imgCode';
|
||||
this.submitting = false;
|
||||
}
|
||||
|
||||
changeImg() {
|
||||
this.imgCode = '';
|
||||
this.imgCodeUrl = environment.host + '/imgCode?t=' + new Date().valueOf();
|
||||
}
|
||||
|
||||
// 提交注册
|
||||
doRegistration() {
|
||||
this.submitting = true;
|
||||
// 数据验证
|
||||
if (!this.email || !this.pwd) {
|
||||
this.nzMessageService.error('邮箱账号和密码不可为空');
|
||||
|
||||
this.submitting = false;
|
||||
return;
|
||||
}
|
||||
const emailReg = /^[\w-]+(\.[\w-]+)*@[\w-]+(\.[\w-]+)+$/;
|
||||
if (!emailReg.test(this.email)) {
|
||||
this.nzMessageService.error('邮箱格式不正确');
|
||||
this.submitting = false;
|
||||
return;
|
||||
}
|
||||
const pwdReg = /^[\w_-]{6,16}$/;
|
||||
if (!pwdReg.test(this.pwd)) {
|
||||
this.nzMessageService.error('密码格式不正确');
|
||||
this.submitting = false;
|
||||
return;
|
||||
}
|
||||
if (!this.imgCode || this.imgCode.length !== 4) {
|
||||
this.nzMessageService.error('验证码不正确');
|
||||
this.submitting = false;
|
||||
return;
|
||||
}
|
||||
// 验证验证码
|
||||
this.apiService.verifyImgCode(this.imgCode).subscribe(data => {
|
||||
// 验证成功 注册
|
||||
this.apiService.registration(this.email, this.pwd).subscribe(regData => {
|
||||
localStorage.setItem('e', this.email);
|
||||
localStorage.setItem('p', this.pwd);
|
||||
this.email = '';
|
||||
this.pwd = '';
|
||||
this.imgCode = '';
|
||||
this.submitting = false;
|
||||
this.nzMessageService.success('注册成功,三秒后跳转登录页面');
|
||||
this.regStatus.emit(true);
|
||||
this.regAccount.emit(new LoginReq(this.email, true, this.pwd));
|
||||
setTimeout(() => {
|
||||
if (this.router) {
|
||||
this.router.navigateByUrl('/user/login');
|
||||
}
|
||||
}, 3000);
|
||||
}
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
errHandler(code: number, msg: string, request?: RequestObj): void {
|
||||
this.nzMessageService.error('reg' + msg);
|
||||
this.regStatus.emit(false);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
import {NgModule} from '@angular/core';
|
||||
import {RouterModule, Routes} from '@angular/router';
|
||||
import {LoginComponent} from './components/login/login.component';
|
||||
import {RegistrationComponent} from './components/registration/registration.component';
|
||||
import {LoginRegistrationComponent} from './login-registration.component';
|
||||
|
||||
const routes: Routes = [
|
||||
{
|
||||
path: '',
|
||||
component: LoginRegistrationComponent,
|
||||
children: [
|
||||
{path: 'login', component: LoginComponent},
|
||||
{path: 'registration', component: RegistrationComponent},
|
||||
{path: '**', component: LoginComponent}
|
||||
]
|
||||
}
|
||||
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
RouterModule.forChild(routes)
|
||||
],
|
||||
exports: [RouterModule]
|
||||
})
|
||||
|
||||
export class LoginRegistrationRoutingModule {
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
<div [style.background-image]="'url(' +picUrl+')'" id="main">
|
||||
<div id="op-Area">
|
||||
<router-outlet></router-outlet>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<nz-modal [(nzVisible)]="loginRegistrationService.showModal" [nzTitle]="title" [nzContent]="content" [nzFooter]="null"
|
||||
(nzOnCancel)="loginRegistrationService.showModal = false">
|
||||
<ng-template #title>
|
||||
<h2>发送密码重置邮件</h2>
|
||||
</ng-template>
|
||||
|
||||
<ng-template #content>
|
||||
|
||||
<form nz-form>
|
||||
<nz-form-item>
|
||||
<input nz-input placeholder="请输入你的邮箱地址" [(ngModel)]="email" name="email">
|
||||
</nz-form-item>
|
||||
<nz-form-item>
|
||||
<button nz-button style="width: 100%" nzType="primary" type="submit" (click)="send()"
|
||||
[nzLoading]="submitting">发送邮件
|
||||
</button>
|
||||
</nz-form-item>
|
||||
</form>
|
||||
</ng-template>
|
||||
</nz-modal>
|
||||
@@ -0,0 +1,114 @@
|
||||
|
||||
.bubble-distribution {
|
||||
position: relative;
|
||||
padding: 25px;
|
||||
border-radius: 2px;
|
||||
background-color: #fff;
|
||||
|
||||
h3 {
|
||||
font-weight: bold;
|
||||
font-size: 16px;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
div {
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.img {
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
bottom: 100%;
|
||||
margin: 0 0 -20px -60px;
|
||||
width: 120px;
|
||||
}
|
||||
|
||||
|
||||
input[type=email],
|
||||
input[type=text],
|
||||
input[type=password] {
|
||||
padding: 10px;
|
||||
outline: none;
|
||||
border: 1px solid #e9e9e9;
|
||||
border-radius: 2px;
|
||||
width: 100%;
|
||||
height: 40px;
|
||||
transition: all 300ms;
|
||||
|
||||
&:focus:valid {
|
||||
border-color: #09f;
|
||||
}
|
||||
|
||||
&:focus:invalid {
|
||||
border-color: #f66;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
button {
|
||||
width: 100%;
|
||||
margin-top: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
.emailDiv,
|
||||
.pwdDiv,
|
||||
.codeDiv {
|
||||
.img {
|
||||
display: none;
|
||||
margin-bottom: -27px;
|
||||
}
|
||||
|
||||
&:focus-within {
|
||||
.img {
|
||||
display: block;
|
||||
}
|
||||
|
||||
& ~ .img {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.codeDiv {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
|
||||
input {
|
||||
width: 70% !important;
|
||||
}
|
||||
|
||||
#imgCode {
|
||||
margin-top: 0;
|
||||
width: 25%;
|
||||
height: 40px;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
#main {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-position: center center;
|
||||
background-size: cover;
|
||||
|
||||
#op-Area {
|
||||
min-width: 320px;
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@media screen and (max-width: 940px) {
|
||||
#op-Area {
|
||||
width: 90%;
|
||||
margin:0 2%;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { LoginRegistrationComponent } from './login-registration.component';
|
||||
|
||||
describe('LoginRegistrationComponent', () => {
|
||||
let component: LoginRegistrationComponent;
|
||||
let fixture: ComponentFixture<LoginRegistrationComponent>;
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ LoginRegistrationComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(LoginRegistrationComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,45 @@
|
||||
import {Component, OnInit} from '@angular/core';
|
||||
import {ApiService} from '../../api/api.service';
|
||||
import {LoginRegistrationService} from './service/login-registration.service';
|
||||
import {NzMessageService} from 'ng-zorro-antd';
|
||||
|
||||
@Component({
|
||||
selector: 'view-login-registration',
|
||||
templateUrl: './login-registration.component.html',
|
||||
styleUrls: ['./login-registration.component.less']
|
||||
})
|
||||
export class LoginRegistrationComponent implements OnInit {
|
||||
|
||||
constructor(private apiService: ApiService,
|
||||
public loginRegistrationService: LoginRegistrationService,
|
||||
private nzMessageService: NzMessageService) {
|
||||
}
|
||||
|
||||
picUrl: string = '';
|
||||
email: string;
|
||||
submitting: boolean = false;
|
||||
|
||||
ngOnInit() {
|
||||
this.apiService.bingPic().subscribe(data => {
|
||||
this.picUrl = data.result;
|
||||
});
|
||||
}
|
||||
|
||||
send() {
|
||||
this.submitting = true;
|
||||
if (!this.email || this.email.length === 0) {
|
||||
this.submitting = false;
|
||||
this.nzMessageService.warning('邮箱不可为空');
|
||||
return;
|
||||
}
|
||||
this.apiService.sendResetPwdEmail(this.email).subscribe(data => {
|
||||
this.submitting = false;
|
||||
this.nzMessageService.success('发送成功');
|
||||
this.loginRegistrationService.showModal = false;
|
||||
}, error => {
|
||||
this.nzMessageService.error(error.msg);
|
||||
this.submitting = false;
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
31
src/app/view/login-registration/login-registration.module.ts
Normal file
31
src/app/view/login-registration/login-registration.module.ts
Normal file
@@ -0,0 +1,31 @@
|
||||
import {NgModule} from '@angular/core';
|
||||
import {CommonModule} from '@angular/common';
|
||||
|
||||
import {LoginComponent} from './components/login/login.component';
|
||||
import {RegistrationComponent} from './components/registration/registration.component';
|
||||
import {LoginRegistrationRoutingModule} from './login-registration-routing.module';
|
||||
import {LoginRegistrationComponent} from './login-registration.component';
|
||||
import {FormsModule} from '@angular/forms';
|
||||
import {NzButtonModule, NzFormModule, NzGridModule, NzInputModule, NzModalModule} from 'ng-zorro-antd';
|
||||
|
||||
|
||||
@NgModule({
|
||||
declarations: [LoginComponent, RegistrationComponent, LoginRegistrationComponent],
|
||||
exports: [
|
||||
LoginComponent,
|
||||
RegistrationComponent
|
||||
],
|
||||
imports: [
|
||||
CommonModule,
|
||||
LoginRegistrationRoutingModule,
|
||||
FormsModule,
|
||||
NzButtonModule,
|
||||
NzModalModule,
|
||||
NzFormModule,
|
||||
NzInputModule,
|
||||
NzGridModule
|
||||
|
||||
]
|
||||
})
|
||||
export class LoginRegistrationModule {
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
import { TestBed } from '@angular/core/testing';
|
||||
|
||||
import { LoginRegistrationService } from './login-registration.service';
|
||||
|
||||
describe('LoginRegistrationService', () => {
|
||||
let service: LoginRegistrationService;
|
||||
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({});
|
||||
service = TestBed.inject(LoginRegistrationService);
|
||||
});
|
||||
|
||||
it('should be created', () => {
|
||||
expect(service).toBeTruthy();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,12 @@
|
||||
import {Injectable} from '@angular/core';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class LoginRegistrationService {
|
||||
|
||||
constructor() {
|
||||
}
|
||||
|
||||
showModal: boolean = false;
|
||||
}
|
||||
Reference in New Issue
Block a user