从"Blog"仓库中分离出来

This commit is contained in:
小海
2019-11-28 19:26:45 +08:00
commit c2aaf280db
616 changed files with 104128 additions and 0 deletions

View File

@@ -0,0 +1,50 @@
.dashboardUl {
width: 100%;
padding: 1.6em;
}
.dashboardUl i {
font-size: 40px;
}
.dashboardUl li {
float: left;
border-right: 1px solid #ececec;
width: 25%;
text-align: center;
}
.dashboardUl li:last-child {
border-right: none;
}
.circle {
border-radius: 50%;
text-align: center;
}
p {
margin: 15px 0;
}
.log {
margin-top: 20px;
max-height: 500px;
padding: 10px;
background: #F8F8F8;
}
.reloadLog {
position: absolute;
right: 20px;
top: 10px;
z-index: 990;
}
.card {
text-align: center;
}
.card i {
font-size: 40px;
}

View File

@@ -0,0 +1,71 @@
<!-- content start -->
<div class="admin-content" id="index">
<div class="admin-content-body" *ngIf="userService.userInfo&&userService.userInfo.role=='user'">
<div>
<div><strong class="part-title">首页</strong></div>
</div>
<h2 style="text-align: center;">
Welcome {{userService.userInfo.displayName}}!
</h2>
<nz-card class="card">
<ul class="dashboardUl">
<li style="width: 50%">
<div><i nz-icon nzType="login" nzTheme="outline"></i></div>
<p>上次登录</p>
<p>{{userService.userInfo.recentlyLandedDate}}</p>
</li>
<li style="width: 50%">
<div><i nz-icon nzType="environment" nzTheme="outline"></i></div>
<p>您的ip和位置</p>
<p>
ip:{{ip}}
<br>
位置:{{location}}
</p>
</li>
</ul>
</nz-card>
</div>
<!-- administrator page -->
<div *ngIf="userService.userInfo&&userService.userInfo.role=='admin'">
<nz-card>
<ul class="dashboardUl">
<li>
<div><i nz-icon nzType="ie" nzTheme="outline"></i></div>
<p>总访问量</p>
<p>{{visitorService.totalVisitCount}}</p>
</li>
<li>
<div><i nz-icon nzType="chrome" nzTheme="outline"></i></div>
<p>今日访问量</p>
<p>{{visitorService.dayVisit}}</p>
</li>
<li>
<div><i nz-icon nzType="login" nzTheme="outline"></i></div>
<p>上次登录</p>
<p>{{userService.userInfo.recentlyLandedDate}}</p>
</li>
<li>
<div><i nz-icon nzType="arrow-up" nzTheme="outline"></i></div>
<p>上次更新</p>
<p>{{webUpdateService.lastestUpdateTime}}</p>
</li>
</ul>
</nz-card>
<div style="position: relative">
<button nz-button nzType="danger" nzShape="circle" class="reloadLog" (click)="readLog()">
<i nz-icon nzType="reload" nzTheme="outline"></i>
</button>
<nz-spin [nzSpinning]="Loading">
<pre class="log">
{{this.logService.logText}}
</pre>
</nz-spin>
</div>
</div>
</div>
<!-- content end -->

View File

