增加公告添加/删除接口

change
panqihua 5 years ago
parent 93c75399a4
commit f5530d4259
  1. 2
      src/app/account/register/register.component.html
  2. 5
      src/app/app-routing.module.ts
  3. 4
      src/app/app.module.ts
  4. 31
      src/app/forum/forum.component.html
  5. 9
      src/app/forum/forum.component.scss
  6. 31
      src/app/forum/forum.component.ts
  7. 13
      src/app/forum/forum.service.ts
  8. 4
      src/app/forum/forum/forum.module.ts
  9. 39
      src/app/forum/notice/notice.component.html
  10. 0
      src/app/forum/notice/notice.component.scss
  11. 25
      src/app/forum/notice/notice.component.spec.ts
  12. 67
      src/app/forum/notice/notice.component.ts
  13. 16
      src/app/forum/notice/notice.service.spec.ts
  14. 53
      src/app/forum/notice/notice.service.ts
  15. 6
      src/app/interface/HttpInterface.ts
  16. 6
      src/app/interface/Notice.ts
  17. 6
      src/app/interface/Response.ts
  18. 7
      src/app/message/message.service.ts
  19. 21
      src/assets/i18n/en-US.json
  20. 21
      src/assets/i18n/zh-CN.json

@ -78,7 +78,7 @@
[class.is-invalid]="getValue('email').invalid"/> [class.is-invalid]="getValue('email').invalid"/>
<select class="custom-select" formControlName="emailType"> <select class="custom-select" formControlName="emailType">
<option value="">{{'tip.select'|translate:{value: 'register.email_type'|translate} }}</option> <option value="">{{'tip.select'|translate:{value: 'register.email_type'|translate} }}</option>
<option *ngFor="let item of (emailType$|async)?.body" [value]="item.suffix">{{item.name}}</option> <option *ngFor="let item of (emailType$|async)?.emailTypeList" [value]="item.suffix">{{item.name}}</option>
</select> </select>

