论坛模块增加公告接口

论坛模块增加帖子接口
change
panqihua 5 years ago
parent cadf5204fe
commit 82598c2bb5
  1. 29
      src/app/account/login/login.component.ts
  2. 64
      src/app/account/login/login.service.ts
  3. 2
      src/app/account/register/register.component.html
  4. 24
      src/app/app.component.ts
  5. 149
      src/app/forum/forum.component.html
  6. 10
      src/app/forum/forum.component.scss
  7. 57
      src/app/forum/forum.component.ts
  8. 16
      src/app/forum/forum.service.spec.ts
  9. 53
      src/app/forum/forum.service.ts
  10. 66
      src/app/interface/ForumType.ts
  11. 6
      src/app/interface/HttpInterface.ts
  12. 10
      src/app/interface/Notice.ts
  13. 1
      src/app/interface/Result.ts
  14. 7
      src/assets/i18n/en-US.json
  15. 6
      src/assets/i18n/zh-CN.json

@ -3,6 +3,10 @@ import {FormBuilder, FormGroup, Validators} from '@angular/forms';
import {Commons} from '../../commons';
import {Router} from '@angular/router';
import {LoginService} from './login.service';
import {Result} from '../../interface/Result';
import {environment} from '../../../environments/environment';
import {CookieService} from 'ngx-cookie-service';
import {MessageService} from '../../message/message.service';
@Component({
selector: 'app-login',
@ -20,7 +24,13 @@ export class LoginComponent extends Commons implements OnInit {
});
constructor(private fb: FormBuilder, private router: Router, private loginService: LoginService) {
constructor(private fb: FormBuilder,
private router: Router,
private loginService: LoginService,
private cookieService: CookieService,
private messageService: MessageService
) {
super();
}
@ -33,11 +43,18 @@ export class LoginComponent extends Commons implements OnInit {
console.debug(this.loginForm.value);
// 发送登陆请求
if (this.loginService.checkToken()) {
this.router.navigateByUrl('/forum');
} else {
this.loginService.request(JSON.stringify(this.loginForm.value));
}
this.loginService.login(JSON.stringify(this.loginForm.value)).subscribe(r => {
if (r.result === Result.OK) {
this.messageService.info('登陆成功');
const time = new Date();
time.setTime(r.body.useTime);
this.cookieService.set(environment.managerKey, r.body.managerName, time);
this.cookieService.set(environment.tokenKey, r.body.token, time);
this.router.navigateByUrl('/forum');
} else {
this.messageService.danger('登陆失败');
}
});
}

@ -1,15 +1,10 @@
import {Injectable} from '@angular/core';
import {CookieService} from 'ngx-cookie-service';
import {Router} from '@angular/router';
import {MessageService} from '../../message/message.service';
import {JSONRequest} from '../../interface/JSONRequest';
import {environment} from '../../../environments/environment';
import {HttpClient} from '@angular/common/http';
import {HttpInterface} from '../../interface/HttpInterface';
import {JSONResponse} from '../../interface/JSONResponse';
import {catchError} from 'rxjs/operators';
import {Result} from '../../interface/Result';
import {Token} from '../../interface/vo/Token';
import {Observable} from 'rxjs';
@Injectable({
providedIn: 'root'
@ -17,71 +12,28 @@ import {Token} from '../../interface/vo/Token';
export class LoginService extends JSONRequest {
constructor(
private cookieService: CookieService,
private router: Router,
private messageService: MessageService,
private http: HttpClient,
) {
super();
}
/**
*
*/
checkToken(): boolean {
return this.cookieService.check(environment.tokenKey);
}
/**
*
*/
login(body: string) {
if (this.checkToken()) {
this.router.navigateByUrl('/forum');
} else {
this.request(body);
}
}
/**
*
*/
logout() {
this.http.post<JSONResponse<any>>(HttpInterface.logout, {}, this.httpOptions)
logout(): Observable<JSONResponse<any>> {
return this.http.post<JSONResponse<any>>(HttpInterface.logout, {}, this.httpOptions)
.pipe(
catchError(this.handleError<any>('注销'))
)
.subscribe(r => {
if (r.result === Result.OK) {
this.cookieService.deleteAll();
this.messageService.info('注销成功');
this.router.navigateByUrl('/login');
} else {
alert('注销失败');
}
});
);
}
/**
*
* @param body
*
*/
request(body) {
this.http.post<JSONResponse<Token>>(HttpInterface.login, body, this.httpOptions)
login(body): Observable<JSONResponse<any>> {
return this.http.post<JSONResponse<any>>(HttpInterface.login, body, this.httpOptions)
.pipe(
catchError(this.handleError<any>('登陆'))
)
.subscribe(r => {
if (r.result === Result.OK) {
this.messageService.info('登陆成功');
const time = new Date();
time.setTime(r.body.useTime);
this.cookieService.set(environment.managerKey, r.body.managerName, time);
this.cookieService.set(environment.tokenKey, r.body.token, time);
this.router.navigateByUrl('/forum');
} else {
this.messageService.danger('登陆失败');
}
});
);
}
}

@ -89,7 +89,7 @@
<div class="col-7 mx-auto text-center mb-3">
<!-- 注册按钮-->
<button type="button" (click)="registerService.register(registerForm.value)" [disabled]="form().invalid"
<button type="button" (click)="register()" [disabled]="form().invalid"
class="btn btn-primary btn-lg">{{ 'button.register' | translate }}</button>
<!-- 返回登陆按钮-->
<button type="button" [routerLink]="['/login']"

@ -11,13 +11,15 @@ import {CookieService} from 'ngx-cookie-service';
// 环境变量
import {environment} from '../environments/environment';
import {LoginService} from './account/login/login.service';
import {Result} from './interface/Result';
import {MessageService} from './message/message.service';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss']
})
export class AppComponent implements OnInit{
export class AppComponent implements OnInit {
// 登陆状态
isLogin = false;
@ -32,12 +34,14 @@ export class AppComponent implements OnInit{
* @param router
* @param cookieService cookie管理服务
* @param loginService
* @param messageService
*/
constructor(
public translate: TranslateService,
private router: Router,
private cookieService: CookieService,
private loginService: LoginService
private loginService: LoginService,
private messageService: MessageService,
) {
this.navStart = router.events.pipe(
filter(evt => evt instanceof NavigationStart)
@ -48,7 +52,15 @@ export class AppComponent implements OnInit{
*
*/
logout() {
this.loginService.logout();
this.loginService.logout().subscribe(r => {
if (r.result === Result.OK) {
this.cookieService.deleteAll();
this.messageService.info('注销成功');
this.router.navigateByUrl('/login');
} else {
alert('注销失败');
}
});
}
async ngOnInit() {
@ -56,12 +68,12 @@ export class AppComponent implements OnInit{
this.isLogin = this.cookieService.check(environment.tokenKey);
this.managerName = this.cookieService.get(environment.managerKey);
if (evt.url === '/' && this.isLogin) {
if (evt.url !== '/forum' && this.isLogin) {
this.router.navigateByUrl('/forum');
} else if (evt.url === '/') {
} else if (evt.url !== '/login' && !this.isLogin) {
this.router.navigateByUrl('/login');
} else {
console.debug('当前路由' + evt.url + '不需要重定向');
}
});

@ -1,74 +1,72 @@
<!--公告轮播-->
<div id="carouselExampleControls" class="carousel slide bg-info m-3" data-ride="carousel">
<div class="carousel-inner">
<!-- <li *ngFor="let item of notices; index as i;">-->
<!-- {{i}}-->
<!-- </li>-->
<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}}
</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>
<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}}
</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>
</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>
</div>
</ng-container>
<ng-template #fff>
<div class="text-center">
<div class="spinner-border load" role="status">
<span class="sr-only">Loading...</span>
</div>
<h1>{{'forum.load_notices'|translate}}</h1>
</div>
</ng-template>
<!--审核贴-->
<div class="row border-warning check m-3">
<!-- 审核帖标识-->
<h1 class="text-info col-12 text-center">{{ 'forum.check' | translate }}</h1>
<ng-container *ngIf="posts;else ggg">
<div class="col-3">
<!--帖子列表-->
<ul class="list-group">
<!-- 帖子列表-->
<li class="list-group-item active">Cras justo odio</li>
<li class="list-group-item">Dapibus ac facilisis in</li>
<li class="list-group-item">Morbi leo risus</li>
<li class="list-group-item">Porta ac consectetur ac</li>
<li class="list-group-item">Vestibulum at eros</li>
<li class="list-group-item">Cras justo odio</li>
<li class="list-group-item">Dapibus ac facilisis in</li>
<li class="list-group-item">Morbi leo risus</li>
<li class="list-group-item">Porta ac consectetur ac</li>
<li class="list-group-item">Vestibulum at eros</li>
<li class="list-group-item" (click)="currentIndex=i" [class.active]="currentIndex===i" *ngFor="let post of posts.list;index as i">{{post.title}}</li>
</ul>
<!-- 分页按钮-->
<ul class="pagination ml-5 mt-3">
<li class="page-item"><a class="page-link" href="#">{{'button.prev_page'|translate}}</a></li>
<li class="page-item active"><a class="page-link" href="#">1</a></li>
<li class="page-item"><a class="page-link" href="#">2</a></li>
<li class="page-item"><a class="page-link" href="#">3</a></li>
<li class="page-item"><a class="page-link" href="#">{{'button.next_page'|translate}}</a></li>
<li class="page-item" [class.disabled]="posts.page.currentPage-1===0"><a class="page-link btn" (click)="getAllPosts(posts.page.currentPage-1)">{{'button.prev_page'|translate}}</a></li>
<li class="page-item active"><a class="page-link btn" (click)="getAllPosts(posts.page.currentPage)">{{posts.page.currentPage}}</a></li>
<li class="page-item"><a class="page-link btn" *ngIf="posts.page.currentPage+1<=posts.page.page" (click)="getAllPosts(posts.page.currentPage+1)">{{posts.page.currentPage+1}}</a></li>
<li class="page-item"><a class="page-link btn" *ngIf="posts.page.currentPage+2<=posts.page.page" (click)="getAllPosts(posts.page.currentPage+2)">{{posts.page.currentPage+2}}</a></li>
<li class="page-item" [class.disabled]="posts.page.currentPage===posts.page.page"><a class="page-link btn" (click)="getAllPosts(posts.page.currentPage+1)">{{'button.next_page'|translate}}</a></li>
</ul>
</div>
@ -77,37 +75,37 @@
<div class="col-9 post border-secondary p-3 position-relative">
<!-- 活动帖子-->
<ng-container *ngIf="true;else elseBlock">
<ng-container *ngIf="this.posts.list[this.currentIndex].type==='active';else elseBlock;">
<!-- 发件人信息-->
<div class="position-absolute sender">
<!-- 发帖人头像-->
<img src="/" class="headimg mb-3"/>
<img [src]="getActive().headImg" alt="headimg" class="headimg mb-3"/>
<!-- 发帖人-->
<div class="forum-label border-info mb-3 text-center">
发帖人
{{getActive().issuer}}
</div>
<!--信用分-->
<div class="forum-label border-info mb-3 text-center">
信用分
{{getActive().userCreditScore}}
</div>
</div>
<!-- 帖子框架-->
<div>
<!-- 标题-->
<h1 class="text-info col-12 text-center mb-3 forum-title">活动名</h1>
<h1 class="text-info col-12 text-center mb-3 forum-title">{{getActive().title}}</h1>
<!-- 帖子正文-->
<div class="forum-content border-info overflow-auto col-9 offset-2 mb-3">
帖子正文帖子正文帖子正文帖子正文帖子正文帖子正文帖子正文帖子正文帖子正文帖子正文帖子正文帖子正文帖子正文帖子正文帖子正文帖子正文帖子正文
{{getActive().content}}
</div>
<!-- 帖子底部-->
<div class="forum-footer border-info p-3 mb-3">
<h3 class="text-center">{{ 'forum.active_date' | translate:{
startDate: '2020-01-01',
endDate: '2020-02-01'
startDate: getActive().startTime|date:'yyyy-MM-dd',
endDate: getActive().endTime|date:'yyyy-MM-dd'
} }}</h3>
<h3 class="text-center">{{ 'forum.active_score' | translate:{score: 10} }}</h3>
<h3 class="text-center">{{ 'forum.active_score' | translate:{score: getActive().activeCreditScore} }}</h3>
</div>
</div>
@ -120,22 +118,24 @@
<!-- 投诉人信息-->
<div class="col-6 border-info l-label">
<div class="text-center">{{'forum.plaintiff'|translate}}</div>
<!-- 头像-->
<div class="d-flex justify-content-center mb-3 m-headimg">
<img src="/" class="headimg">
<img [src]="getComplaint().plaintiffHeadImg" alt="headimg" class="headimg">
</div>
<div class="text-center border-info mb-3 l-label">投诉人</div>
<div class="text-center border-info l-label">信用分</div>
<div class="text-center border-info mb-3 l-label">{{getComplaint().plaintiffName}}</div>
<div class="text-center border-info l-label">{{getComplaint().plaintiffCreditScore}}</div>
</div>
<!-- 被投诉人信息-->
<div class="col-6 border-info l-label">
<div class="text-center">{{'forum.defendant'|translate}}</div>
<div class="d-flex justify-content-center mb-3 m-headimg">
<!-- 头像-->
<img src="/" class="headimg">
<img [src]="getComplaint().defendantHeadImg" alt="headimg" class="headimg">
</div>
<div class="text-center border-info mb-3 l-label">投诉人</div>
<div class="text-center border-info l-label">信用分</div>
<div class="text-center border-info mb-3 l-label">{{getComplaint().defendantName}}</div>
<div class="text-center border-info l-label">{{getComplaint().defendantCreditScore}}</div>
</div>
</div>
@ -144,22 +144,31 @@
<!-- 投诉内容-->
<div class="col-7 border-success l-label h-100">
<!-- 投诉项-->
<h1 class="text-center">投诉项</h1>
<h1 class="text-center">{{getComplaint().title}}</h1>
<!-- 投诉内容-->
<div class="forum-content border-info overflow-auto mb-3">
投诉内容投诉内容投诉内容投诉内容投诉内容投诉内容投诉内容投诉内容投诉内容投诉内容投诉内容投诉内容投诉内容投诉内容投诉内容投诉内容投诉内容
{{getComplaint().content}}
</div>
<!-- 投诉时间-->
<h1 class="text-center">{{ 'forum.complaint_time' | translate:{time: '2020-01-01'} }}</h1>
<h1 class="text-center">{{ 'forum.complaint_time' | translate:{time: getComplaint().time|date:'yyyy-MM-dd'} }}</h1>
</div>
</div>
</ng-template>
<!--帖子审核按钮-->
<div class="col-12 text-center">
<button class="btn btn-info col-2 mr-3">{{ 'forum.approve' | translate }}</button>
<button class="btn btn-danger col-2">{{ 'forum.reject' | translate }}</button>
<button class="btn btn-info col-2 mr-3" (click)="checkPost(0)">{{ 'forum.approve' | translate }}</button>
<button class="btn btn-danger col-2" (click)="checkPost(1)">{{ 'forum.reject' | translate }}</button>
</div>
</div>
</ng-container>
<ng-template #ggg>
<div class="text-center col-12">
<div class="spinner-border load" role="status">
<span class="sr-only">Loading...</span>
</div>
<h1>{{'forum.load_posts'|translate}}</h1>
</div>
</ng-template>
</div>

@ -5,7 +5,7 @@
//公告正文边框
.notice-content {
height: 200px;
height: 230px;
border-style: solid;
border-width: 3px;
}
@ -17,7 +17,7 @@
//公告底部
.notice-footer {
top: 145px;
top: 175px;
bottom: 0;
width: 100%;
}
@ -101,5 +101,11 @@
margin-top: 50px;
}
//加载进度
.load{
width: 5rem;
height: 5rem;
}
//投诉帖end

@ -2,6 +2,8 @@ import {Component, OnInit} from '@angular/core';
import {Router} from '@angular/router';
import {ForumService} from './forum.service';
import {Result} from '../interface/Result';
import {Active, Complaint, Forum} from '../interface/ForumType';
import {Notice} from '../interface/Notice';
/**
*
@ -16,14 +18,15 @@ export class ForumComponent implements OnInit {
/**
*
*/
notices: [
{
managerName: string;
content: string;
title: string,
createTime: number
}
];
notices: Array<Notice>;
/**
*
*/
posts: Forum;
// 激活帖子索引
currentIndex = 0;
constructor(
private router: Router,
@ -31,6 +34,14 @@ export class ForumComponent implements OnInit {
) {
}
getActive(): Active {
return this.posts.list[this.currentIndex] as Active;
}
getComplaint(): Complaint {
return this.posts.list[this.currentIndex] as Complaint;
}
/**
*
*/
@ -39,14 +50,40 @@ export class ForumComponent implements OnInit {
if (res.result === Result.OK) {
console.debug('获取公告信息成功');
this.notices = res.body;
} else {
alert('获取公告信息失败');
}
});
}
/**
*
*/
getAllPosts(page) {
this.posts = null;
this.forumService.getAllPosts(page).subscribe(res => {
if (res.result === Result.OK) {
console.debug('获取帖子信息成功');
this.posts = res.body;
}
});
}
/**
*
*/
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('审核操作失败,请重试');
}
});
}
ngOnInit(): void {
this.getAllNotices();
this.getAllPosts(1);
}
}

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

