增加公告添加/删除接口

change
panqihua 4 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. 83
      src/app/forum/forum.component.html
  5. 9
      src/app/forum/forum.component.scss
  6. 45
      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"/>
<select class="custom-select" formControlName="emailType">
<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>

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

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

@ -1,47 +1,66 @@
<!--公告轮播-->
<ng-container *ngIf="notices;else fff">
<div id="carouselExampleControls" class="carousel slide bg-info m-3" data-ride="carousel">
<div class="carousel-inner">
<ng-container *ngFor="let notice of notices;first as isFirst">
<div class="carousel-item" [class.active]="isFirst" >
<!--公告栏-->
<div class="notice bg-light col-5 mx-auto">
<!-- 公告标志-->
<h1 class="text-center mb-3">{{ 'forum.notice' | translate }}</h1>
<!-- 公告内容-->
<div class="notice-content border-success mt-3 mb-3 position-relative">
<!-- 公告标题-->
<h2 class="text-center mb-3 mt-3">{{notice.title}}</h2>
<!-- 公告正文-->
<div class="notice-body overflow-auto p-3">
{{notice.content}}
<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 class="carousel-inner">
<ng-container *ngFor="let notice of notices;first as isFirst">
<div class="carousel-item" [class.active]="isFirst">
<!--公告栏-->
<div class="notice bg-light col-5 mx-auto">
<!-- 公告标志-->
<div class="">
<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-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="notice-content border-success mt-3 mb-3 position-relative">
<!-- 公告标题-->
<h2 class="text-center mb-3 mt-3">{{notice.title}}</h2>
<!-- 公告正文-->
<div class="notice-body overflow-auto p-3">
{{notice.content}}
</div>
<!-- 公告底部-->
<div class="notice-footer border border-info text-right align-text-bottom position-absolute">
<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>
</ng-container>
</ng-container>
</div>
<a class="carousel-control-prev" href="#carouselExampleControls" role="button" data-slide="prev">
<span class="carousel-control-prev-icon" aria-hidden="true"></span>
<span class="sr-only">Previous</span>
</a>
<a class="carousel-control-next" href="#carouselExampleControls" role="button" data-slide="next">
<span class="carousel-control-next-icon" aria-hidden="true"></span>
<span class="sr-only">Next</span>
</a>
</div>
<a class="carousel-control-prev" href="#carouselExampleControls" role="button" data-slide="prev">
<span class="carousel-control-prev-icon" aria-hidden="true"></span>
<span class="sr-only">Previous</span>
</a>
<a class="carousel-control-next" href="#carouselExampleControls" role="button" data-slide="next">
<span class="carousel-control-next-icon" aria-hidden="true"></span>
<span class="sr-only">Next</span>
</a>
</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-template #fff>
<ng-template #load_notice_err>
<div class="text-center">
<div class="spinner-border load" role="status">
<span class="sr-only">Loading...</span>
</div>
<h1>{{'forum.load_notices'|translate}}</h1>
<h1>{{loadNoticesStatus|translate}}</h1>
</div>
</ng-template>

@ -102,10 +102,17 @@
}
//加载进度
.load{
.load {
width: 5rem;
height: 5rem;
}
//投诉帖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 {Active, Complaint, Forum} from '../interface/ForumType';
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',
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;
loadNoticesStatus = this.prefix('load_notices');
constructor(
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() {
this.forumService.getAllNotices().subscribe(res => {
this.noticeService.getAllNotices().subscribe(res => {
this.loadNoticesStatus = this.prefix(res.message);
if (res.result === Result.OK) {
console.debug('获取公告信息成功');
this.notices = res.body;
this.notices = res.noticeList;
}
});
}
@ -67,18 +74,29 @@ 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';
});
}
});
}
/**
*
*/
checkPost(status) {
this.forumService.checkPost(this.posts.list[this.currentIndex].id, status).subscribe(res => {
if (res.result === Result.OK) {
this.posts.list.splice(this.currentIndex, 1);
} else {
alert('审核操作失败,请重试');
}
});
this.forumService.checkPost(this.posts.list[this.currentIndex].id, status).subscribe(res => {
if (res.result === Result.OK) {
this.posts.list.splice(this.currentIndex, 1);
} else {
alert('审核操作失败,请重试');
}
});
}
ngOnInit(): void {
@ -86,4 +104,7 @@ export class ForumComponent implements OnInit {
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 {JSONResponse} from '../interface/JSONResponse';
import {HttpInterface} from '../interface/HttpInterface';
@ -20,17 +20,6 @@ export class ForumService extends JSONRequest {
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 {TranslateModule} from '@ngx-translate/core';
import {RouterModule} from '@angular/router';
/**
@ -15,7 +16,8 @@ import {TranslateModule} from '@ngx-translate/core';
],
imports: [
CommonModule,
TranslateModule
TranslateModule,
RouterModule
]
})
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',
// 审核帖子
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)) {

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

@ -1,6 +1,7 @@
import {Result} from './Result';
import {Token} from './Token';
import {EmailType} from './EmailType';
import {Notice} from './Notice';
export interface Response {
// 响应结果
@ -40,3 +41,8 @@ export interface EmailTypeResponse 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() {
this.messageService.message = null;
}

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

Loading…
Cancel
Save