@@ -0,0 +1,25 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { AIndexComponent } from './a-index.component';
describe('AIndexComponent', () => {
let component: AIndexComponent;
let fixture: ComponentFixture<AIndexComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ AIndexComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(AIndexComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@@ -0,0 +1,80 @@
import {Component, OnInit} from '@angular/core';
import {UserService} from '../../services/user/user.service';
import {VisitorService} from '../../services/visitor/visitor.service';
import {WebUpdateService} from '../../services/update/web-update.service';
import {LogService} from '../../services/log/log.service';
import {Observable} from 'rxjs';
@Component({
selector: 'app-a-index',
templateUrl: './a-index.component.html',
styleUrls: ['./a-index.component.css']
})
export class AIndexComponent implements OnInit {
constructor(public userService: UserService,
public visitorService: VisitorService,
public webUpdateService: WebUpdateService,
public logService: LogService) {
}
Loading: boolean = false;
ip: string;
location: string;
ngOnInit() {
if (this.userService.userInfo) {
if (this.userService.userInfo.role === 'admin') {
this.admin();
} else {
this.user();
}
} else {
this.userService.getUserInfo().subscribe(data => {
if (data.result.role === 'admin') {
this.admin();
} else {
this.user();
}
});
}
}
admin() {
if (!this.visitorService.dayVisit) {
this.visitorService.getDayVisitor();
}
this.visitorService.getTotalVisitorCount();
if (!this.webUpdateService.lastestUpdateTime) {
this.webUpdateService.getLastestUpdateTime();
}
this.readLog();
}
user() {
this.visitorService.getLocalIp().subscribe(data => {
if (data.code === 0) {
this.ip = data.result;
const getip = this.visitorService.getIp(this.ip);
if (getip instanceof Observable) {
getip.subscribe(ipOb => {
this.location = ipOb.result;
});
} else {
this.location = getip;
}
}
});
}
readLog() {
this.Loading = true;
this.logService.getLog().subscribe(date => {
setTimeout(() => {
this.Loading = false;
}, 100);
});
}
}

View File

@@ -0,0 +1,6 @@
.popup-content {
text-align: center;
height: 70px;
}

View File

@@ -0,0 +1,73 @@
<!--文章管理-->
<div class="admin-content" id="article-manager">
<div class="admin-content-body">
<div>
<div><strong class="part-title">文章管理</strong></div>
</div>
<div class="scrollable-horizontal" *ngIf="articleService.currentPage">
<table class="table">
<thead>
<tr>
<th>ID</th>
<th>标题</th>
<th>发布日期</th>
<th>更新日期</th>
<th>阅读量</th>
<th title="(可见/不可见)勾选则可见,否则不可见">文章状态</th>
<th>管理</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let article of articleService.currentPage.list">
<td>{{article.id}}</td>
<td><a [routerLink]="[ '/article']" [queryParams]="{'id':article.id}">{{article.title}}</a>
</td>
<td>{{article.publishDateFormat}}</td>
<td>{{article.updateDateFormat}}</td>
<td><span class="badge badge-success">{{article.readingNumber}}</span></td>
<td style="text-align: center">
<input type="checkbox" class="disabled" disabled [checked]="article.open"
[title]="article.open?'可见':'不可见'">
</td>
<td>
<a [href]="'../write?id='+article.id">
<i nz-icon nzType="edit" nzTheme="twotone" nzTwotoneColor="#52c41a"></i> 编辑
</a>
<nz-divider nzType="vertical"></nz-divider>
<a nz-dropdown [nzDropdownMenu]="menu" nzPlacement="bottomLeft" nzTrigger="click">
更多 <i nz-icon nzType="down" nzTheme="outline"></i>
</a>
<nz-dropdown-menu #menu="nzDropdownMenu">
<ul nz-menu nzSelectable>
<li nz-menu-item>
<a [href]="'../article/'+article.id">
<i nz-icon nzType="file" nzTheme="twotone" nzTwotoneColor="#3F66FF"></i> 查看
</a>
</li>
<li nz-menu-item>
<a nz-popconfirm [nzTitle]="'是否要删除'+article.title+'?'"
(nzOnConfirm)="doDel(article.id)">
<i nz-icon nzType="delete" nzTheme="twotone" nzTwotoneColor="#eb2f96"></i> 删除
</a>
</li>
</ul>
</nz-dropdown-menu>
</td>
</tr>
</tbody>
</table>
<nz-pagination align="center" [nzHideOnSinglePage]="true" [nzPageIndex]="pageNum" [nzPageSize]="pageSize"
[nzTotal]="articleService.currentPage.total"
(nzPageIndexChange)="toPage($event)">
</nz-pagination>
</div>
</div>
</div>

View File

@@ -0,0 +1,25 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { ArticleManagerComponent } from './article-manager.component';
describe('ArticleManagerComponent', () => {
let component: ArticleManagerComponent;
let fixture: ComponentFixture<ArticleManagerComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ ArticleManagerComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(ArticleManagerComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@@ -0,0 +1,50 @@
import {Component, OnInit} from '@angular/core';
import {NzMessageService} from 'ng-zorro-antd';
import {ArticleService} from '../../services/article/article.service';
@Component({
selector: 'app-article-manager',
templateUrl: './article-manager.component.html',
styleUrls: ['./article-manager.component.css']
})
export class ArticleManagerComponent implements OnInit {
constructor(private message: NzMessageService,
public articleService: ArticleService) {
}
public pageNum = 1;
public pageSize = 10;
showPupup = false;
ngOnInit() {
this.getData();
}
getData() {
this.articleService.getArticle(this.pageNum, this.pageSize);
}
doDel(id) {
this.showPupup = false;
this.articleService.deleteArticle(id).subscribe(data => {
if (data.code === 0) {
this.message.success('删除成功');
this.getData();
} else {
this.message.error('失败,原因:' + data.msg);
}
});
}
toPage(e: number) {
this.pageNum = e;
this.getData();
}
}

View File

@@ -0,0 +1,4 @@
a{
padding: 10px 0;
z-index: 5;
}

View File

@@ -0,0 +1,66 @@
<!--分类-->
<div class="admin-content" id="category-manager">
<div class="admin-content-body">
<div>
<strong class="part-title">分类管理</strong>
<button nz-button nzGhost="true" nzType="primary" style="margin-left: 30px" (click)="addNewOne()">新增分类
</button>
</div>
<div class="scrollable-horizontal" *ngIf="categoryService.categories">
<table class="table">
<thead>
<tr>
<th>ID</th>
<th>分类名称</th>
<th>分类文章</th>
<th>文章数目</th>
<th>管理</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let category of categoryService.categories">
<td>{{category.id}}</td>
<td class="text-truncate" style="max-width: 150px">{{category.name}}</td>
<td>{{category.articles}}</td>
<td><span class="badge badge-success">{{category.articles.split(",").length - 1}}</span>
</td>
<td>
<a [href]="'../category?name='+category.name">
<i nz-icon nzType="book" nzTheme="twotone"></i> 查看
</a>
<nz-divider nzType="vertical"></nz-divider>
<a nz-dropdown [nzDropdownMenu]="menu" nzPlacement="bottomLeft" nzTrigger="click">
更多 <i nz-icon nzType="down" nzTheme="outline"></i>
</a>
<nz-dropdown-menu #menu="nzDropdownMenu">
<ul nz-menu nzSelectable>
<li nz-menu-item>
<a class="btn btn-secondary " (click)="edit(category.id,category.name)">编辑</a>
</li>
<li nz-menu-item>
<a nz-popconfirm nzTitle="是否要删除这个分类?" (nzOnConfirm)="doDel(category.id)">删除
</a>
</li>
</ul>
</nz-dropdown-menu>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<nz-modal [(nzVisible)]="showPupup" nzTitle="编辑" (nzOnCancel)="cancel()" (nzOnOk)="submit()">
<input nz-input style="width: 80%;margin-left: 10%" [(ngModel)]="updateReqBody.name">
</nz-modal>

View File

@@ -0,0 +1,25 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { CategoryManagerComponent } from './category-manager.component';
describe('CategoryManagerComponent', () => {
let component: CategoryManagerComponent;
let fixture: ComponentFixture<CategoryManagerComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ CategoryManagerComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(CategoryManagerComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@@ -0,0 +1,95 @@
import {Component, OnInit} from '@angular/core';
import {NzMessageService} from 'ng-zorro-antd';
import {CategoryService} from '../../services/category/category.service';
@Component({
selector: 'app-category-manager',
templateUrl: './category-manager.component.html',
styleUrls: ['./category-manager.component.css']
})
export class CategoryManagerComponent implements OnInit {
constructor(public categoryService: CategoryService, private message: NzMessageService) {
}
showPupup = false;
updateReqBody = {
id: null,
name: null
};
isAddNowOne = false; // 是否是新增分类的标识
ngOnInit() {
this.getData();
}
getData() {
if (this.categoryService.categories) {
return;
}
this.categoryService.getAllCategory();
}
edit(id, name) {
this.showPupup = true;
this.updateReqBody.id = id;
this.updateReqBody.name = name;
this.isAddNowOne = false;
}
submit() {
if (this.updateReqBody.name === '') {
alert('不能修改为空值!');
return;
}
this.showPupup = false;
if (!this.isAddNowOne) {
// 更新
this.categoryService.update(this.updateReqBody).subscribe(data => {
if (data.code === 0) {
this.message.success('修改成功');
for (let i = 0; i < this.categoryService.categories.length; i++) {
if ( this.categoryService.categories[i].id === this.updateReqBody.id) {
this.categoryService.categories[i].name = this.updateReqBody.name;
}
}
} else {
this.message.error('修改失败,原因:' + data.msg);
}
});
} else {
// 新建
this.categoryService.create(this.updateReqBody.name).subscribe(data => {
if (data.code === 0) {
this.message.success('新增成功');
} else {
this.message.error('新增失败,原因:' + data.msg);
}
});
}
}
doDel(id) {
this.categoryService.delete(id).subscribe(data => {
if (data.code === 0) {
this.message.success('删除成功');
} else {
this.message.error('删除失败,原因:' + data.msg);
}
});
}
addNewOne() {
this.showPupup = true;
this.updateReqBody.name = name;
this.isAddNowOne = true;
}
cancel() {
this.showPupup = !this.showPupup;
}
}

View File

@@ -0,0 +1,16 @@
.modal-mask {
background: black;
opacity: 0.4;
position: absolute;
overflow: hidden;
top: 0;
bottom: 0;
left: 0;
right: 0;
}
.comment {
border: 1px solid #cccccc;
border-radius: 5px;
padding: 5px 10px;
}

View File

@@ -0,0 +1,174 @@
<!--评论管理-->
<div class="admin-content" id="comment-manager">
<div class="admin-content-body">
<div><strong class="part-title">评论管理</strong>
<select class="select" [(ngModel)]="commentType" (change)="doInquire()">
<option class="option" selected value="1">评论</option>
<option class="option" value="0">留言</option>
</select>
</div>
<!-- 评论 -->
<div *ngIf="commentType==1&&commentService.currentComment">
<div class="scrollable-horizontal">
<table class="table">
<thead>
<tr>
<th>ID</th>
<th>文章标题</th>
<th>评论内容</th>
<th>评论日期</th>
<th>管理</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let comment of commentService.currentComment.list">
<td>{{comment.id}}</td>
<td class="text-truncate" [title]="comment.articleID+'.'+comment.articleTitle">
<a [routerLink]="[ '/article']"
[queryParams]="{'id':comment.articleID}">{{comment.articleTitle}}</a>
</td>
<td [title]="comment.content">
<span>{{comment.content.length > 40 ? (comment.content.substr(0, 40) + '...') : comment.content}}</span>
<nz-divider nzType="vertical"></nz-divider>
<a style="float: right;clear: both" (click)="prepareComment(comment)">查看</a>
</td>
<td>{{comment.date}}</td>
<td>
<a (click)="edit(0,comment.id,comment.content)">
<i nz-icon nzType="edit" nzTheme="twotone" nzTwotoneColor="#52c41a"></i> 编辑
</a>
<a nz-dropdown [nzDropdownMenu]="menu" nzPlacement="bottomLeft" nzTrigger="click">
更多 <i nz-icon nzType="down" nzTheme="outline"></i>
</a>
<nz-dropdown-menu #menu="nzDropdownMenu">
<ul nz-menu nzSelectable>
<!-- <li nz-menu-item>-->
<!-- <a disabled="true">回复</a>-->
<!-- </li>-->
<li nz-menu-item>
<a nz-popconfirm nzTitle="是否要删除这条评论?"
(nzOnConfirm)="doDel(comment.id)">删除
</a>
</li>
</ul>
</nz-dropdown-menu>
</td>
</tr>
</tbody>
</table>
<nz-pagination align="center" [nzHideOnSinglePage]="true" [nzPageIndex]="pageNum"
[nzTotal]="commentService.currentComment.total"
[nzPageSize]="pageSize" (nzPageIndexChange)="toPage($event)">
</nz-pagination>
</div>
</div>
<!-- 留言 -->
<div *ngIf="commentType==0&&commentService.currentLeaveMsg">
<div class=" scrollable-horizontal">
<table class="table ">
<thead>
<tr>
<th>ID</th>
<th>留言者</th>
<th>留言内容</th>
<th>留言日期</th>
<th>管理</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let leaveMsg of commentService.currentLeaveMsg.list">
<td>{{leaveMsg.id}}</td>
<td>{{leaveMsg.authorName}}</td>
<td [title]="leaveMsg.content">
<span>{{leaveMsg.content.length > 40 ? (leaveMsg.content.substr(0, 40) + '...') : leaveMsg.content}}</span>
<a style="float: right;clear: both" (click)="prepareComment(leaveMsg)">查看</a>
</td>
<td>{{leaveMsg.date}}</td>
<td>
<a (click)="edit(1,leaveMsg.id,leaveMsg.content)">
<i nz-icon nzType="edit" nzTheme="twotone" nzTwotoneColor="#52c41a"></i> 编辑
</a>
<nz-divider nzType="vertical"></nz-divider>
<a nz-dropdown [nzDropdownMenu]="menu" nzPlacement="bottomLeft" nzTrigger="click">
更多 <i nz-icon nzType="down" nzTheme="outline"></i>
</a>
<nz-dropdown-menu #menu="nzDropdownMenu">
<ul nz-menu nzSelectable>
<!-- <li nz-menu-item>-->
<!-- <a disabled="true">回复</a>-->
<!-- </li>-->
<li nz-menu-item>
<a nz-popconfirm nzTitle="是否要删除这条留言?"
(nzOnConfirm)="doDel(leaveMsg.id)">删除
</a>
</li>
</ul>
</nz-dropdown-menu>
</td>
</tr>
</tbody>
</table>
<nz-pagination align="center" [nzHideOnSinglePage]="true" [nzPageIndex]="pageNum"
[nzTotal]="commentService.currentLeaveMsg.total"
[nzPageSize]="pageSize" (nzPageIndexChange)="toPage($event)">
</nz-pagination>
</div>
</div>
</div>
</div>
<!-- 带输入框的弹出层 -->
<nz-modal [(nzVisible)]="showPupup" nzTitle="编辑" (nzOnCancel)="showPupup=!showPupup" (nzOnOk)="update()">
<textarea nz-input [(ngModel)]="updateReqBody.content"
[nzAutosize]="{ minRows: 2, maxRows: 6 }"></textarea>
</nz-modal>
<nz-modal [(nzVisible)]="showCommentDetail" (nzOnCancel)="showCommentDetail=!showCommentDetail"
(nzOnOk)="showCommentDetail=!showCommentDetail">
<nz-comment [nzAuthor]="commentDetail.authorName"
[nzDatetime]="commentDetail.date">
<nz-avatar nz-comment-avatar nzIcon="user" [nzSrc]="commentDetail.authorAvatarImgUrl"></nz-avatar>
<nz-comment-content class="comment">
<p>{{commentDetail.content}}</p>
</nz-comment-content>
<ng-container *ngIf="commentDetail.child && commentDetail.child.length">
<nz-comment *ngFor="let secLeaveMsg of commentDetail.child" [nzAuthor]="secLeaveMsg.authorName"
[nzDatetime]="secLeaveMsg.date">
<nz-avatar nz-comment-avatar nzIcon="user" [nzSrc]="secLeaveMsg.authorAvatarImgUrl"></nz-avatar>
<nz-comment-content class="comment">
<p>{{secLeaveMsg.content}}</p>
</nz-comment-content>
</nz-comment>
</ng-container>
<nz-comment>
<nz-comment-content>
<nz-form-item>
<textarea [(ngModel)]="responseComment.content" nz-input
[nzAutosize]="{ minRows: 2, maxRows: 6 }"></textarea>
</nz-form-item>
<nz-form-item>
<button nz-button nzType="primary" [disabled]="!responseComment.content"
(click)="reply()"> 回复
</button>
<button nz-button nzType="default" style="margin-left: 15px;"
(click)="responseComment.pid=null"> 取消
</button>
</nz-form-item>
</nz-comment-content>
</nz-comment>
</nz-comment>
</nz-modal>

View File

@@ -0,0 +1,25 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { CommentManagerComponent } from './comment-manager.component';
describe('CommentManagerComponent', () => {
let component: CommentManagerComponent;
let fixture: ComponentFixture<CommentManagerComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ CommentManagerComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(CommentManagerComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@@ -0,0 +1,130 @@
import {Component, OnInit} from '@angular/core';
import {NzMessageService} from 'ng-zorro-antd';
import {UserService} from '../../services/user/user.service';
import {CommentService} from '../../services/comment/comment.service';
import {Comment} from '../../classes/comment';
import {CommentReq} from '../../classes/commentReq';
@Component({
selector: 'app-comment-manager',
templateUrl: './comment-manager.component.html',
styleUrls: ['./comment-manager.component.css']
})
export class CommentManagerComponent implements OnInit {
constructor(public userService: UserService,
public commentService: CommentService,
private message: NzMessageService) {
}
pageNum: number = 1;
pageSize: number = 10;
commentType: number = 0;
showPupup = false;
updateReqBody = {
id: null,
type: null,
content: null
};
showCommentDetail: boolean = false;
commentDetail: Comment = new Comment();
responseComment: CommentReq = new CommentReq(true);
ngOnInit() {
if (!this.userService.userInfo) {
setTimeout(() => {
this.doInquire();
}, 500);
} else {
this.doInquire();
}
}
doInquire() {
const isAdmin: boolean = this.userService.userInfo.role === 'admin';
if (this.commentType) {
this.commentService.getComments(this.pageNum, this.pageSize, isAdmin);
} else {
this.commentService.getLeaveMsg(this.pageNum, this.pageSize, isAdmin);
}
}
toPage(e: number) {
this.pageNum = e;
this.doInquire();
}
prepareComment(comment: Comment) {
this.showCommentDetail = true;
this.commentDetail = comment;
this.commentService.getByPid(comment.id).subscribe(data => {
if (data.code === 0) {
this.commentDetail.child = data.result.list;
}
});
// tslint:disable-next-line:triple-equals
this.responseComment.comment = this.commentType == 1;
// 若展示的是顶级评论 则pid为顶级评论的id 否则为该二级评论的pid
this.responseComment.pid = this.commentDetail.pid === -1 ? this.commentDetail.id : this.commentDetail.pid;
this.responseComment.articleID = this.commentDetail.articleID;
console.log(`${this.commentType.valueOf() == 1} and type is ${this.commentType}`);
}
edit(type, id, content) {
this.showPupup = true;
this.updateReqBody.id = id;
this.updateReqBody.type = type;
this.updateReqBody.content = content;
}
update() {
if (this.updateReqBody.content === '') {
this.message.warning('不能为空');
return;
}
this.showPupup = false;
this.commentService.update(this.updateReqBody).subscribe(data => {
if (data.code === 0) {
this.message.success('修改成功!');
}
});
}
doDel(id) {
this.commentService.delete(id).subscribe(data => {
if (data.code === 0) {
this.message.success('删除成功');
} else {
this.message.error('删除失败,原因:' + data.msg);
}
});
}
reply() {
if (this.responseComment.content == null || this.responseComment.content === '') {
this.message.info('内容不能为空');
return;
}
this.responseComment.content = `@${this.commentDetail.authorName} ${this.responseComment.content}`
this.commentService.rely(this.responseComment).subscribe(data => {
if (data.code === 0) {
this.commentDetail.child.push(data.result);
this.message.success('回复成功');
this.responseComment = new CommentReq(true);
// tslint:disable-next-line:triple-equals
if (this.commentType == 1) {
this.commentService.currentComment.list.push(data.result);
} else {
this.commentService.currentLeaveMsg.list.push(data.result);
}
}
});
}
}

View File

@@ -0,0 +1,59 @@
<div class="admin-content" id="links-manager">
<div class="admin-content-body">
<div>
<strong class="part-title">友链管理</strong>
<button nz-button nzType="primary" nzGhost="true" style="margin-left: 30px;" (click)="add()">新增</button>
</div>
<div>
<div class=" scrollable-horizontal" *ngIf="linkService.currentPage">
<table class="table ">
<thead>
<tr>
<th>ID</th>
<th>友链名称</th>
<th>友链链接</th>
<th>状态</th>
<th>管理</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let link of linkService.currentPage.list">
<td>{{link.id}}</td>
<td class="text-truncate" style="max-width: 150px" [title]="link.name">{{link.name}}</td>
<td><a [href]="link.url" target="_blank">{{link.url}}</a></td>
<td><input type="checkbox" [checked]="link.open" disabled="disabled"></td>
<td>
<div class="btn-group">
<a (click)="edit(link)">编辑</a>
<nz-divider nzType="vertical"></nz-divider>
<a nz-popconfirm nzTitle="是否要删除这条友链?" (nzOnConfirm)="doDel(link.id)">删除</a>
</div>
</td>
</tr>
</tbody>
<nz-pagination align="center" [nzPageIndex]="pageNum" [nzHideOnSinglePage]="true"
[nzTotal]="linkService.currentPage.total" [nzPageSize]="pageSize"
(nzPageIndexChange)="toPage($event)"></nz-pagination>
</table>
</div>
</div>
</div>
</div>
<!-- 带输入框的弹出层 -->
<nz-modal [(nzVisible)]="showPupup" nzTitle="友链编辑" (nzOnCancel)="showPupup=!showPupup" (nzOnOk)="update()">
<label style="margin-left: 10%;">网站名称:</label>
<input nz-input style="width: 80%;margin-left: 10%" [(ngModel)]="updateReqBody.name">
<label style="margin-left: 10%;">网站链接:</label>
<input nz-input style="width: 80%;margin-left: 10%" [(ngModel)]="updateReqBody.url">
<label style="margin-left: 10%;">是否公开显示:</label>
<select [(ngModel)]="updateReqBody.open">
<option value="">请选择</option>
<option value="true">显示</option>
<option value="false">不显示</option>
</select>
</nz-modal>

View File

@@ -0,0 +1,25 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { LinksManagerComponent } from './links.component';
describe('LinksComponent', () => {
let component: LinksManagerComponent;
let fixture: ComponentFixture<LinksManagerComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [LinksManagerComponent]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(LinksManagerComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@@ -0,0 +1,104 @@
import {Component, OnInit} from '@angular/core';
import {NzMessageService} from 'ng-zorro-antd';
import {LinkService} from '../../services/link/link.service';
import {Link} from '../../classes/link';
@Component({
selector: 'app-links',
templateUrl: './links.component.html',
styleUrls: ['./links.component.css']
})
export class LinksManagerComponent implements OnInit {
constructor(public linkService: LinkService, private message: NzMessageService) {
}
pageNum: number = 1;
pageSize: number = 10;
showPupup = false;
updateReqBody = new Link();
isUpdate;
ngOnInit() {
this.getData();
}
getData() {
this.linkService.getLinks(this.pageNum, this.pageSize);
}
toPage(e: number) {
this.pageNum = e;
this.getData();
}
edit(link) {
this.showPupup = true;
this.updateReqBody = link;
this.isUpdate = true;
}
update() {
if (this.updateReqBody.name === '') {
this.message.warning('友链名称不能为空');
return;
}
if (this.updateReqBody.url === '') {
this.message.warning('友链链接不能为空');
return;
}
// @ts-ignore
// tslint:disable-next-line:triple-equals
if (this.updateReqBody.open == '') {
this.message.warning('友链状态不能为空');
return;
}
this.showPupup = false;
if (this.isUpdate) {
this.linkService.update(this.updateReqBody).subscribe(data => {
if (data.code === 0) {
this.message.success('更新成功');
this.getData();
} else {
this.message.error('更新失败,原因:' + data.msg);
}
this.updateReqBody.name = null;
this.updateReqBody.url = null;
this.updateReqBody.open = null;
});
} else {
this.linkService.create(this.updateReqBody).subscribe(data => {
if (data.code === 0) {
this.message.success('新增成功');
this.getData();
} else {
this.message.error('新增失败,原因:' + data.msg);
}
this.updateReqBody.name = null;
this.updateReqBody.url = null;
this.updateReqBody.open = null;
});
}
}
add() {
this.showPupup = true;
this.isUpdate = false;
}
doDel(id) {
this.linkService.delete(id).subscribe(data => {
if (data.code === 0) {
this.message.success('删除成功!');
this.getData();
} else {
this.message.error('删除失败,原因:' + data.msg);
}
});
}
}

View File

@@ -0,0 +1,11 @@
#publishArticle{
width: 100%;
height: 32px;
border-bottom-left-radius: 10px;
border-bottom-right-radius: 10px;
border: none;
background: turquoise;
color: white
}

View File

@@ -0,0 +1,68 @@
<!--标签-->
<div class="admin-content" id="tag-manager">
<div class="admin-content-body">
<div>
<div><strong class="part-title">标签管理</strong></div>
</div>
<div class="g">
<div class="scrollable-horizontal" *ngIf="tagService.currentTagPage">
<table class="table">
<thead>
<tr>
<th>ID</th>
<th>标签名称</th>
<th>标签文章</th>
<th>文章数目</th>
<th>管理</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let tag of tagService.currentTagPage.list">
<td>{{tag.id}}</td>
<td class="text-truncate" style="max-width: 150px" [title]="tag.name">{{tag.name}}</td>
<td>{{tag.articles}}</td>
<td><span class="badge badge-success">{{tag.articles.split(',').length - 1}}</span></td>
<td>
<a [href]="'../tag?name='+tag.name">
<i nz-icon nzType="tag" nzTheme="twotone"></i> 查看
</a>
<nz-divider nzType="vertical"></nz-divider>
<a nz-dropdown [nzDropdownMenu]="menu" nzPlacement="bottomLeft" nzTrigger="click">
更多 <i nz-icon nzType="down" nzTheme="outline"></i>
</a>
<nz-dropdown-menu #menu="nzDropdownMenu">
<ul nz-menu nzSelectable>
<li nz-menu-item>
<a (click)="edit(tag.id,tag.name)">编辑</a>
</li>
<li nz-menu-item>
<a nz-popconfirm nzTitle="是否要删除这条标签?" (nzOnConfirm)="doDel(tag.id)">删除</a>
</li>
</ul>
</nz-dropdown-menu>
</td>
</tr>
</tbody>
</table>
<nz-pagination align="center" [nzPageIndex]="pageNum" [nzHideOnSinglePage]="true"
[nzTotal]="tagService.currentTagPage.total" [nzPageSize]="pageSize"
(nzPageIndexChange)="toPage($event)"></nz-pagination>
</div>
</div>
</div>
</div>
<!-- 带输入框的弹出层 -->
<nz-modal [(nzVisible)]="showPupup" nzTitle="编辑" (nzOnCancel)="showPupup=!showPupup" (nzOnOk)="update()">
<input class="select" style="width: 80%;margin-left: 10%" [(ngModel)]="updateReqBody.name">
</nz-modal>

View File

@@ -0,0 +1,25 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { TagManagerComponent } from './tag-manager.component';
describe('TagManagerComponent', () => {
let component: TagManagerComponent;
let fixture: ComponentFixture<TagManagerComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ TagManagerComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(TagManagerComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@@ -0,0 +1,72 @@
import {Component, OnInit} from '@angular/core';
import {NzMessageService} from 'ng-zorro-antd';
import {TagService} from '../../services/tag/tag.service';
@Component({
selector: 'app-tag-manager',
templateUrl: './tag-manager.component.html',
styleUrls: ['./tag-manager.component.css']
})
export class TagManagerComponent implements OnInit {
constructor(public tagService: TagService, private message: NzMessageService) {
}
pageNum: number = 1;
pageSize: number = 10;
showPupup: boolean = false;
updateReqBody = {
id: null,
name: null
};
ngOnInit() {
this.getData();
}
getData() {
this.tagService.getTags(this.pageNum, this.pageSize);
}
toPage(e: number) {
this.pageNum = e;
this.getData();
}
edit(id, name) {
this.showPupup = true;
this.updateReqBody.id = id;
this.updateReqBody.name = name;
}
update() {
if (this.updateReqBody.name === '') {
this.message.warning('不能为空');
return;
}
this.showPupup = false;
this.tagService.update(this.updateReqBody.id, this.updateReqBody.name).subscribe(data => {
if (data.code === 0) {
this.message.success('修改成功!');
this.getData();
}
});
}
doDel(id) {
this.tagService.delete(id).subscribe(data => {
if (data.code === 0) {
this.message.success('删除成功');
this.getData();
} else {
this.message.error(`删除失败,原因:${data.msg}`);
}
});
}
}

View File

@@ -0,0 +1,54 @@
<div class="admin-content" id="tag-manager">
<div class="admin-content-body">
<div>
<strong class="part-title">更新管理</strong>
<button nz-button nzType="primary" nzGhost="true" style="margin-left: 30px;" (click)="add()">新增</button>
</div>
<div>
<div class=" scrollable-horizontal" *ngIf="updateService.updateInfoList">
<table class="table">
<thead>
<tr>
<th>ID</th>
<th>更新内容</th>
<th>更新日期</th>
<th>管理</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let update of updateService.updateInfoList.list">
<td>{{update.id}}</td>
<td style="max-width: 150px" nz-tooltip [nzTitle]="update.info">
{{update.info.length > 20 ? update.info.substr(0, 20) + '...' : update.info}}
</td>
<td>{{update.time}}</td>
<td>
<div class="btn-group">
<a (click)="edit(update)">编辑</a>
<nz-divider nzType="vertical"></nz-divider>
<a nz-popconfirm nzTitle="是否要删除这条更新?" (nzOnConfirm)="doDel(update.id)">删除</a>
</div>
</td>
</tr>
</tbody>
</table>
<nz-pagination align="center" [nzPageIndex]="pageNum" [nzHideOnSinglePage]="true"
[nzTotal]="updateService.updateInfoList.total"
[nzPageSize]="pageSize" (nzPageIndexChange)="toPage($event)"></nz-pagination>
</div>
</div>
</div>
</div>
<!-- 带输入框的弹出层 -->
<nz-modal [(nzVisible)]="showPupup" nzTitle="编辑" (nzOnCancel)="showPupup=!showPupup" (nzOnOk)="submit()">
<label style="margin-left: 10%;margin-bottom: 10px">更新内容:</label>
<textarea nz-input style="width: 80%;margin-left: 10%; height: 100px;"
[(ngModel)]="updateReqBody.info" placeholder="更新内容"
[nzAutosize]="{ minRows: 2, maxRows: 6 }"></textarea>
</nz-modal>

View File

@@ -0,0 +1,25 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { UpdateManagerComponent } from './update.component';
describe('UpdateComponent', () => {
let component: UpdateManagerComponent;
let fixture: ComponentFixture<UpdateManagerComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [UpdateManagerComponent]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(UpdateManagerComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@@ -0,0 +1,95 @@
import {Component, OnInit} from '@angular/core';
import {NzMessageService} from 'ng-zorro-antd';
import {WebUpdateService} from '../../services/update/web-update.service';
import {UpdateInfo} from "../../classes/updateInfo";
@Component({
selector: 'app-update',
templateUrl: './update.component.html',
styleUrls: ['./update.component.css']
})
export class UpdateManagerComponent implements OnInit {
constructor(public updateService: WebUpdateService, private message: NzMessageService) {
}
isUpdate = false;
pageNum: number = 1;
pageSize: number = 10;
showPupup = false;
updateReqBody = new UpdateInfo();
ngOnInit() {
this.getData();
}
getData() {
this.updateService.getUpdateInfo(this.pageNum, this.pageSize);
}
toPage(e: number) {
this.pageNum = e;
this.getData();
}
edit(link) {
this.showPupup = true;
this.updateReqBody = link;
this.isUpdate = true;
}
submit() {
if (this.updateReqBody.info === '') {
this.message.warning('更新内容不能为空');
return;
}
this.showPupup = false;
if (this.isUpdate) {
this.updateService.update(this.updateReqBody).subscribe(data => {
if (data.code === 0) {
this.message.success('更新成功');
this.getData();
} else {
this.message.error('更新失败,原因:' + data.msg);
}
});
} else {
this.updateReqBody.id = null;
this.updateService.create(this.updateReqBody.info).subscribe(data => {
if (data.code === 0) {
this.message.success('新增成功');
this.getData();
} else {
this.message.error('新增失败,原因:' + data.msg);
}
});
}
this.updateReqBody.id = null;
this.updateReqBody.info = '';
}
add() {
this.showPupup = true;
this.isUpdate = false;
this.updateReqBody.id = null;
this.updateReqBody.info = '';
}
doDel(id: number) {
this.updateService.delete(id).subscribe(data => {
if (data.code === 0) {
this.message.success('删除成功!');
this.getData();
} else {
this.message.error('删除失败,原因:' + data.msg);
}
});
}
}

View File

@@ -0,0 +1,78 @@
.label {
margin-bottom: 20px;
font-weight: bold;
font-size: 1.4em;
text-align: center;
}
table {
width: auto;
}
td {
border: none;
}
tr {
background: none;
}
input {
width: 200px;
border: none;
border-radius: 5px;
background: #eeeeee;
height: 30px;
padding-left: 5px;
}
#user-gender input {
width: auto;
height: auto;
margin-left: 10px;
}
.submit {
width: 80%;
margin-left: 10%;
}
#avatar {
position: absolute;
right: 20px;
top: 30%;
border: 1px solid #999999;
border-radius: 1px;
padding: 10px;
}
#avatarimg {
width: 100px;
height: 100px;
margin: 10px;
}
#info {
width: 350px;
position: relative;
top: 50%;
left: 50%;
transform: translate(-50%, 50%);
}
#info i {
margin-right: 10px;
}
#info .sendEmail {
position: absolute;
margin-top: 3px;
top: 0;
right: 15px;
}
#info input {
width: 90%;
margin-bottom: 10px;
height: 40px;
}

View File

@@ -0,0 +1,46 @@
<!--修改信息-->
<div class="admin-content" id="user-info">
<div class="admin-content-body">
<div>
<div><strong class="part-title">个人资料</strong> /
<small>Personal information</small>
</div>
</div>
<hr/>
<div id="info">
<i nz-icon nzType="mail" nzTheme="twotone"></i>
<input nz-input [(ngModel)]="user.email" style="display: inline" [disabled]="true"/>
<button *ngIf="!user.emailStatus" nz-button nzType="primary" class="sendEmail" (click)="sendEmail()"
[title]="'发生邮件到'+user.email+''" [disabled]="!clickable">
发送激活邮件
</button>
<br>
<i nz-icon nzType="info-circle" nzTheme="twotone"></i>
<input nz-input type="text" placeholder="用一句话来描述自己吧" name="desc" id="desc" [(ngModel)]="user.desc">
<br>
<i nz-icon nzType="crown" nzTheme="twotone"></i>
<input nz-input type="text" placeholder="昵称" name="displayName" id="displayName"
[(ngModel)]="user.displayName">
<br>
<button nz-button nzType="primary" nzGhost="true" [nzBlock]="true" (click)="userInfoSubmit()">提交</button>
</div>
<div id="avatar">
<h3><strong>头像</strong></h3>
<div>
<img id="avatarimg" [src]="user.avatarImgUrl" alt="avatar">
</div>
<div>
<nz-upload [nzAction]="host+'/user/imgUpload'" nzWithCredentials="true" nzLimit="1" nzSize="2048"
(nzChange)="avatarUpload($event)">
<button nz-button><i nz-icon nzType="upload"></i><span>选择图片上传</span></button>
</nz-upload>
</div>
</div>
</div>
</div>

View File

@@ -0,0 +1,25 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { UserInfoComponent } from './user-info.component';
describe('UserInfoComponent', () => {
let component: UserInfoComponent;
let fixture: ComponentFixture<UserInfoComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ UserInfoComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(UserInfoComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@@ -0,0 +1,74 @@
import {Component, OnInit} from '@angular/core';
import {NzMessageService} from 'ng-zorro-antd';
import {UserService} from '../../services/user/user.service';
import {User} from '../../classes/user';
import {environment} from '../../../environments/environment';
@Component({
selector: 'app-user-info',
templateUrl: './user-info.component.html',
styleUrls: ['./user-info.component.css']
})
export class UserInfoComponent implements OnInit {
constructor(public userService: UserService,
private message: NzMessageService) {
}
host: string;
user: User = new User();
clickable: boolean = true;
ngOnInit() {
if (!this.userService.userInfo) {
setTimeout(() => {
this.user = this.userService.userInfo;
}, 500);
} else {
this.user = this.userService.userInfo;
}
this.host = environment.host;
}
userInfoSubmit() {
const info = {
desc: this.user.desc,
displayName: this.user.displayName
};
this.userService.updateInfo(info).subscribe(data => {
if (data.code === 0) {
this.message.success('修改成功');
} else if (data.code === 301) {
window.location.href = '/login';
} else {
this.message.error('修改信息失败,原因:' + data.msg);
}
});
}
sendEmail() {
this.clickable = false;
if (!this.userService.userInfo) {
window.location.href = '/login';
}
this.userService.sendEmail().subscribe(data => {
if (data.code === 0) {
this.message.success('发送成功!请前往邮箱进行激活');
} else {
this.message.error(data.msg);
}
});
}
avatarUpload(info: any) {
if (info.type === 'success' && info.file.response.code === 0) {
const time = new Date().valueOf();
this.userService.userInfo.avatarImgUrl = this.userService.avatarHost + '/' + info.file.response.result;
// 加上时间戳 让图片自动预览,避免读取本地缓存而不显示新头像
this.user.avatarImgUrl = this.userService.avatarHost + '/' + info.file.response.result + '?time=' + time;
}
}
}

View File

@@ -0,0 +1,7 @@
.error {
padding-left: 20px;
color: red;
border: 1px solid #eb2f96;
border-radius: 2px;
display: block;
}

View File

@@ -0,0 +1,77 @@
<!--标签-->
<div class="admin-content" id="tag-manager">
<div class="admin-content-body">
<div>
<div><strong class="part-title">用户管理</strong></div>
</div>
<div class="g">
<div class="scrollable-horizontal" *ngIf="userService.currentUserPage">
<table class="table">
<thead>
<tr>
<th>ID</th>
<th>用户邮箱</th>
<th>用户昵称</th>
<th>用户角色</th>
<th>管理</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let user of userService.currentUserPage.list">
<td align="center">{{user.id}}</td>
<td align="center" class="text-truncate">{{user.email}}</td>
<td align="center">{{user.displayName}}</td>
<td align="center"><span class="badge badge-success">{{user.role}}</span></td>
<td>
<a (click)="edit(user)"><i nz-icon nzType="tag" nzTheme="twotone"></i> 编辑</a>
<nz-divider nzType="vertical"></nz-divider>
<a nz-popconfirm nzTitle="是否要删除这名用户?" (nzOnConfirm)="delete(user.id)">
<i nz-icon nzType="delete" nzTheme="twotone" nzTwotoneColor="#eb2f96"></i> 删除</a>
</td>
</tr>
</tbody>
</table>
<nz-pagination align="center" [nzPageIndex]="pageNum" [nzHideOnSinglePage]="true"
[nzTotal]="userService.currentUserPage.total" [nzPageSize]="pageSize"
(nzPageIndexChange)="toPage($event)"></nz-pagination>
</div>
</div>
</div>
</div>
<!--用户编辑-->
<nz-modal [(nzVisible)]="showPupup" nzTitle="编辑" (nzOnCancel)="showPupup=!showPupup" (nzOnOk)="update()">
<form action="#">
<label for="email">邮箱:</label>
<input nz-input type="email" id="email" name="email" [(ngModel)]="editUser.email" (blur)="getEmailStatus()">
<ng-template [ngIf]="showError">
<span class="error">
<i nz-icon nzType="exclamation-circle" nzTheme="twotone" nzTwotoneColor="#eb2f96"></i>
邮箱已被占用!
</span>
</ng-template>
<label for="display-name">昵称:</label>
<input nz-input type="text" id="display-name" name="display-name" [(ngModel)]="editUser.displayName">
<label for="pwd">密码:<span style="font-weight: lighter;font-size: smaller">留空则不重设密码,反之则设置为输入的密码</span></label>
<input nz-input type="password" id="pwd" name="pwd" [(ngModel)]="editUser.pwd" placeholder="******">
<label for="user-role">角色:</label>
<nz-select name="user-role" style="width: 100%" id="user-role"
[nzDisabled]="editUser.id==userService.userInfo.id" [(ngModel)]="editUser.role">
<nz-option nzValue="user" nzLabel="user"></nz-option>
<nz-option nzValue="admin" nzLabel="admin"></nz-option>
</nz-select>
<label for="email-status">邮箱验证状态:</label>
<br>
<nz-radio-group name="email-status" id="email-status" [(ngModel)]="editUser.emailStatus">
<label nz-radio [nzValue]="true">已验证</label>
<label nz-radio [nzValue]="false">未验证</label>
</nz-radio-group>
<br>
<label for="desc">描述:</label>
<textarea rows="4" id="desc" name="desc" nz-input [(ngModel)]="editUser.desc"></textarea>
</form>
</nz-modal>

View File

@@ -0,0 +1,25 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { UserManagerComponent } from './user-manager.component';
describe('UserManagerComponent', () => {
let component: UserManagerComponent;
let fixture: ComponentFixture<UserManagerComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ UserManagerComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(UserManagerComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@@ -0,0 +1,91 @@
import {Component, OnInit} from '@angular/core';
import {UserService} from '../../services/user/user.service';
import {User} from '../../classes/user';
import {NzMessageService} from 'ng-zorro-antd';
@Component({
selector: 'app-user-manager',
templateUrl: './user-manager.component.html',
styleUrls: ['./user-manager.component.css']
})
export class UserManagerComponent implements OnInit {
constructor(public userService: UserService,
private messageService: NzMessageService) {
}
pageNum: number = 1;
pageSize: number = 10;
showPupup: boolean = false;
editUser: User = new User();
showError: boolean = false;
formerEmail: string;
ngOnInit() {
this.userService.getPageUser(this.pageNum, this.pageSize);
}
toPage(e: number) {
this.pageNum = e;
this.userService.getPageUser(this.pageNum, this.pageSize);
}
edit(user: User) {
this.showPupup = true;
this.showError = false;
// 避免引用赋值采用json进行浅拷贝
this.editUser = JSON.parse(JSON.stringify(user));
this.formerEmail = this.editUser.email;
}
delete(id: number) {
this.userService.delete(id).subscribe(data => {
if (data.code === 0) {
if (data.result[0].status) {
this.messageService.success('删除成功!');
this.userService.getPageUser(this.pageNum, this.pageSize);
} else {
this.messageService.error(`删除失败,原因:${data.result[0].msg}`);
}
} else {
this.messageService.error(`请求失败,原因:${data.msg}`);
}
});
}
update() {
this.editUser.recentlyLandedDate = null;
this.editUser.avatarImgUrl = null;
if (this.showError) {
this.showPupup = false;
this.messageService.warning('邮箱不可用,请修改!');
return;
}
this.userService.update(this.editUser).subscribe(data => {
if (data.code === 0) {
this.messageService.success('修改成功!');
if (this.userService.userInfo.id === this.editUser.id) {
this.userService.userInfo = this.editUser;
}
this.userService.getPageUser(this.pageNum, this.pageSize, true);
} else {
this.messageService.error('修改失败!');
}
});
this.showPupup = false;
}
getEmailStatus() {
if (this.editUser.email === this.formerEmail) {
return;
}
this.userService.getExistOfEmail(this.editUser.email).subscribe(data => {
if (data.code === 0) {
this.showError = data.result;
} else {
this.messageService.error(data.msg);
}
});
}
}

View File

@@ -0,0 +1,49 @@
<!--访问量-->
<div class="admin-content" id="visitor-manager">
<div class="admin-content-body">
<div>
<div><strong class="part-title">访问管理</strong>
<span>---当日访问量{{visitorService.dayVisit}}</span>
</div>
</div>
<div class="g">
<div class="scrollable-horizontal" *ngIf="visitorService.currentPage">
<table class="table">
<thead>
<tr>
<th>ID</th>
<th>ip地址</th>
<th>访问日期</th>
<th>浏览器类型</th>
<th>系统</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let visitor of visitorService.currentPage.list">
<td>{{visitor.id}}</td>
<td>
<span (mouseenter)="getIp(visitor.ip)" [title]="location">{{visitor.ip}}</span>
<i nz-icon nzType="smile" nzTheme="twotone" nzTwotoneColor="#00DC25"
*ngIf="visitor.ip==localIp" style="float: right;clear: both" title="您的访问记录"></i>
</td>
<td>{{visitor.date}}</td>
<td style="text-align: center" [title]="visitor.browserVersion">
<span *ngIf="visitor.browserName!='Unknown'"> {{visitor.browserName}}</span>
</td>
<td>
<span *ngIf="visitor.osname!='Unknown' "> {{visitor.osname}}</span>
</td>
</tr>
</tbody>
</table>
<nz-pagination align="center " [nzPageIndex]="pageNum " [nzHideOnSinglePage]="true "
[nzTotal]="visitorService.currentPage.total " [nzPageSize]="pageSize "
(nzPageIndexChange)="toPage($event) "></nz-pagination>
</div>
</div>
</div>
</div>

View File

@@ -0,0 +1,25 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { VisitorManagerComponent } from './visitor-manager.component';
describe('VisitorManagerComponent', () => {
let component: VisitorManagerComponent;
let fixture: ComponentFixture<VisitorManagerComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ VisitorManagerComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(VisitorManagerComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@@ -0,0 +1,58 @@
import {Component, OnInit} from '@angular/core';
import {VisitorService} from '../../services/visitor/visitor.service';
@Component({
selector: 'app-visitor-manager',
templateUrl: './visitor-manager.component.html',
styleUrls: ['./visitor-manager.component.css']
})
export class VisitorManagerComponent implements OnInit {
constructor(public visitorService: VisitorService) {
}
pageNum: number = 1;
pageSize: number = 10;
localIp = '';
location: string;
ngOnInit() {
this.getPageData();
this.visitorService.getDayVisitor();
this.visitorService.getLocalIp().subscribe(data => {
this.localIp = data.result;
});
}
getIp(ip) {
const result = this.visitorService.getIp(ip);
if (typeof result === 'string') {
this.location = result;
return;
}
result.subscribe(data => {
if (data.code === 0) {
this.location = data.result;
}
});
}
getPageData() {
this.visitorService.getVisitor(this.pageNum, this.pageSize);
}
toPage(e) {
this.pageNum = e;
this.getPageData();
}
}