@ -0,0 +1,53 @@
import { Injectable } from '@angular/core';
import {HttpClient} from '@angular/common/http';
import {JSONResponse} from '../interface/JSONResponse';
import {HttpInterface} from '../interface/HttpInterface';
import {JSONRequest} from '../interface/JSONRequest';
import {Observable} from 'rxjs';
import {catchError} from 'rxjs/operators';
/**
*
*/
@Injectable({
providedIn: 'root'
})
export class ForumService extends JSONRequest {
constructor(
private http: HttpClient
) {
super();
}
/**
*
*/
getAllNotices(): Observable<JSONResponse<any>> {
return this.http.get<JSONResponse<any>>(HttpInterface.getAllNotices, this.httpOptions)
.pipe(
catchError(this.handleError<any>('获取公告信息'))
);
}
/**
*
*/
getAllPosts(page): Observable<JSONResponse<any>> {
return this.http.get<JSONResponse<any>>(HttpInterface.getAllPosts + '/' + page, this.httpOptions)
.pipe(
catchError(this.handleError<any>('获取帖子'))
);
}
/**
*
*/
checkPost(id, s): Observable<JSONResponse<any>> {
return this.http.patch<JSONResponse<any>>(HttpInterface.checkPost + '/' + id, { status : s}, this.httpOptions)
.pipe(
catchError(this.handleError<any>('审核帖子'))
);
}
}

