Browse Source

[新增]聊天功能完善

非煤矿山灾害智能感知和预警系统
邵佳豪 3 years ago
parent
commit
ae3a3f26d2
  1. 6
      src/app/home/commonComponents/chat-window/chat-window.component.html
  2. 5
      src/app/home/commonComponents/chat-window/chat-window.component.scss
  3. 108
      src/app/home/commonComponents/chat-window/chat-window.component.ts
  4. 1
      src/app/home/home.module.ts
  5. 2
      src/app/home/task/da-oneself-plan/plan-adjustment/plan-adjustment.component.ts
  6. 13
      src/app/home/task/station-task-apply/station-task-apply.component.html
  7. 7
      src/app/home/task/station-task-apply/station-task-apply.component.ts
  8. 20
      src/app/home/task/station-task-execution/station-task-execution.component.html
  9. 5
      src/app/home/task/station-task-execution/station-task-execution.component.ts
  10. 33
      src/app/home/task/station-weekly-plan/station-weekly-plan.component.html
  11. 6
      src/app/home/task/station-weekly-plan/station-weekly-plan.component.scss
  12. 12
      src/app/home/task/station-weekly-plan/station-weekly-plan.component.ts
  13. 57
      src/signalRChat.ts

6
src/app/home/commonComponents/chat-window/chat-window.component.html

@ -6,12 +6,12 @@
<span class="close" nz-icon nzType="close" nzTheme="outline" (click)="close()"></span> <span class="close" nz-icon nzType="close" nzTheme="outline" (click)="close()"></span>
</div> </div>
<div class="chatcontent" id="chatcontent"> <div class="chatcontent" id="chatcontent">
<div class="chatitem" *ngFor="let item of data" [ngClass]="{'chatitemMe': item.name == ''}"> <div class="chatitem" *ngFor="let item of MessagesList" [ngClass]="{'chatitemMe': item.senderId == userId}">
<div class="name"> <div class="name">
{{item.name}} {{item.senderName}}
</div> </div>
<div class="chatmessage"> <div class="chatmessage">
{{item.content}} {{item.message}}
</div> </div>
</div> </div>
</div> </div>

5
src/app/home/commonComponents/chat-window/chat-window.component.scss

@ -18,11 +18,12 @@
border-bottom: 1px solid #E4E7EC; border-bottom: 1px solid #E4E7EC;
box-sizing: border-box; box-sizing: border-box;
padding: 0 18px; padding: 0 18px;
color: #000;
.titlename { .titlename {
flex: 1; flex: 1;
cursor: move; cursor: move;
text-align: left; text-align: left;
} }
.close { .close {
@ -57,7 +58,7 @@
width: fit-content; width: fit-content;
width: -webkit-fit-content; width: -webkit-fit-content;
width: -moz-fit-content; width: -moz-fit-content;
color: #000;
} }
} }

108
src/app/home/commonComponents/chat-window/chat-window.component.ts