@ -4,6 +4,7 @@ import {LoginComponent} from './account/login/login.component';
import {RegisterComponent} from './account/register/register.component'; import {RegisterComponent} from './account/register/register.component';
import {ResetpwdComponent} from './account/resetpwd/resetpwd.component'; import {ResetpwdComponent} from './account/resetpwd/resetpwd.component';
import {ForumComponent} from './forum/forum.component'; import {ForumComponent} from './forum/forum.component';
import {NoticeComponent} from './forum/notice/notice.component';
// 路由配置 // 路由配置
export const routes: Routes = [ export const routes: Routes = [
@ -13,8 +14,10 @@ export const routes: Routes = [
{path: 'register', component: RegisterComponent}, {path: 'register', component: RegisterComponent},
// 重置密码 // 重置密码
{path: 'reset_pwd', component: ResetpwdComponent}, {path: 'reset_pwd', component: ResetpwdComponent},
// 论坛管理' // 论坛管理
{path: 'forum', component: ForumComponent}, {path: 'forum', component: ForumComponent},
// 公告管理
{path: 'notice', component: NoticeComponent},
// 自动重定向到登陆 // 自动重定向到登陆
{path: '', redirectTo: 'login', pathMatch: 'full'} {path: '', redirectTo: 'login', pathMatch: 'full'}
]; ];

@ -20,6 +20,7 @@ import {ForumModule} from './forum/forum/forum.module';
// Http请求模块 // Http请求模块
import {HttpClient, HttpClientModule} from '@angular/common/http'; import {HttpClient, HttpClientModule} from '@angular/common/http';
import {HtmlPipe} from './html.pipe'; import {HtmlPipe} from './html.pipe';
import {NoticeComponent} from './forum/notice/notice.component';
export function HttpLoaderFactory(http: HttpClient) { export function HttpLoaderFactory(http: HttpClient) {
return new TranslateHttpLoader(http); return new TranslateHttpLoader(http);
@ -32,7 +33,8 @@ export function HttpLoaderFactory(http: HttpClient) {
declarations: [ declarations: [
AppComponent, AppComponent,
ErrorComponent, ErrorComponent,
HtmlPipe HtmlPipe,
NoticeComponent
], ],
imports: [ imports: [
BrowserModule, BrowserModule,

@ -1,14 +1,28 @@
<!--公告轮播--> <!--公告轮播-->
<ng-container *ngIf="notices;else fff"> <ng-container *ngIf="notices;else load_notice_err">
<h1 *ngIf="notices.length==0;else notice_temp"
class="text-center col-12 m-3">{{'server.forum.notice.zero'|translate}}</h1>
<ng-template #notice_temp>
<div id="carouselExampleControls" class="carousel slide bg-info m-3" data-ride="carousel"> <div id="carouselExampleControls" class="carousel slide bg-info m-3" data-ride="carousel">
<div class="carousel-inner"> <div class="carousel-inner">
<ng-container *ngFor="let notice of notices;first as isFirst"> <ng-container *ngFor="let notice of notices;first as isFirst">
<div class="carousel-item" [class.active]="isFirst" > <div class="carousel-item" [class.active]="isFirst">
<!--公告栏--> <!--公告栏-->
<div class="notice bg-light col-5 mx-auto"> <div class="notice bg-light col-5 mx-auto">
<!-- 公告标志--> <!-- 公告标志-->
<div class="">
<h1 class="text-center mb-3">{{ 'forum.notice' | translate }}</h1> <h1 class="text-center mb-3">{{ 'forum.notice' | translate }}</h1>
<button [title]="this.prefix('delete')|translate" (click)="deleteNotice(notice.id)"
class="position-absolute delete_notice btn btn-outline-danger">
<svg t="1586720093778" class="icon" viewBox="0 0 1024 1024"
xmlns="http://www.w3.org/2000/svg" width="50" height="50">
<path
d="M810.666667 273.493333L750.506667 213.333333 512 451.84 273.493333 213.333333 213.333333 273.493333 451.84 512 213.333333 750.506667 273.493333 810.666667 512 572.16 750.506667 810.666667 810.666667 750.506667 572.16 512z"
>
</path>
</svg>
</button>
</div>
<!-- 公告内容--> <!-- 公告内容-->
<div class="notice-content border-success mt-3 mb-3 position-relative"> <div class="notice-content border-success mt-3 mb-3 position-relative">
<!-- 公告标题--> <!-- 公告标题-->
@ -19,7 +33,8 @@
</div> </div>
<!-- 公告底部--> <!-- 公告底部-->
<div class="notice-footer border border-info text-right align-text-bottom position-absolute"> <div class="notice-footer border border-info text-right align-text-bottom position-absolute">
<div class="col-12">{{ 'forum.sender' | translate }} :{{notice.managerName}}<br>{{ 'forum.time' | translate }}:{{notice.createTime|date:'yyyy-MM-dd HH:mm:ss'}}</div> <div class="col-12">{{ 'forum.sender' | translate }} :{{notice.author}}
<br>{{ 'forum.time' | translate }}:{{notice.time|date:'yyyy-MM-dd HH:mm:ss'}}</div>
</div> </div>
</div> </div>
</div> </div>
@ -35,13 +50,17 @@
<span class="sr-only">Next</span> <span class="sr-only">Next</span>
</a> </a>
</div> </div>
</ng-template>
<div class="col-7 mx-auto text-center mb-3">
<button routerLink="/notice" class="btn btn-outline-info">添加更多公告</button>
</div>
</ng-container> </ng-container>
<ng-template #fff> <ng-template #load_notice_err>
<div class="text-center"> <div class="text-center">
<div class="spinner-border load" role="status"> <div class="spinner-border load" role="status">
<span class="sr-only">Loading...</span> <span class="sr-only">Loading...</span>
</div> </div>
<h1>{{'forum.load_notices'|translate}}</h1> <h1>{{loadNoticesStatus|translate}}</h1>
</div> </div>
</ng-template> </ng-template>

@ -102,10 +102,17 @@
} }
//加载进度 //加载进度
.load{ .load {
width: 5rem; width: 5rem;
height: 5rem; height: 5rem;
} }
//投诉帖end //投诉帖end
//删除公告图标
.delete_notice {
z-index: 1;
right: 17px;
top: 67px;
}

@ -4,6 +4,9 @@ import {ForumService} from './forum.service';
import {Result} from '../interface/Result'; import {Result} from '../interface/Result';
import {Active, Complaint, Forum} from '../interface/ForumType'; import {Active, Complaint, Forum} from '../interface/ForumType';
import {Notice} from '../interface/Notice'; import {Notice} from '../interface/Notice';
import {MessageInterface, MessageUtil} from '../message/message.service';
import {NoticeService} from './notice/notice.service';
import {TranslateService} from '@ngx-translate/core';
/** /**
* *
@ -13,7 +16,7 @@ import {Notice} from '../interface/Notice';
templateUrl: './forum.component.html', templateUrl: './forum.component.html',
styleUrls: ['./forum.component.scss'] styleUrls: ['./forum.component.scss']
}) })
export class ForumComponent implements OnInit { export class ForumComponent implements OnInit, MessageInterface {
/** /**
* *
@ -27,10 +30,14 @@ export class ForumComponent implements OnInit {
// 激活帖子索引 // 激活帖子索引
currentIndex = 0; currentIndex = 0;
loadNoticesStatus = this.prefix('load_notices');
constructor( constructor(
private router: Router, private router: Router,
private forumService: ForumService private forumService: ForumService,
private noticeService: NoticeService,
private messageUtil: MessageUtil,
private translate: TranslateService
) { ) {
} }
@ -46,10 +53,10 @@ export class ForumComponent implements OnInit {
* *
*/ */
getAllNotices() { getAllNotices() {
this.forumService.getAllNotices().subscribe(res => { this.noticeService.getAllNotices().subscribe(res => {
this.loadNoticesStatus = this.prefix(res.message);
if (res.result === Result.OK) { if (res.result === Result.OK) {
console.debug('获取公告信息成功'); this.notices = res.noticeList;
this.notices = res.body;
} }
}); });
} }
@ -67,6 +74,17 @@ export class ForumComponent implements OnInit {
}); });
} }
// 删除公告
deleteNotice(noticeId) {
this.translate.get(this.prefix('confirm_delete')).subscribe(r => {
if (confirm(r)) {
this.noticeService.deleteNotice({id: noticeId}).subscribe(res => {
this.messageUtil.alert(this.prefix(res.message));
location.href = '/forum';
});
}
});
}
/** /**
* *
@ -86,4 +104,7 @@ export class ForumComponent implements OnInit {
this.getAllPosts(1); this.getAllPosts(1);
} }
prefix(key: string): string {
return 'server.forum.notice.' + key;
}
} }

@ -1,4 +1,4 @@
import { Injectable } from '@angular/core'; import {Injectable} from '@angular/core';
import {HttpClient} from '@angular/common/http'; import {HttpClient} from '@angular/common/http';
import {JSONResponse} from '../interface/JSONResponse'; import {JSONResponse} from '../interface/JSONResponse';
import {HttpInterface} from '../interface/HttpInterface'; import {HttpInterface} from '../interface/HttpInterface';
@ -20,17 +20,6 @@ export class ForumService extends JSONRequest {
super(); super();
} }
/**
*
*/
getAllNotices(): Observable<JSONResponse<any>> {
return this.http.get<JSONResponse<any>>(HttpInterface.getAllNotices, this.httpOptions)
.pipe(
catchError(this.handleError<any>('获取公告信息'))
);
}
/** /**
* *
*/ */