@ -0,0 +1,66 @@
// 帖子类型
export enum ForumType {
active= 'active',
complaint= 'complaint'
}
// 活动帖
export interface Active {
// 活动帖
// 帖子类型
type: ForumType;
// 帖子ID
id: number;
// 发帖人
issuer: string;
// 头像
headImg: string;
// 用户信用分
userCreditScore: number;
// 帖子标题
title: string;
// 帖子内容
content: string;
// 活动开始时间
startTime: number;
// 活动结束时间
endTime: number;
// 活动奖励分
activeCreditScore: number;
}
// 投诉帖
export interface Complaint {
// 帖子类型
type: ForumType;
// 帖子ID
id: number;
// 投诉人头像
plaintiffHeadImg: string;
// 投诉人名称
plaintiffName: string;
// 投诉人信用分
plaintiffCreditScore: number;
// 被投诉人头像
defendantHeadImg: string;
// 被投诉人名称
defendantName: string;
// 被投诉人信用分
defendantCreditScore: number;
// 投诉标题
title: string;
// 投诉内容
content: string;
// 投诉时间
time: number;
}
export interface Forum {
list: Array<Active|Complaint>;
page: {
count: number;
page: number;
currentPage: number;
};
}

@ -19,7 +19,11 @@ const HttpInterface = {
// 重置密码
resetPwd: '/api/manager/reset/resetPwd',
// 获取所有公告
getAllNotices: '/api/forum/notices'
getAllNotices: '/api/forum/notices',
// 获取所有帖子
getAllPosts: '/api/forum/posts',
// 审核帖子
checkPost: '/api/forum/posts'
};
for (const key of Object.keys(HttpInterface)) {

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

@ -1,3 +1,4 @@
// 返回结果
export enum Result {
OK = 'OK',
FAIL = 'FAIL'

@ -28,11 +28,14 @@
"active_score": "Active Score:{{score}}",
"approve": "approve",
"reject": "reject",
"complaint": "time:{{time}}"
"complaint": "time:{{time}}",
"plaintiff": "plaintiff",
"defendant": "defendant",
"load_notices": "Loading advertising information"
},
"tip":{
"input": "please input {{value}}",
"HELLO": "Hello {{value}} welcome to you",
"HELLO": "Hello <span style='color:red'>{{value}}</span> welcome to you",
"notnull": "The {{value}} cannot be empty",
"password_diff": "The passwords do not match",
"mobile_error": "The phone number is illegal",

@ -28,7 +28,11 @@
"active_score": "参与活动奖励信用分:{{score}}",
"approve": "审核通过",
"reject": "审核不通过",
"complaint_time": "投诉时间:{{time}}"
"complaint_time": "投诉时间:{{time}}",
"plaintiff": "投诉人",
"defendant": "被投诉人",
"load_notices": "正在加载广告信息",
"load_posts": " 正在加载帖子信息"
},
"tip":{
"input": "请输入{{value}}",

Loading…
Cancel
Save