@ -1,7 +1,9 @@
import { Component, ElementRef, OnInit, NgZone, Input, Inject } from '@angular/core'; import { Component, ElementRef, OnInit, NgZone, Input, Inject } from '@angular/core';
import { NzMessageService } from 'ng-zorro-antd/message'; import { NzMessageService } from 'ng-zorro-antd/message';
import { debounceTime, fromEvent } from 'rxjs'; import signalR from '../../../../signalRChat'
import { StationTaskApplyComponent } from '../../task/station-task-apply/station-task-apply.component'; import { HttpClient } from '@angular/common/http';
import { StationWeeklyPlanComponent } from '../../task/station-weekly-plan/station-weekly-plan.component';
@Component({ @Component({
selector: 'app-chat-window', selector: 'app-chat-window',
@ -13,43 +15,70 @@ export class ChatWindowComponent implements OnInit {
constructor(private ngZone: NgZone, private element: ElementRef, private message: NzMessageService, constructor(private ngZone: NgZone, private element: ElementRef, private message: NzMessageService,
@Inject(StationTaskApplyComponent) private parentComponent: any) { } @Inject(StationWeeklyPlanComponent) private parentComponent: any, private http: HttpClient) { }
chatcontent chatcontent
userId
userName
ngOnInit(): void { ngOnInit(): void {
this.userId = JSON.parse(sessionStorage.getItem('userData')).id
this.userName = JSON.parse(sessionStorage.getItem('userData')).name
this.chatcontent = this.element.nativeElement.querySelector(`#chatcontent`) this.chatcontent = this.element.nativeElement.querySelector(`#chatcontent`)
setTimeout(() => { setTimeout(() => {
this.scrollToBottom() this.scrollToBottom()
}, 0); }, 0);
this.getAllMessages()
signalR.initSR(this.taskId);
// 接收来自中心的消息
(signalR.SR as any).on('receiveMessage', (message: any) => {
console.log('收到消息', message)
this.MessagesList.push(message);
if (this.chatcontent.scrollHeight - (this.chatcontent.scrollTop + this.chatcontent.clientHeight) == 0) {
setTimeout(() => {
this.scrollToBottom()
}, 0);
}
})
} }
text = '' /**
data = [ *
{ name: '小王', content: '说三道四的数据库的技术框架的开始倒计时打开双击打开双击打开双击打开速度加快速度加快速度加快是昆明昆明昆明的技术框架的历下区A消防救援站正在执行熟悉演练任务~' }, */
{ name: '小李', content: '收到~' }, MessagesList = []
{ name: '炒鸡消防站', content: '~' }, /**
{ name: '我', content: '说三道四的数据库的技术框架的开始倒计时打开双击打开双击打开双击打开速度加快速度加快速度加快是昆明昆明昆明的技术框架的历下区A消防救援站正在执行熟悉演练任务~' }, *
{ name: '阿玉', content: 'fdff~' }, */
{ name: '我', content: '咋了~' }, getAllMessages() {
{ name: '阿玉', content: 'hahah~' } console.log('任务id', this.taskId)
] this.http.get('/api/TaskChats/Messages', {
params: {
TaskId: this.taskId,
PageNumber:1,
PageSize:999,
SortProperty:'CreationTime',
SortType:'asc'
}
}).subscribe((data: any) => {
this.MessagesList = data.items
console.log('聊天记录', this.MessagesList)
})
}
ngOnDestroy(): void {
signalR.stopSR()
}
text = ''
close() { close() {
// let obj = {
// name: "小虎",
// content: '测试数据'
// }
// this.ngZone.run(() => {
// this.data.push(obj)
// //如果此时滚动条在最底部
// if (this.chatcontent.scrollHeight - (this.chatcontent.scrollTop + this.chatcontent.clientHeight) == 0) {
// setTimeout(() => {
// this.scrollToBottom()
// }, 0);
// }
// })
this.parentComponent.closechat() this.parentComponent.closechat()
} }
send() { send() {
@ -57,34 +86,15 @@ export class ChatWindowComponent implements OnInit {
this.message.create('warning', '输入不能为空'); this.message.create('warning', '输入不能为空');
return return
} }
let obj = { // 发送消息
name: "我", (signalR.SR as any).send('sendMessage', this.taskId, this.text)
content: this.text
}
this.data.push(obj)
setTimeout(() => { setTimeout(() => {
this.scrollToBottom() this.scrollToBottom()
this.text = ''
}, 0); }, 0);
this.text = ''
} }
scrollToBottom() { scrollToBottom() {
this.chatcontent.scrollTop = this.chatcontent.scrollHeight this.chatcontent.scrollTop = this.chatcontent.scrollHeight
} }
//是否滚动到底部
// isScrollBottom = true
ngAfterViewInit(): void {
// let tableHeader = this.element.nativeElement.querySelector(`.ant-table-header`).clientHeight
// fromEvent(this.chatcontent as HTMLCanvasElement, 'scroll').pipe(debounceTime(100)).subscribe(async (event: any) => { //监听 DOM 滚动事件
// //如果滚动到底部
// if (event.target.scrollHeight - (event.target.scrollTop + event.target.clientHeight) == 0) {
// this.isScrollBottom = true
// } else {
// this.isScrollBottom = false
// }
// });
}
} }

1
src/app/home/home.module.ts

@ -69,7 +69,6 @@ import { NzBadgeModule } from 'ng-zorro-antd/badge';
import { NzListModule } from 'ng-zorro-antd/list'; import { NzListModule } from 'ng-zorro-antd/list';
import { OperationLogComponent } from './basic-info/unit-details/operation-log/operation-log.component'; import { OperationLogComponent } from './basic-info/unit-details/operation-log/operation-log.component';
import { NzDividerModule } from 'ng-zorro-antd/divider'; import { NzDividerModule } from 'ng-zorro-antd/divider';
import { AppModule } from '../app.module';
import { ChatWindowComponent } from './commonComponents/chat-window/chat-window.component'; import { ChatWindowComponent } from './commonComponents/chat-window/chat-window.component';
import { AngularDraggableModule } from 'angular2-draggable'; import { AngularDraggableModule } from 'angular2-draggable';
@NgModule({ @NgModule({

2
src/app/home/task/da-oneself-plan/plan-adjustment/plan-adjustment.component.ts

@ -22,9 +22,9 @@ export class PlanAdjustmentComponent implements OnInit {
OrganizationId OrganizationId
ngOnInit(): void { ngOnInit(): void {
this.userId = JSON.parse(sessionStorage.getItem('userData')).id this.userId = JSON.parse(sessionStorage.getItem('userData')).id
this.OrganizationId = JSON.parse(sessionStorage.getItem('userData')).organizationId
this.organizationName = JSON.parse(sessionStorage.getItem('userData')).organizationName this.organizationName = JSON.parse(sessionStorage.getItem('userData')).organizationName
this.OrganizationId = JSON.parse(sessionStorage.getItem('userData')).organizationId
let roles = JSON.parse(sessionStorage.getItem('userData')).roles let roles = JSON.parse(sessionStorage.getItem('userData')).roles
let isSupervisor = roles.find(item => { let isSupervisor = roles.find(item => {
return item.name.indexOf('检查') != -1 return item.name.indexOf('检查') != -1

13
src/app/home/task/station-task-apply/station-task-apply.component.html

@ -190,14 +190,6 @@
操作 操作
</span> </span>
</div> </div>
<div class="flexcol">
<span>
<img style="cursor: pointer;width: 36px;height: 28px;" src="../../../../assets/images/icon/chat.png" (click)="openchat()" alt="">
</span>
<span>
消息
</span>
</div>
</div> </div>
</div> </div>
<div class="pagination"> <div class="pagination">
@ -210,9 +202,4 @@
</div> </div>
</div> </div>
</div> </div>
<div *ngIf="ischat" style="position: absolute;left: 30%;top: 12%;">
<app-chat-window [taskId]="'1234'"></app-chat-window>
</div>
</div> </div>

7
src/app/home/task/station-task-apply/station-task-apply.component.ts

@ -404,13 +404,6 @@ export class StationTaskApplyComponent implements OnInit {
}); });
} }
ischat = false
openchat() {
this.ischat = true
}
public closechat() {
this.ischat = false
}
} }
export enum ApprovalStatus { export enum ApprovalStatus {

20
src/app/home/task/station-task-execution/station-task-execution.component.html

@ -95,7 +95,7 @@
<div class="flexcol"> <div class="flexcol">
<span> <span>
2022.07.20 14:00 {{item.lastModificationTime | date:"yyyy-MM-dd"}}
</span> </span>
<span> <span>
时间 时间
@ -128,25 +128,23 @@
</div> </div>
<div class="flexcol flexcolassistant"> <div class="flexcol flexcolassistant">
<span class="assistant" nz-tooltip [nzTooltipTitle]="titleTemplate"> <span class="assistant" nz-tooltip [nzTooltipTitle]="titleTemplate">
<span *ngFor="let i of item.assistantOrganizations">
{{i.name}}
</span>
<span *ngFor="let i of item.supervisors"> <span *ngFor="let i of item.supervisors">
<img *ngIf="i.posts && i.posts[0] == '主查人员'"
src="../../../../assets/images/icon/main.png" alt="">
<img *ngIf="i.posts && i.posts[0] == '协查人员'"
src="../../../../assets/images/icon/assist.png" alt="">
{{i.name}} {{i.name}}
</span> </span>
</span> </span>
<ng-template #titleTemplate let-thing> <ng-template #titleTemplate let-thing>
<span style="margin-right: 6px;" *ngFor="let i of item.supervisors"> <span *ngFor="let i of item.assistantOrganizations">
<img *ngIf="i.posts && i.posts[0] == '主查人员'" {{i.name}}
src="../../../../assets/images/icon/main.png" alt=""> </span>
<img *ngIf="i.posts && i.posts[0] == '协查人员'" <span *ngFor="let i of item.supervisors">
src="../../../../assets/images/icon/assist.png" alt="">
{{i.name}} {{i.name}}
</span> </span>
</ng-template> </ng-template>
<span> <span>
协助人员 {{'协助机构/人员'}}
</span> </span>
</div> </div>
<div class="flexcol"> <div class="flexcol">

5
src/app/home/task/station-task-execution/station-task-execution.component.ts

@ -72,9 +72,9 @@ export class StationTaskExecutionComponent implements OnInit {
// OrganizationId: this.OrganizationId, // OrganizationId: this.OrganizationId,
TaskName: this.searchForm.taskname, TaskName: this.searchForm.taskname,
CompanyName: this.searchForm.unitname, CompanyName: this.searchForm.unitname,
assistantOrganizationId: this.searchForm.or, SupervisorId: this.isSupervisor ? this.userId : null,
AssitantOrganizationId: this.isSupervisor ? null : this.OrganizationId,
approvalStatuses: ['已检查'], approvalStatuses: ['已检查'],
SupervisorId: this.userId,
PageNumber: this.PageNumber, PageNumber: this.PageNumber,
PageSize: this.PageSize PageSize: this.PageSize
} }
@ -192,6 +192,7 @@ export class StationTaskExecutionComponent implements OnInit {
time2 time2
ngOnInit(): void { ngOnInit(): void {
this.userId = JSON.parse(sessionStorage.getItem('userData')).id
this.OrganizationId = JSON.parse(sessionStorage.getItem('userData')).organizationId this.OrganizationId = JSON.parse(sessionStorage.getItem('userData')).organizationId
this.userId = JSON.parse(sessionStorage.getItem('userData')).id this.userId = JSON.parse(sessionStorage.getItem('userData')).id
let roles = JSON.parse(sessionStorage.getItem('userData')).roles let roles = JSON.parse(sessionStorage.getItem('userData')).roles

33
src/app/home/task/station-weekly-plan/station-weekly-plan.component.html

@ -195,20 +195,18 @@
</div> </div>
<div class="flexcol flexcolassistant"> <div class="flexcol flexcolassistant">
<span class="assistant" nz-tooltip [nzTooltipTitle]="titleTemplate"> <span class="assistant" nz-tooltip [nzTooltipTitle]="titleTemplate">
<span *ngFor="let o of i.assistantOrganizations">
{{o.name}}
</span>
<span *ngFor="let o of i.supervisors"> <span *ngFor="let o of i.supervisors">
<img *ngIf="o.posts && o.posts[0] == '主查人员'"
src="../../../../assets/images/icon/main.png" alt="">
<img *ngIf="o.posts && o.posts[0] == '协查人员'"
src="../../../../assets/images/icon/assist.png" alt="">
{{o.name}} {{o.name}}
</span> </span>
</span> </span>
<ng-template #titleTemplate let-thing> <ng-template #titleTemplate let-thing>
<span style="margin-right: 6px;" *ngFor="let o of i.supervisors"> <span *ngFor="let o of i.assistantOrganizations">
<img *ngIf="o.posts && o.posts[0] == '主查人员'" {{o.name}}
src="../../../../assets/images/icon/main.png" alt=""> </span>
<img *ngIf="o.posts && o.posts[0] == '协查人员'" <span *ngFor="let o of i.supervisors">
src="../../../../assets/images/icon/assist.png" alt="">
{{o.name}} {{o.name}}
</span> </span>
</ng-template> </ng-template>
@ -236,9 +234,16 @@
检查时间 检查时间
</span> </span>
</div> </div>
<!-- <div class="btnbox"> <div class="flexcol flexcolcenter">
聊天 <span>
</div> --> <img style="cursor: pointer;width: 36px;height: 28px;"
src="../../../../assets/images/icon/chat.png" (click)="openchat(i)"
alt="">
</span>
<span>
消息
</span>
</div>
</div> </div>
</div> </div>
</div> </div>
@ -250,4 +255,8 @@
<div class="cutoffrule"></div> <div class="cutoffrule"></div>
</div> </div>
<div *ngIf="ischat" style="position: absolute;left: 30%;top: 12%;">
<app-chat-window [taskId]="taskId"></app-chat-window>
</div>
</div> </div>

6
src/app/home/task/station-weekly-plan/station-weekly-plan.component.scss

@ -4,6 +4,7 @@
display: flex; display: flex;
flex-direction: column; flex-direction: column;
overflow: hidden; overflow: hidden;
position: relative;
} }
.informbox { .informbox {
@ -389,8 +390,11 @@
span:nth-child(2) { span:nth-child(2) {
color: #C7CAD0; color: #C7CAD0;
} }
} }
.flexcolcenter{
align-items: center;
}
.flexcolassistant { .flexcolassistant {
flex: 2; flex: 2;

12
src/app/home/task/station-weekly-plan/station-weekly-plan.component.ts

@ -665,4 +665,16 @@ export class StationWeeklyPlanComponent implements OnInit {
nzCancelText: '取消' nzCancelText: '取消'
}); });
} }
ischat = false
taskId
openchat(item) {
console.log(item)
this.taskId = item.id
this.ischat = true
}
closechat() {
this.ischat = false
}
} }

57
src/signalRChat.ts

@ -0,0 +1,57 @@
import * as signalR from '@microsoft/signalr'
export default {
SR: {},
// 初始化连接
initSR: function (id) {
const that = this
// // 连接 SignalR
const options: signalR.IHttpConnectionOptions = {
accessTokenFactory: async () => {
return sessionStorage.getItem('token')
}
}
// 1.获取系统中定义的baseURL
const url = '/hubs/taskchat'
// 2.初始化连接
that.SR = new signalR.HubConnectionBuilder()
.withUrl(url, options)
.configureLogging(signalR.LogLevel.Information)
.build();
// 3. 在停止signalR时,不让onclose内的 start执行
(that.SR as any).flag = true
// 4.启动连接的方法
async function start() {
try {
await (that.SR as any).start().then(() => {
console.log('加入聊天室',id)
that.SR.send("joinRoom", id)
});
} catch (err) {
setTimeout(start, 5000);
}
}
// 5.关闭之后重连
(that.SR as any).onclose(async () => {
if ((that.SR as any).flag) {
await start();
}
});
// 6.启动连接
start();
},
// 停止连接,因为调用that.SR.stop(),同时会触发5操作,所以用了flag
stopSR: function () {
let that = this;
(that.SR as any).flag = false
async function stop() {
try {
await that.SR.stop();
console.log("signaR退出成功");
} catch (err) { }
}
stop();
}
};
Loading…
Cancel
Save