@ -3,6 +3,7 @@ import {CommonModule} from '@angular/common';
// 论坛组件 // 论坛组件
import {ForumComponent} from '../forum.component'; import {ForumComponent} from '../forum.component';
import {TranslateModule} from '@ngx-translate/core'; import {TranslateModule} from '@ngx-translate/core';
import {RouterModule} from '@angular/router';
/** /**
@ -15,7 +16,8 @@ import {TranslateModule} from '@ngx-translate/core';
], ],
imports: [ imports: [
CommonModule, CommonModule,
TranslateModule TranslateModule,
RouterModule
] ]
}) })
export class ForumModule { export class ForumModule {

@ -0,0 +1,39 @@
<!--设置高度,添加bootstrap样式类d-flex align-items-center 使表单垂直居中,justify-content-center水平居中-->
<div [style]="height" class="d-flex align-items-center justify-content-center">
<form [formGroup]="noticeForm" class="col-6">
<!-- 公告标题-->
<div class="input-group mb-3 mx-auto col-7">
<div class="input-group-prepend">
<span class="input-group-text">{{ 'forum.notice_title' | translate }}</span>
</div>
<input type="text" class="form-control text-center" [class.is-invalid]="getValue('title').invalid"
[placeholder]="'tip.input' | translate:{value:'forum.notice_title'|translate}"
formControlName="title"/>
<div class="invalid-feedback font-weight-bold text-center">
{{'tip.notnull' | translate:{value: 'forum.notice_title'|translate} }}
</div>
</div>
<!-- 公告内容-->
<div class="input-group mb-3 mx-auto col-7">
<div class="input-group-prepend">
<span class="input-group-text">{{ 'forum.notice_title' | translate }}</span>
</div>
<textarea class="form-control" [class.is-invalid]="getValue('content').invalid"
[placeholder]="'tip.input' | translate:{value:'forum.notice_content'|translate}"
formControlName="content"></textarea>
<div class="invalid-feedback font-weight-bold text-center">
{{'tip.notnull' | translate:{value: 'forum.notice_content'|translate} }}
</div>
</div>
<div class="col-7 mx-auto text-center mb-3">
<!-- 提交按钮-->
<button type="button" (click)="addNotice()" [disabled]="form().invalid"
class="btn btn-primary btn-lg">{{ 'button.notice' | translate }}</button>
<!-- 返回论坛主界面-->
<button type="button" [routerLink]="['/forum']"
class="btn btn-info btn-lg ml-3">{{ 'button.back' | translate }}</button>
</div>
</form>
</div>

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

@ -0,0 +1,67 @@
import {Component, OnInit} from '@angular/core';
import {Commons} from '../../commons';
import {FormBuilder, FormGroup, Validators} from '@angular/forms';
import {NoticeService} from './notice.service';
import {Result} from '../../interface/Result';
import {MessageInterface, MessageUtil} from '../../message/message.service';
import {CookieService} from 'ngx-cookie-service';
import {environment} from '../../../environments/environment';
@Component({
selector: 'app-notice',
templateUrl: './notice.component.html',
styleUrls: ['./notice.component.scss']
})
export class NoticeComponent extends Commons implements OnInit, MessageInterface {
// 公告表单
noticeForm = this.fb.group({
// 公告标题
title: this.fb.control('', [Validators.required]),
// 公告内容
content: this.fb.control('', [Validators.required])
});
managerName = '';
constructor(
private fb: FormBuilder,
private noticeService: NoticeService,
private messageUtil: MessageUtil,
private cookieService: CookieService
) {
super();
}
// 添加公告
addNotice() {
this.noticeService.addNotice(Object.assign(
this.noticeForm.value, {author: this.cookieService.get(environment.managerKey)}
)).subscribe(res => {
if (res.result === Result.OK) {
location.href = '/forum';
} else {
this.messageUtil.danger(res.message);
}
});
}
ngOnInit(): void {
this.validForm = {};
for (const key of Object.keys(this.noticeForm.value)) {
this.validForm[key] = {
flag: false
};
}
}
form(): FormGroup {
return this.noticeForm;
}
prefix(key: string): string {
return 'server.forum.notice.';
}
}

@ -0,0 +1,16 @@
import {TestBed} from '@angular/core/testing';
import {NoticeService} from './notice.service';
describe('NoticeService', () => {
let service: NoticeService;
beforeEach(() => {
TestBed.configureTestingModule({});
service = TestBed.inject(NoticeService);
});
it('should be created', () => {
expect(service).toBeTruthy();
});
});

@ -0,0 +1,53 @@
import {Injectable} from '@angular/core';
import {JSONRequest} from '../../interface/JSONRequest';
import {HttpClient} from '@angular/common/http';
import {Observable} from 'rxjs';
import {ForumNoticeResponse} from '../../interface/Response';
import {HttpInterface} from '../../interface/HttpInterface';
import {catchError} from 'rxjs/operators';
@Injectable({
providedIn: 'root'
})
/**
*
*/
export class NoticeService extends JSONRequest {
constructor(
private http: HttpClient
) {
super();
}
/**
*
*/
getAllNotices(): Observable<ForumNoticeResponse> {
return this.http.get<ForumNoticeResponse>(HttpInterface.getAllNotices, this.httpOptions)
.pipe(
catchError(this.handleError<any>('获取公告信息'))
);
}
/**
*
*/
addNotice(body): Observable<ForumNoticeResponse> {
return this.http.post<ForumNoticeResponse>(HttpInterface.addNotice, body, this.httpOptions)
.pipe(
catchError(this.handleError<any>('添加公告'))
);
}
/**
*
*/
deleteNotice(body): Observable<ForumNoticeResponse> {
return this.http.post<ForumNoticeResponse>(HttpInterface.deleteNotice, body, this.httpOptions)
.pipe(
catchError(this.handleError<any>('添加公告'))
);
}
}

@ -23,7 +23,11 @@ const HttpInterface = {
// 获取所有帖子 // 获取所有帖子
getAllPosts: '/api/forum/posts', getAllPosts: '/api/forum/posts',
// 审核帖子 // 审核帖子
checkPost: '/api/forum/posts' checkPost: '/api/forum/posts',
// 添加公告
addNotice: '/api/forum/notice/add',
// 删除公告
deleteNotice: '/api/forum/notice/delete'
}; };
for (const key of Object.keys(HttpInterface)) { for (const key of Object.keys(HttpInterface)) {

@ -1,10 +1,12 @@
export interface Notice { export interface Notice {
// 公告id
id: number;
// 公告人 // 公告人
managerName: string; author: string;
// 公告内容 // 公告内容
content: string; content: string;
// 公告标题 // 公告标题
title: string; title: string;
// 公告时间 // 公告时间
createTime: number; time: number;
} }

@ -1,6 +1,7 @@
import {Result} from './Result'; import {Result} from './Result';
import {Token} from './Token'; import {Token} from './Token';
import {EmailType} from './EmailType'; import {EmailType} from './EmailType';
import {Notice} from './Notice';
export interface Response { export interface Response {
// 响应结果 // 响应结果
@ -40,3 +41,8 @@ export interface EmailTypeResponse extends Response {
export interface ResetpwdResponse extends Response { export interface ResetpwdResponse extends Response {
} }
// 公告信息响应
export interface ForumNoticeResponse extends Response {
noticeList: Array<Notice>;
}

@ -70,6 +70,13 @@ export class MessageUtil {
}); });
} }
// tslint:disable-next-line:ban-types
alert(key: string | Array<string>, interpolateParams?: Object) {
this.translate.get(key, interpolateParams).subscribe(s => {
alert(s);
});
}
reset() { reset() {
this.messageService.message = null; this.messageService.message = null;
} }

@ -31,8 +31,9 @@
"complaint": "time:{{time}}", "complaint": "time:{{time}}",
"plaintiff": "plaintiff", "plaintiff": "plaintiff",
"defendant": "defendant", "defendant": "defendant",
"load_notices": "Loading advertising information", "load_posts": "Loading posts",
"load_posts": "Loading posts" "notice_title": "notice title",
"notice_content": "notice content"
}, },
"tip":{ "tip":{
"input": "please input {{value}}", "input": "please input {{value}}",
@ -54,7 +55,9 @@
"prev": "prev", "prev": "prev",
"next_page": "Next", "next_page": "Next",
"prev_page": "Previous", "prev_page": "Previous",
"check_code": "check_code" "check_code": "check_code",
"notice": "submit",
"back": "back"
}, },
"server": { "server": {
"login": { "login": {
@ -86,6 +89,18 @@
"valid_code_fail": "验证码不正确,请重新输入", "valid_code_fail": "验证码不正确,请重新输入",
"resetpwd_ok": "重置密码成功", "resetpwd_ok": "重置密码成功",
"resetpwd_fail": "重置密码失败" "resetpwd_fail": "重置密码失败"
},
"forum": {
"notice": {
"load_notices": "Loading advertising information",
"ok": "获取公告信息成功",
"fail": "获取公告信息失败",
"zero": "没有任何公告信息",
"delete": "删除公告信息",
"confirm_delete": "确认删除当前公告信息吗?",
"delete_ok": "删除成功",
"delete_fail": "删除失败"
}
} }
} }
} }

@ -31,8 +31,9 @@
"complaint_time": "投诉时间:{{time}}", "complaint_time": "投诉时间:{{time}}",
"plaintiff": "投诉人", "plaintiff": "投诉人",
"defendant": "被投诉人", "defendant": "被投诉人",
"load_notices": "正在加载广告信息", "load_posts": " 正在加载帖子信息",
"load_posts": " 正在加载帖子信息" "notice_title": "公告标题",
"notice_content": "公告内容"
}, },
"tip":{ "tip":{
"input": "请输入{{value}}", "input": "请输入{{value}}",
@ -54,7 +55,9 @@
"prev": "上一步", "prev": "上一步",
"next_page": "下一页", "next_page": "下一页",
"prev_page": "上一页", "prev_page": "上一页",
"check_code": "检查验证码" "check_code": "检查验证码",
"notice": "添加公告",
"back": "返回"
}, },
"server": { "server": {
"login": { "login": {
@ -86,6 +89,18 @@
"valid_code_fail": "验证码不正确,请重新输入", "valid_code_fail": "验证码不正确,请重新输入",
"resetpwd_ok": "重置密码成功", "resetpwd_ok": "重置密码成功",
"resetpwd_fail": "重置密码失败" "resetpwd_fail": "重置密码失败"
},
"forum": {
"notice": {
"load_notices": "正在加载广告信息",
"ok": "获取公告信息成功",
"fail": "获取公告信息失败",
"zero": "没有任何公告信息",
"delete": "删除公告信息",
"confirm_delete": "确认删除当前公告信息吗?",
"delete_ok": "删除成功",
"delete_fail": "删除失败"
}
} }
} }
} }

Loading…
Cancel
Save