react_hsbc_teller 2.0.2 → 2.0.4-6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. package/lib/hsbc.js +1 -1
  2. package/lib/hsbc.js.LICENSE.txt +11 -0
  3. package/package.json +2 -1
  4. package/packages/api/api.js +267 -2
  5. package/packages/assets/img/icon_asr.png +0 -0
  6. package/packages/assets/img/icon_env.png +0 -0
  7. package/packages/assets/img/icon_fail.jpg +0 -0
  8. package/packages/assets/img/icon_paper.png +0 -0
  9. package/packages/assets/img/icon_success.jpg +0 -0
  10. package/packages/assets/mp3/ipad_join_meeting.mp3 +0 -0
  11. package/packages/assets/mp3/ipad_leave_error.mp3 +0 -0
  12. package/packages/assets/mp3/ipad_leave_meeting.mp3 +0 -0
  13. package/packages/assets/mp3/ipad_low_power.mp3 +0 -0
  14. package/packages/assets/mp3/networkweak.mp3 +0 -0
  15. package/packages/assets/mp3/pip_close.mp3 +0 -0
  16. package/packages/assets/mp3/record_error.mp3 +0 -0
  17. package/packages/demo/demo.js +52 -18
  18. package/packages/demo/pdf.js +16 -1
  19. package/packages/pages/foot/foot.jsx +29 -6
  20. package/packages/pages/foot/foot.less +1 -0
  21. package/packages/pages/header/header.jsx +1 -1
  22. package/packages/pages/multiModule/components/copy/agree.jsx +115 -0
  23. package/packages/pages/multiModule/components/copy/agree.less +105 -0
  24. package/packages/pages/multiModule/components/copy/copyTwo.jsx +666 -0
  25. package/packages/pages/multiModule/components/copy/copyTwo.less +180 -0
  26. package/packages/pages/multiModule/components/copy/copy_en.jsx +368 -0
  27. package/packages/pages/multiModule/components/copy/copy_en.less +145 -0
  28. package/packages/pages/multiModule/components/copy/copylist.jsx +291 -0
  29. package/packages/pages/multiModule/components/copy/copylist.less +83 -0
  30. package/packages/pages/multiModule/components/copy/risk.jsx +296 -0
  31. package/packages/pages/multiModule/components/copy/risk.less +123 -0
  32. package/packages/pages/multiModule/components/sign/signMy.jsx +308 -0
  33. package/packages/pages/multiModule/components/sign/signMy.less +128 -0
  34. package/packages/pages/multiModule/components/subscribe/subscribe.jsx +113 -0
  35. package/packages/pages/multiModule/components/subscribe/subscribe.less +82 -0
  36. package/packages/pages/multiModule/multiModule.jsx +26 -0
  37. package/packages/pages/multiModule/multiModule.less +20 -0
  38. package/packages/pages/sign/signMy.jsx +2 -0
  39. package/packages/pages/video/video.jsx +2431 -717
  40. package/packages/pages/video/video.less +92 -2
  41. package/packages/utils/asrController.js +246 -0
  42. package/packages/utils/utils.js +122 -0
  43. package/packages/common/JKL.js +0 -61
  44. package/packages/common/XML.js +0 -271
  45. package/packages/common/websocket.js +0 -267
  46. package/packages/utils/cell.js +0 -64
@@ -4,11 +4,15 @@
4
4
  import React, { Component, useState } from 'react';
5
5
  import QRCode from 'qrcode.react';
6
6
  import API from '../../api/api';
7
- import { initWebSocket, joinRoom, disconnect } from '../../common/websocket';
8
7
  import { BoardOperate } from '../../common/index.esm.js';
9
8
  import './video.less'
9
+ import { compressImage, isLight } from '../../utils/utils'
10
+ import Recorder from "js-audio-recorder";
11
+ import MyAsrController from '../../utils/asrController'
10
12
  import Header from '../header/header.jsx'
11
13
  import Foot from '../foot/foot.jsx'
14
+ import IconSuccess from '../../assets/img/icon_success.jpg'
15
+ import IconFail from '../../assets/img/icon_fail.jpg'
12
16
  import voiceImgOpen from '../../assets/img/icon_Mute.png'
13
17
  import voiceImgCloe from '../../assets/img/icon_MuteOne.png'
14
18
  import cameraImgOpen from '../../assets/img/icon_camera.png'
@@ -16,12 +20,18 @@ import cameraImgCloe from '../../assets/img/icon_cameraOne.png'
16
20
  import beautyImg from '../../assets/img/whiteningLut.jpg'
17
21
  import ocrImage from '../../assets/img/jietu.png'
18
22
  import faceImage from '../../assets/img/jietu_face.png'
19
- import autod from '../../assets/mp3/joinmeeting.mp3'
23
+ import joinMeeting from '../../assets/mp3/joinmeeting.mp3'
24
+ import ipadjoinMeeting from '../../assets/mp3/ipad_join_meeting.mp3'
25
+ import ipadLeaveMeeting from '../../assets/mp3/ipad_leave_meeting.mp3'
26
+ import recordErrorAudio from '../../assets/mp3/record_error.mp3'
27
+ import IpadLeaveAudio from '../../assets/mp3/ipad_leave_error.mp3';
28
+ import IpadLowPowerAudio from '../../assets/mp3/ipad_low_power.mp3';
20
29
  import internalJoin from '../../assets/mp3/internalJoin.mp3'
21
30
  import internalLeft from '../../assets/mp3/internalLeft.mp3'
22
31
  import leftMetting from '../../assets/mp3/leftmeeting.mp3'
32
+ import networkWeakAudio from '../../assets/mp3/networkweak.mp3'
33
+ import PIPictureClosedAudio from '../../assets/mp3/pip_close.mp3'
23
34
  import errorPng from '../../assets/img/tooltips2_fail.png'
24
- import { callNimIM } from '../../utils/cell.js'
25
35
  import Modal from "antd/lib/modal";
26
36
  import 'antd/lib/modal/style'
27
37
  import message from "antd/lib/message";
@@ -37,29 +47,59 @@ import 'antd/lib/radio/style'
37
47
 
38
48
  import Space from "antd/lib/space";
39
49
  import 'antd/lib/space/style'
50
+ import { Collapse } from 'antd';
51
+ import 'antd/lib/collapse/style'
52
+ const { Panel } = Collapse;
40
53
 
41
54
 
42
55
  import styled from 'styled-components';
43
56
  import { Button } from '../../../node_modules/antd/lib/index';
44
57
  import SignMy from '../sign/signMy.jsx'
45
58
  import Step from '../components/step/step.jsx'
59
+ import MultiModule from '../multiModule/multiModule'//签字、抄录
46
60
  import axios from 'axios';
47
61
  import CryptoJS from "crypto-js";
62
+
63
+ const SDK_VERISON = '2.0.46.1'
48
64
  const IDtypeFront = '请客户在其设备后置摄像头下展示证件正面(如:身份证照片页面)'
49
65
  const IDtypeBack = '请在后置摄像头下展示证件反面(如:身份证国徽页)'
50
66
  const { Option } = Select;
51
67
  const LEAVE_TYPE = {
52
68
  TELLER_EXIT: 1, // 坐席退出
53
69
  ROOM_DESTROYED: -1, // 房间异常
70
+ TELLER_DISCONNECT: -2, // 坐席连接断开
71
+ }
72
+ const POINT_TYPE = {
73
+ tts: '文字转语音',
74
+ asr: '语音转文字',
75
+ ffd: "人脸出框检测",
76
+ env: "环境检测",
77
+ pipd: "画中画显示、关闭",
78
+ pwd: "违禁词检测",
79
+ wnd: "弱网",
80
+ mute: "静音",
81
+ expDark: '曝光、背光',
82
+ fcd: '人脸变化检测',
83
+ padConnected: 'ipad已连接'
54
84
  }
85
+ const RECORD_DEVICE_NAME = 'screen-capture-recorder'
86
+ // const RECORD_DEVICE_NAME = 'Full HD webcam'
87
+ const IPAD_SUFFIX = '_ipad'
88
+ const H5_SUFFIX = '_h5'
89
+ let media_status = 0
55
90
  let pictureInPictureVideo
56
91
  let mix_stream
57
92
  let worker
58
93
  let streamShare
94
+ let streamRecord
59
95
  let videoName
96
+ let lastFaceNum = 1
60
97
  let muteJson = new Map()
61
- let dateTime = 0
98
+ // let dateTime = 0
62
99
  let messageValue = ''
100
+ let messageValueMap = new Map()
101
+ let videoMessageMap = new Map() // 画中画消息数据
102
+ let third_id_Map = new Map()
63
103
  // let beautyType = false
64
104
  // let beautyNum = 0 // 0-关闭 1--弱 2--中 5---高
65
105
  let rateList = []
@@ -69,6 +109,8 @@ let isSuccuseHs = false
69
109
  let isGraffiti = false
70
110
  let strokeColor = '#333'
71
111
  let clearTime
112
+ let beautyMode = 'none'
113
+ let hsMode = 'none'
72
114
  let CanvasHome = styled.div`
73
115
  position: fixed;
74
116
  z-index: ${props => props.zIndexNum};
@@ -102,6 +144,7 @@ function clearStreamRemain() {
102
144
  beautyDiv.beauty_canvas = null;
103
145
  }
104
146
  if (!(beautyDiv.beauty_player == null || beautyDiv.beauty_player == undefined)) {
147
+ console.log('beautyDiv destroy')
105
148
  beautyDiv.beauty_player.destroy();
106
149
  beautyDiv.beauty_player = null;
107
150
  }
@@ -114,7 +157,7 @@ function clearStreamRemain() {
114
157
  };
115
158
  async function startBeauty(stream) {
116
159
  await beautyInit();
117
- beautyStart(stream, "none");
160
+ beautyStart(stream, beautyMode);
118
161
  }
119
162
  async function startMix(stream, onState) {
120
163
  var drawCanvas = document.getElementById('canvas');
@@ -130,21 +173,25 @@ async function startHs(stream) {
130
173
 
131
174
  await hsInit();
132
175
 
133
- hsStart(stream, 'none');
176
+ hsStart(stream, hsMode);
134
177
 
135
178
  }
136
179
 
137
180
  async function stopHs() {
138
- var stop_stream = true;//控制是否内部来进行关闭流
139
- var stream = hsStop(stop_stream);
140
- if (stream != null && stream != undefined) {
141
- stream.getTracks().forEach((track) => {
142
- track.stop();
143
- });
144
- stream = null;
181
+ try {
182
+ var stop_stream = true;//控制是否内部来进行关闭流
183
+ var stream = hsStop(stop_stream);
184
+ if (stream != null && stream != undefined) {
185
+ stream.getTracks().forEach((track) => {
186
+ track.stop();
187
+ });
188
+ stream = null;
189
+ }
190
+ isSuccuseHs = false
191
+ } catch (err) {
192
+ console.log('stopHs Error')
193
+ console.log(err)
145
194
  }
146
- isSuccuseHs = false
147
-
148
195
  }
149
196
  async function mixStopClick() {
150
197
  var stop_stream = true;//控制是否内部来进行关闭流
@@ -169,6 +216,7 @@ class Video extends Component {
169
216
  }
170
217
  cancel = axios.CancelToken.source()
171
218
  state = {
219
+ ablePlayNetweakAudio: true,
172
220
  beautyType: false,
173
221
  beautyName: '开启美颜',
174
222
  signNoClick: false,
@@ -201,6 +249,8 @@ class Video extends Component {
201
249
  isModalVisibleFacial: false,
202
250
  isModalVisibleEnd: false,
203
251
  isModalVisible: false,
252
+ isPictureConfirmModalVisible:false,
253
+ isDisconnectModalVisible: false,
204
254
  screenName: '共享模式',
205
255
  suspendName: '暂停',
206
256
  cameraImg: cameraImgOpen,
@@ -240,14 +290,14 @@ class Video extends Component {
240
290
  microphoneList: [],
241
291
  speakerList: [],
242
292
  isModalVisibleInspection: false,
293
+ envInfo: {},
294
+ isModalVisibleEnvironment: false,
243
295
  cameraValue: '',
244
296
  microphoneValue: '',
245
297
  imStatus: false,
246
- imJoinRoom: false,
247
298
  analyserData: new Map(),
248
299
  analyserHeight: new Map(),
249
300
  OnVolumeAnalyserMap: new Map(),
250
- manualClose: false,
251
301
  defaultValue: '1',
252
302
  customOcrSid: '',
253
303
  shareMaskState: false,
@@ -288,6 +338,8 @@ class Video extends Component {
288
338
  cardFailReason: '',
289
339
  videoType: '',
290
340
  certificateValidityType: true,
341
+ drawCanvasInterval: null,
342
+ faceDetectionTimer: null, // 人脸检测定时器
291
343
  };
292
344
  // eslint-disable-next-line no-undef
293
345
  test_controller = '';
@@ -295,7 +347,7 @@ class Video extends Component {
295
347
  saveLog = (val) => {
296
348
  axios({
297
349
  method: 'get',
298
- baseURL: this.props.logUrl + '&message=' + encodeURIComponent(val) + '&react_hsbc_teller=2.0.2&logTime=' + Date.now() + '&mtoken=' + encodeURIComponent(this.state.rtoken) + '&roomId=' + encodeURIComponent(this.state.channelId) + '&sessionId=' + encodeURIComponent(this.state.sessionId) + '&appointmentID=' + this.props.businessNumber,
350
+ baseURL: this.props.logUrl + '&message=' + encodeURIComponent(val) + '&react_hsbc_teller='+ SDK_VERISON +'&logTime=' + Date.now() + '&mtoken=' + encodeURIComponent(this.state.rtoken) + '&roomId=' + encodeURIComponent(this.state.channelId) + '&sessionId=' + encodeURIComponent(this.state.sessionId) + '&appointmentID=' + this.props.businessNumber,
299
351
 
300
352
  }).then(res => {
301
353
 
@@ -315,8 +367,16 @@ class Video extends Component {
315
367
  try {
316
368
  let result = await API.createRoom({
317
369
  staffId: this.props.tellerAccount,
370
+ staffName: this.props.staffName,
318
371
  activityId: this.props.businessNumber,
319
372
  callbackUrl: this.props.callbackUrl,
373
+ meetingDuration: this.props.meetingDuration,
374
+ recordMode: this.props.recordMode,
375
+ defaultBranchCode: this.props.defaultBranchCode,
376
+ customerId: this.props.customerId,
377
+ customerType: this.props.customerType.toString(),
378
+ salesBranchCode: this.props.salesBranchCode,
379
+ financialOffice: this.props.financialOffice,
320
380
  roomId: this.state.channelId,
321
381
  mtoken: this.state.rtoken,
322
382
  type: 2
@@ -324,32 +384,31 @@ class Video extends Component {
324
384
  console.log(result);
325
385
  this.state.imRoomId = result.imRoomId,
326
386
  this.state.sessionId = result.sessionId;
387
+ window.imRoom.sessionId = result.sessionId;
388
+
389
+ let publish_config = {}
390
+ publish_config.media_type = 1
391
+ publish_config.publish_device = 1
392
+ publish_config.videoSource = this.state.cameraValue
393
+ publish_config.audioSource = this.state.microphoneValue
394
+ publish_config.need_volume_analyser = true
395
+ // publish_config.video_profile_type = 3
396
+ publish_config.video_profile_type = 100
397
+ publish_config.video_profile_diy = { width: 640, height: 360, frameRate: 15, bitrate: 400 }
398
+ publish_config.publish_video_id = 'publish_video1'
399
+ publish_config.publish_streamId_id = 'publish_streamId1'
400
+ publish_config.publish_tag = 'tag1'
401
+ if (this.props.recordMode == 2) {
402
+ // 分行模式,只收音 不发布摄像头
403
+ publish_config.media_type = 2
404
+ // publish_config.publish_streamId_id = 'publish_video1'
405
+ }
406
+ this.test_controller.Publish(publish_config)
407
+
408
+ // this.publishAllScreen();
409
+ // 单独发布录制屏幕设备的流
410
+ // this.publishRecorderDevice()
327
411
 
328
- this.state.cameraList.forEach((el, i) => {
329
- let publish_config = {}
330
- publish_config.media_type = i==0? 1:3
331
- publish_config.publish_device = 1
332
- publish_config.videoSource = el.actionid
333
- publish_config.audioSource = this.state.microphoneValue
334
- publish_config.need_volume_analyser = true
335
- // publish_config.video_profile_type = 3
336
- publish_config.video_profile_type = 100
337
- publish_config.video_profile_diy = { width: 640, height: 360, frameRate: 15, bitrate: 400 }
338
- publish_config.publish_video_id = 'publish_video' + (i+1)
339
- publish_config.publish_streamId_id = 'publish_streamId' + (i+1)
340
- publish_config.publish_tag = 'tag' + (i+1)
341
- this.test_controller.Publish(publish_config)
342
- })
343
-
344
- // eslint-disable-next-line no-undef
345
- setTimeout(() => {
346
- if (this.state.imStatus && !this.state.imJoinRoom) {
347
- joinRoom((this.props.tellerAccount + '@' + JSON.parse(window.sessionStorage.getItem('sigData')).hostname), this.state.imRoomId)
348
- this.state.imJoinRoom = true
349
- this.saveLog('Join im room')
350
- console.log('加入IM房间')
351
- }
352
- })
353
412
  this.props.createRoomCallback({
354
413
  type: 1,
355
414
  errorManage: '',
@@ -438,9 +497,16 @@ class Video extends Component {
438
497
  // let result = await API.mpaasSig({account: data.account, type: data.type});
439
498
  console.log('mpaasSig', result, result.mpsSig);
440
499
  window.sessionStorage.setItem('alimpassSig', result.mpsSig);
441
- this.state.workSpaceId = result.workspaceId,
442
- this.state.appId = result.appId,
500
+ this.state.workSpaceId = result.workspaceId
501
+ this.state.appId = result.appId
443
502
  this.state.bizName = result.bizName
503
+
504
+ //asr初始化
505
+ this.state.asrAppKey = this.props.asrAppKey || result.asrAppKey
506
+ this.state.asrServerUrl = this.props.asrServerUrl || result.asrServerUrl
507
+ this.state.asrToken = this.props.asrToken || result.asrToken
508
+ this.initAsrRecorder()
509
+
444
510
  window.sessionStorage.setItem('sigData', JSON.stringify(result));
445
511
  if (data.sigType == 1) {
446
512
  this.handleEdit()
@@ -459,11 +525,6 @@ class Video extends Component {
459
525
  handleEdit = () => {
460
526
  console.log(JSON.parse(window.sessionStorage.getItem('sigData')));
461
527
  // eslint-disable-next-line no-undef
462
- // initWebSocket('wss://im.uat.dsp.hsbcfts.com.cn:443/wealth/im/ws/')
463
- if (!this.state.imStatus) {
464
- this.state.manualClose = false
465
- initWebSocket('wss://' + JSON.parse(window.sessionStorage.getItem('sigData')).hostname + ':' + JSON.parse(window.sessionStorage.getItem('sigData')).webPort + '/ws/');
466
- }
467
528
  const config_param = {};
468
529
  config_param.workspaceId = this.state.workSpaceId;
469
530
  config_param.uid = this.props.tellerAccount;
@@ -472,7 +533,7 @@ class Video extends Component {
472
533
  config_param.sign = window.sessionStorage.getItem('alimpassSig')
473
534
  config_param.room_server_url = this.props.roomServerUrl;
474
535
  // 允许最大断网时间 (超过未重连, 直接关闭)
475
- config_param.network_check_timeout = 10000;
536
+ config_param.network_check_timeout = 1200000; // sdk默认120秒。wpb要求一直重连,设定20分钟
476
537
  this.test_controller.Connect(config_param)
477
538
  this.saveLog('mrtc connect start')
478
539
  };
@@ -491,57 +552,56 @@ class Video extends Component {
491
552
  publish_streamId_id: 'publish_streamId1',
492
553
  publish_tag: 'tag1'
493
554
  },
494
- {
495
- publish_video_id: 'publish_video2',
496
- publish_streamId_id: 'publish_streamId2',
497
- publish_tag: 'tag2'
498
- },
499
- {
500
- publish_video_id: 'publish_video3',
501
- publish_streamId_id: 'publish_streamId3',
502
- publish_tag: 'tag3'
503
- }
555
+ // {
556
+ // publish_video_id: 'publish_video2',
557
+ // publish_streamId_id: 'publish_streamId2',
558
+ // publish_tag: 'tag2'
559
+ // },
560
+ // {
561
+ // publish_video_id: 'publish_video3',
562
+ // publish_streamId_id: 'publish_streamId3',
563
+ // publish_tag: 'tag3'
564
+ // }
504
565
  ];
505
566
  config_param.initSubscribe = [
506
567
  {
507
568
  subscribe_video_id: 'video1',
508
569
  subscribe_audio_id: 'audio1',
509
- subscribe_streamId_id: 'subscribe_streamId1',
510
570
  feedId_id: 'feedId1'
511
571
  },
512
572
  {
513
573
  subscribe_video_id: 'video2',
514
574
  subscribe_audio_id: 'audio2',
515
- subscribe_streamId_id: 'subscribe_streamId2',
516
575
  feedId_id: 'feedId2'
517
576
  },
518
577
  {
519
578
  subscribe_video_id: 'video3',
520
579
  subscribe_audio_id: 'audio3',
521
- subscribe_streamId_id: 'subscribe_streamId3',
522
580
  feedId_id: 'feedId3'
523
581
  },
524
582
  {
525
583
  subscribe_video_id: 'video4',
526
584
  subscribe_audio_id: 'audio4',
527
- subscribe_streamId_id: 'subscribe_streamId4',
528
585
  feedId_id: 'feedId4'
529
586
  },
530
587
  {
531
588
  subscribe_video_id: 'video5',
532
589
  subscribe_audio_id: 'audio5',
533
- subscribe_streamId_id: 'subscribe_streamId5',
534
590
  feedId_id: 'feedId5'
535
591
  },
536
592
  {
537
593
  subscribe_video_id: 'video6',
538
594
  subscribe_audio_id: 'audio6',
539
- subscribe_streamId_id: 'subscribe_streamId6',
540
595
  feedId_id: 'feedId6'
541
596
  }
542
597
  ];
543
598
  this.test_controller.InitRoomConfig(config_param)
544
599
  this.saveLog('mrtc InitRoomConfig start')
600
+
601
+ // 预热摄像头 (可能导致录屏插件发布时变成摄像头 以及重音问题,先注释掉)
602
+ // config_param.videoSource = this.state.cameraValue
603
+ // config_param.audioSource = this.state.microphoneValue
604
+ // this.test_controller.PreOpenLocalMedia(config_param)
545
605
  };
546
606
  rateAll = async () => {
547
607
  let data = ''
@@ -558,17 +618,18 @@ class Video extends Component {
558
618
  }
559
619
  }
560
620
  // 开启录制
561
- enableServerRecording = () => {
621
+ enableServerRecording = (record_business_id) => {
562
622
  const that = this
623
+ const SCALE = 1.5
563
624
  this.rateAll().then((res) => {
564
- console.log('退出房间者', res)
625
+ console.log('开启录制', res)
565
626
  let list = [
566
627
  {
567
628
  tag: 'projectionWhiteboard',
568
629
  xPosition: 0,
569
- yPosition: 175,
570
- width: 960,
571
- height: 540
630
+ yPosition: 175 * SCALE,
631
+ width: 1280,
632
+ height: 720
572
633
  },
573
634
  // {
574
635
  // tag: 'VIDEO_SOURCE_SCREEN_ONE',
@@ -588,68 +649,75 @@ class Video extends Component {
588
649
  tag: 'tag1',
589
650
  xPosition: 0,
590
651
  yPosition: 0,
591
- width: 213,
592
- height: 175
652
+ width: 213 * SCALE,
653
+ height: 175 * SCALE
593
654
  },
594
655
  {
595
- tag: 'tag2',
596
- xPosition: 213,
656
+ tag: 'customer1',
657
+ xPosition: 213 * SCALE,
597
658
  yPosition: 0,
598
- width: 213,
599
- height: 175
659
+ width: 213 * SCALE,
660
+ height: 175 * SCALE
600
661
  },
601
662
  {
602
- tag: 'tag3',
603
- xPosition: 426,
663
+ tag: 'customer2',
664
+ xPosition: 426 * SCALE,
604
665
  yPosition: 0,
605
- width: 213,
606
- height: 175
666
+ width: 213 * SCALE,
667
+ height: 175 * SCALE
607
668
  },
608
669
  {
609
- tag: 'customer1',
610
- xPosition: 639,
670
+ tag: 'customer3',
671
+ xPosition: 639 * SCALE,
611
672
  yPosition: 0,
612
- width: 213,
613
- height: 175
673
+ width: 213 * SCALE,
674
+ height: 175 * SCALE
614
675
  },
615
676
  {
616
- tag: 'customer2',
617
- xPosition: 852,
677
+ tag: 'customer4',
678
+ xPosition: 852 * SCALE,
618
679
  yPosition: 0,
619
- width: 213,
620
- height: 175
680
+ width: 213 * SCALE,
681
+ height: 175 * SCALE
621
682
  },
622
683
  {
623
- tag: 'customer3',
624
- xPosition: 1065,
684
+ tag: 'customer5',
685
+ xPosition: 1065 * SCALE,
625
686
  yPosition: 0,
626
- width: 213,
627
- height: 175
687
+ width: 213 * SCALE,
688
+ height: 175 * SCALE
628
689
  },
629
690
  {
630
- tag: 'customer4',
631
- xPosition: 1278,
691
+ tag: 'customer6',
692
+ xPosition: 1278 * SCALE,
632
693
  yPosition: 0,
633
- width: 213,
634
- height: 175
694
+ width: 213 * SCALE,
695
+ height: 175 * SCALE
635
696
  },
697
+ // {
698
+ // tag: 'sharedScreen', // 一期暂时不需要录制
699
+ // xPosition: 960 * SCALE,
700
+ // yPosition: 180 * SCALE,
701
+ // width: 320 * SCALE,
702
+ // height: 180 * SCALE
703
+ // }
636
704
  ]
637
705
  Array.isArray(res) ?
638
706
  res.map((item) => {
639
707
  list.push({
640
708
  tag: item.tag,
641
- xPosition: item.xaxis,
642
- yPosition: item.yaxis,
643
- width: item.width,
644
- height: item.height
709
+ xPosition: (item.xaxis * SCALE),
710
+ yPosition: (item.yaxis * SCALE),
711
+ width: (item.width * SCALE),
712
+ height: (item.height * SCALE)
645
713
  })
646
714
  }) :
647
715
  list.push({
648
716
  tag: 'VIDEO_SOURCE_SCREEN',
649
- xPosition: 960,
650
- yPosition: 535,
651
- width: 320,
652
- height: 180
717
+ xPosition: 960 * SCALE,
718
+ yPosition: 535 * SCALE,
719
+ width: 320 * SCALE,
720
+ height: 180 * SCALE
653
721
  })
654
722
  // list.push({
655
723
  // tag: 'VIDEO_SOURCE_SCREEN_19_9',
@@ -660,33 +728,98 @@ class Video extends Component {
660
728
  // })
661
729
  const filePath = 'recordId_' + new Date().valueOf();
662
730
  const recordParam = {};
663
- recordParam.width = 1280;
664
- recordParam.height = 720;
731
+ recordParam.width = 1280 * SCALE;
732
+ recordParam.height = 720 * SCALE;
665
733
  recordParam.recordTotalStream = 0;
666
734
  recordParam.startTimeout = 10;
667
735
  recordParam.splitType = 0;
668
736
  recordParam.endType = 1;
669
737
  recordParam.crf = 26
670
738
  recordParam.overlaps = [
739
+ {
740
+ tag: '', // 流 tag,如果不设置或为空,则为全局⽔印
741
+ type: 2, // 1 为时间戳⽔印;2 为⽂字⽔印;3 为图⽚⽔印
742
+ id: 2, // ⽔印 ID
743
+ enable: true,
744
+ xPosition: 16 * SCALE, // x 轴位置
745
+ yPosition: 8 * SCALE, // y 轴位置
746
+ text: `${this.props.recordMode ==1 ?'远程录制' :'网点录制'} ${this.state.salesBranchCode || ''} ${this.state.branchName || ''} ${this.state.financialOffice || ''}`,
747
+ fontSize: 16 * SCALE, // 字体⼤⼩
748
+ url: '' // ⽔印图⽚ HTTP 地址
749
+ },
671
750
  {
672
751
  tag: '', // 流 tag,如果不设置或为空,则为全局⽔印
673
752
  type: 1, // 1 为时间戳⽔印;2 为⽂字⽔印;3 为图⽚⽔印
674
753
  id: 1, // ⽔印 ID
675
754
  enable: true,
676
- xPosition: 1000, // x 轴位置
677
- yPosition: 10, // y 轴位置
755
+ xPosition: 1080 * SCALE, // x 轴位置
756
+ yPosition: 10 * SCALE, // y 轴位置
678
757
  text: '', // ⽔印⽂字
679
- fontSize: 16, // 字体⼤⼩
758
+ fontSize: 16 * SCALE, // 字体⼤⼩
680
759
  url: '' // ⽔印图⽚ HTTP 地址
681
760
  },
682
761
  ];
683
762
  recordParam.tagPositions = list
684
763
  console.log('recordParam', recordParam);
685
- that.test_controller.StartRemoteRecord(filePath, recordParam, '')
764
+ that.test_controller.StartRemoteRecord(filePath, recordParam, record_business_id)
686
765
 
687
766
  })
688
767
 
689
768
  };
769
+ // 开启ipad录制
770
+ enableIpadRecording = (record_business_id) => {
771
+ const that = this
772
+ const filePath = 'recordId_' + new Date().valueOf() + '_ipad';
773
+ const recordParam = {};
774
+ recordParam.width = 1280;
775
+ recordParam.height = 720;
776
+ recordParam.recordTotalStream = 0;
777
+ recordParam.startTimeout = 10;
778
+ recordParam.splitType = 0;
779
+ recordParam.endType = 1;
780
+ recordParam.crf = 26
781
+ recordParam.overlaps = [
782
+ {
783
+ tag: '', // 流 tag,如果不设置或为空,则为全局⽔印
784
+ type: 2, // 1 为时间戳⽔印;2 为⽂字⽔印;3 为图⽚⽔印
785
+ id: 2, // ⽔印 ID
786
+ enable: true,
787
+ xPosition: 16, // x 轴位置
788
+ yPosition: 8, // y 轴位置
789
+ text: `${this.props.recordMode ==1 ?'远程录制' :'网点录制'} ${this.state.salesBranchCode || ''} ${this.state.branchName || ''} ${this.state.financialOffice || ''}`,
790
+ fontSize: 16, // 字体⼤⼩
791
+ url: '' // ⽔印图⽚ HTTP 地址
792
+ },
793
+ {
794
+ tag: '', // 流 tag,如果不设置或为空,则为全局⽔印
795
+ type: 1, // 1 为时间戳⽔印;2 为⽂字⽔印;3 为图⽚⽔印
796
+ id: 1, // ⽔印 ID
797
+ enable: true,
798
+ xPosition: 1080, // x 轴位置
799
+ yPosition: 10, // y 轴位置
800
+ text: '', // ⽔印⽂字
801
+ fontSize: 16, // 字体⼤⼩
802
+ url: '' // ⽔印图⽚ HTTP 地址
803
+ },
804
+ ];
805
+ recordParam.tagPositions = [{
806
+ tag: that.state.ipadTag,
807
+ xPosition: 0,
808
+ yPosition: 0,
809
+ width: 1280,
810
+ height: 720
811
+ },{
812
+ tag: 'tag1',
813
+ xPosition: 0,
814
+ yPosition: 0,
815
+ width: 0,
816
+ height: 0
817
+ }]
818
+ // recordParam.tagFilter = that.state.ipadTag
819
+ // recordParam.layoutParam = [that.state.ipadTag, 'tag1'];
820
+ console.log('recordParam', recordParam);
821
+ that.test_controller.StartRemoteRecord(filePath, recordParam, record_business_id+'_ipad')
822
+ };
690
823
  // 结束会话
691
824
  endSession = value => {
692
825
  if (value == 'customerHangUp') {
@@ -698,6 +831,15 @@ class Video extends Component {
698
831
  })
699
832
  }
700
833
  };
834
+ sendMessage = (msg) => {
835
+ try {
836
+ console.log('发送消息', JSON.stringify(msg))
837
+ this.test_controller.SendTextMsg(JSON.stringify(msg))
838
+ } catch (err) {
839
+ console.error(`内部错误, msg = ${JSON.stringify(msg)} `)
840
+ console.error(err)
841
+ }
842
+ }
701
843
  errorCodeClick=(type,value)=>{
702
844
  if(type == 'ocr'){
703
845
  if(value == -1007 || value == -100701 || value == -100702 || value == -200001 || value == -300901 || value == -300902 || value == -400001) {
@@ -885,49 +1027,77 @@ class Video extends Component {
885
1027
  this.messageClick('当前暂无客户', 'error')
886
1028
  }
887
1029
  }
888
- messageClick = (value, valueOne) => {
889
- console.log(value, valueOne)
890
- if (messageValue != value) {
891
- messageValue = value
892
- dateTime = new Date().getTime()
893
- if (valueOne == 'error') {
1030
+ messageClick = (value, tipType, userId) => {
1031
+ console.log('messageClick', value, tipType)
1032
+
1033
+ if (userId) {
1034
+ // 画中画实时消息
1035
+ this.addPictureMessage(value, userId)
1036
+ }
1037
+ const intervalSec = 5 // 相同提示触发间隔
1038
+ const durationSec = 4.5 // 提示持续时间
1039
+ if (messageValueMap.get(value) == undefined) {
1040
+ // map中没有相同消息
1041
+ messageValueMap.set(value, setTimeout(() => {
1042
+ messageValueMap.delete(value)
1043
+ }, intervalSec * 1000))
1044
+
1045
+ if (tipType == 'error') {
894
1046
  message.error({
895
1047
  content: value,
896
1048
  icon: <img src={require("../../assets/img/tooltips2_fail.png").default} alt="" ></img>,
897
1049
  className: 'errorClassName',
898
1050
  top: 200,
899
- duration: 10
1051
+ duration: durationSec
900
1052
  })
901
- } else if (valueOne == 'success') {
1053
+ } else if (tipType == 'success') {
902
1054
  message.success({
903
1055
  content: value,
904
1056
  icon: <img src={require("../../assets/img/tooltips1_pass.png").default} alt="" ></img>,
905
1057
  className: 'successClassName',
906
1058
  top: 200,
907
- duration: 10
1059
+ duration: durationSec
908
1060
  })
909
1061
  }
910
- } else if (((new Date().getTime()) - dateTime) / 1000 > 30) {
911
- dateTime = new Date().getTime()
912
- if (valueOne == 'error') {
913
- message.error({
914
- content: value,
915
- icon: <img src={require("../../assets/img/tooltips2_fail.png").default} alt="" ></img>,
916
- className: 'errorClassName',
917
- top: 200,
918
- duration: 10
919
- })
920
- } else if (valueOne == 'success') {
921
- message.success({
922
- content: value,
923
- icon: <img src={require("../../assets/img/tooltips1_pass.png").default} alt="" ></img>,
924
- className: 'successClassName',
925
- top: 200,
926
- duration: 10
927
- })
1062
+ if (!userId) {
1063
+ // 坐席消息
1064
+ messageValue = value
1065
+
1066
+ clearTimeout(this.messageClearTimer)
1067
+ this.messageClearTimer = setTimeout(() => {
1068
+ messageValue = ''
1069
+ }, durationSec * 1000);
1070
+ }
1071
+ }
1072
+ }
1073
+ // 画中画内消息
1074
+ addPictureMessage = (value, userId) => {
1075
+ console.log('addPictureMessage', value, userId)
1076
+
1077
+ const intervalSec = 5 // 相同提示触发间隔
1078
+ const durationSec = 4.5 // 提示持续时间
1079
+ let mapItem = videoMessageMap.get(userId)
1080
+ if (!mapItem) {
1081
+ mapItem = {
1082
+ messageValue: value,
1083
+ clearTimer: null,
1084
+ valueMap: new Map()
928
1085
  }
929
1086
  }
930
-
1087
+ const valueMap = mapItem.valueMap
1088
+ if (valueMap.get(value) == undefined) {
1089
+ // map中没有相同消息
1090
+ valueMap.set(value, setTimeout(() => {
1091
+ valueMap.delete(value)
1092
+ }, intervalSec * 1000))
1093
+
1094
+ mapItem.messageValue = value
1095
+ clearTimeout(mapItem.clearTimer)
1096
+ mapItem.clearTimer = setTimeout(() => {
1097
+ mapItem.messageValue = ''
1098
+ }, durationSec * 1000)
1099
+ videoMessageMap.set(userId, mapItem)
1100
+ }
931
1101
  }
932
1102
  // 人脸识别
933
1103
  facialRecognition = () => {
@@ -939,6 +1109,112 @@ class Video extends Component {
939
1109
  this.selectCustomer('facial')
940
1110
  }
941
1111
  };
1112
+ generateMediaInfo = (sid) => {
1113
+ let that = this
1114
+ console.log(that.test_controller, sid)
1115
+ console.log(that.test_controller.GetMediaInfo(sid))
1116
+ let originalMediaInfo = that.test_controller.GetMediaInfo(sid);
1117
+ let mediaInfo = {
1118
+ peer_connection_: originalMediaInfo.peer_connection_,
1119
+ local_video_width: originalMediaInfo.local_video_width,
1120
+ local_video_height: originalMediaInfo.local_video_height,
1121
+ local_video_frame: originalMediaInfo.local_video_frame,
1122
+ local_video_bitrate: originalMediaInfo.local_video_bitrate,
1123
+ stream_type: originalMediaInfo.stream_type,
1124
+ stat_interval_: 3,
1125
+ video_send_packets_base_: 0,
1126
+ video_recv_packets_base_: 0,
1127
+ video_send_lost_pack_base_: 0,
1128
+ video_recv_lost_pack_base_: 0,
1129
+ audio_send_packets_base_: 0,
1130
+ audio_recv_packets_base_: 0,
1131
+ audio_send_lost_pack_base_: 0,
1132
+ audio_recv_lost_pack_base_: 0,
1133
+ video_send_qpsum_base: 0,
1134
+ video_send_frame_encoded_base: 0,
1135
+ video_recv_qpsum_base: 0,
1136
+ video_recv_frame_decoded_base: 0,
1137
+ video_send_bitrate_base_: 0,
1138
+ video_recv_bitrate_base_: 0,
1139
+ audio_send_bitrate_base_: 0,
1140
+ audio_recv_bitrate_base_: 0,
1141
+ };
1142
+ return mediaInfo;
1143
+ }
1144
+ detectNetworkWeak = (streamInfo) => {
1145
+ return new Promise((resolve, reject) => {
1146
+ const Total_Detect_Number = 3; // 触发弱网回调后,再连续检测3次
1147
+ let detectionsNumber = Total_Detect_Number;
1148
+ let finalResult = true
1149
+ let setTimer = () => {
1150
+ setTimeout(() => {
1151
+ this.test_controller.GetStats(streamInfo || this.mediaInfo).then(media_stat => {
1152
+ if (detectionsNumber> Total_Detect_Number-1) {
1153
+ // 不考虑第一次的评估结果,重新计算码率(因为刚触发弱网时的获取的码率总是非常大,原因不明)
1154
+ detectionsNumber--;
1155
+ setTimer()
1156
+ return
1157
+ }
1158
+ console.log('media_stat:')
1159
+ console.log(media_stat)
1160
+ // 分辨率、帧率
1161
+ let googAvailableSendBandwidth = (media_stat["VideoBwe"]["googAvailableSendBandwidth"] / 1000).toFixed(2);
1162
+ let googTransmitBitrate = (media_stat["VideoBwe"]["googTransmitBitrate"] / 1000).toFixed(2);
1163
+ let ssrcVideoSendLostRate = media_stat["ssrcVideoSend"]["lostRate"];
1164
+ let ssrcAudioSendLostRate = media_stat["ssrcAudioSend"]["lostRate"];
1165
+ let weak_googAvailableSendBandwidth = 200;
1166
+ // let weak_ssrcVideoSendLostRate = 0.20;
1167
+ // let weak_ssrcAudioSendLostRate = 0.20;
1168
+ let weak_str = "网络正常";
1169
+ if (googAvailableSendBandwidth < weak_googAvailableSendBandwidth) {
1170
+ weak_str = "当前网络不佳";
1171
+ }
1172
+ let bpsSend = (media_stat.ssrcVideoSend["bpsSend"] / 1000).toFixed(2)
1173
+ let bpsAudioSend = (media_stat.ssrcAudioSend["bpsSend"] / 1000).toFixed(2)
1174
+ let fps = media_stat["ssrcVideoSend"].googFrameRateSent
1175
+ let str =
1176
+ "带宽评估:" + (googAvailableSendBandwidth == undefined ? "none" : googAvailableSendBandwidth + "kbps") + "; "
1177
+ + "视频码率:" + bpsSend + "kb" + "; "
1178
+ + "音频码率:" + bpsAudioSend + "kb" + "; "
1179
+ + "视频丢包率:" + (ssrcVideoSendLostRate == undefined ? "none" : ssrcVideoSendLostRate + "%") + "; "
1180
+ + "音频丢包率:" + (ssrcAudioSendLostRate == undefined ? "none" : ssrcAudioSendLostRate + "%") + "; "
1181
+ + weak_str + "; "
1182
+ + "当前编码格式:" + media_stat["ssrcVideoSend"].googCodecName + "; "
1183
+ + "分辨率:" + media_stat["ssrcVideoSend"].resolution + "; "
1184
+ + "帧率:" + fps + '; '
1185
+ + "源帧率:" + media_stat["ssrcVideoSend"].googFrameRateInput;
1186
+ console.log('弱网', str)
1187
+
1188
+ let bpsResult = (bpsSend && bpsSend < 200 ) || (bpsAudioSend && bpsAudioSend < 200 )
1189
+ // 码率和带宽评估均低于200
1190
+ let result = bpsResult && (!googAvailableSendBandwidth || googAvailableSendBandwidth < weak_googAvailableSendBandwidth)
1191
+
1192
+ if (fps !== undefined) {
1193
+ // 丢包率>=10 或者帧率 <= 5
1194
+ let videoResult = (Number(ssrcVideoSendLostRate) >= 0.1 ) || fps <= 5
1195
+ console.log('丢包及帧率不满足', ssrcVideoSendLostRate, fps, videoResult)
1196
+ result = videoResult || result
1197
+ }
1198
+ if (result) {
1199
+ console.log('[!]弱网单次评估' + result);
1200
+ } else {
1201
+ finalResult = false
1202
+ console.log('弱网单次评估' + result);
1203
+ }
1204
+ if (detectionsNumber > 0 && finalResult) {
1205
+ detectionsNumber -= 1
1206
+ setTimer();
1207
+ } else {
1208
+ console.log('弱网综合检测结果:' + finalResult)
1209
+ resolve(finalResult)
1210
+ }
1211
+ });
1212
+
1213
+ }, 3000)
1214
+ }
1215
+ setTimer()
1216
+ })
1217
+ }
942
1218
  ocrClick = () => {
943
1219
  if (this.isFileSuccuse()) {
944
1220
  this.state.faceCustomerType = 2
@@ -954,6 +1230,10 @@ class Video extends Component {
954
1230
  streamShare.getTracks().forEach(track => track.stop());
955
1231
  streamShare = ''
956
1232
  }
1233
+ if (streamRecord) {
1234
+ streamRecord.getTracks().forEach(track => track.stop());
1235
+ streamRecord = ''
1236
+ }
957
1237
  this.finishSession()
958
1238
 
959
1239
  };
@@ -990,14 +1270,15 @@ class Video extends Component {
990
1270
  return a.order - b.order;
991
1271
  })
992
1272
  for (let i =1;i<=12;i++){
993
- if(document.getElementById('video'+i).name){
1273
+ if(sortedlist[i-1].videoName){
994
1274
  list.push({
995
- name: 'video' + i,
996
- title: sortedlist[i-1].videoName,
997
- mute: sortedlist[i-1].mute,
998
- noVideo: sortedlist[i-1].noVideo
999
- })
1000
- }
1275
+ name: 'video' + sortedlist[i-1].idIndex,
1276
+ title: sortedlist[i-1].videoName,
1277
+ mute: sortedlist[i-1].mute,
1278
+ noVideo: sortedlist[i-1].noVideo,
1279
+ userId: sortedlist[i-1].userId,
1280
+ })
1281
+ }
1001
1282
  }
1002
1283
  console.log(list)
1003
1284
  this.state.listVideoPicture = list
@@ -1029,11 +1310,18 @@ class Video extends Component {
1029
1310
  worker = new Worker(url);
1030
1311
  window.URL.revokeObjectURL(blob);
1031
1312
 
1032
-
1033
1313
  worker.onmessage = () => {
1034
- cobj.clearRect(0, 0, 640, 360 * this.state.listVideoPicture.length);
1314
+ const messageBoxHeight = 50;
1315
+ const recordBoxHeight = 50; // this.state.businessRecordId ? 50 : 0;
1316
+ const baseStartHeight = messageBoxHeight + recordBoxHeight
1317
+
1318
+ cobj.clearRect(0, 0, 640, 360 * this.state.listVideoPicture.length + baseStartHeight);
1035
1319
  canvas.width = 640;
1036
- canvas.height = 360 * this.state.listVideoPicture.length;
1320
+ canvas.height = 360 * this.state.listVideoPicture.length + baseStartHeight;
1321
+ if (this.state.listVideoPicture.length == 0) {
1322
+ // 画中画设置最小高度,避免没有人时 宽度被拉得很大
1323
+ canvas.height = 360 + baseStartHeight
1324
+ }
1037
1325
  for (let i = 0; i < this.state.listVideoPicture.length; i++) {
1038
1326
 
1039
1327
  let videoId = this.state.listVideoPicture[i].name;
@@ -1049,15 +1337,15 @@ class Video extends Component {
1049
1337
  }
1050
1338
  if (this.state.listVideoPicture[i].noVideo) {
1051
1339
  cobj.fillStyle = '#333';
1052
- cobj.fillRect((640 - newVideoWidth) / 2, 360 * i, newVideoWidth, newVideoHeight)
1340
+ cobj.fillRect((640 - newVideoWidth) / 2, 360 * i + baseStartHeight, newVideoWidth, newVideoHeight)
1053
1341
  } else {
1054
- cobj.drawImage(videoDiv, (640 - newVideoWidth) / 2, 360 * i, 640, 360);
1342
+ cobj.drawImage(videoDiv, (640 - newVideoWidth) / 2, 360 * i + baseStartHeight, 640, 360);
1055
1343
 
1056
1344
  }
1057
1345
  cobj.beginPath();
1058
1346
  cobj.strokeStyle = this.props.titleColor;
1059
1347
  cobj.fillStyle = this.props.titleBackground;
1060
- cobj.fillRect(0, 360 * (i + 1) - 60, 300, 60)
1348
+ cobj.fillRect(0, 360 * (i + 1) - 60 + baseStartHeight, 300, 60)
1061
1349
  cobj.fill();
1062
1350
  cobj.stroke();
1063
1351
  cobj.beginPath();
@@ -1075,12 +1363,12 @@ class Video extends Component {
1075
1363
  break;
1076
1364
  }
1077
1365
  }
1078
- cobj.strokeText(str, 70, 360 * (i + 1) - 20);
1366
+ cobj.strokeText(str, 70, 360 * (i + 1) - 20 + baseStartHeight);
1079
1367
  cobj.stroke();
1080
1368
  //左边框
1081
1369
  cobj.beginPath();
1082
- cobj.moveTo(0, 0);
1083
- cobj.lineTo(0, 360 * this.state.listVideoPicture.length);
1370
+ cobj.moveTo(0, 0 + baseStartHeight);
1371
+ cobj.lineTo(0, 360 * this.state.listVideoPicture.length + baseStartHeight);
1084
1372
  cobj.closePath(); //闭合路径
1085
1373
  cobj.lineWidth = 5; //线的边框为10像素
1086
1374
  cobj.strokeStyle = '#d9363e';
@@ -1088,8 +1376,8 @@ class Video extends Component {
1088
1376
 
1089
1377
  //下边框
1090
1378
  cobj.beginPath();
1091
- cobj.moveTo(0, 0);
1092
- cobj.lineTo(640, 0);
1379
+ cobj.moveTo(0, 0 + baseStartHeight);
1380
+ cobj.lineTo(640, 0 + baseStartHeight);
1093
1381
  cobj.closePath(); //闭合路径
1094
1382
  cobj.lineWidth = 5; //线的边框为10像素
1095
1383
  cobj.strokeStyle = '#d9363e';
@@ -1097,8 +1385,8 @@ class Video extends Component {
1097
1385
 
1098
1386
  //右边框
1099
1387
  cobj.beginPath();
1100
- cobj.moveTo(640, 360 * this.state.listVideoPicture.length);
1101
- cobj.lineTo(640, 0);
1388
+ cobj.moveTo(640, 360 * this.state.listVideoPicture.length + baseStartHeight);
1389
+ cobj.lineTo(640, 0 + baseStartHeight);
1102
1390
  cobj.closePath(); //闭合路径
1103
1391
  cobj.lineWidth = 5; //线的边框为10像素
1104
1392
  cobj.strokeStyle = '#d9363e';
@@ -1107,8 +1395,8 @@ class Video extends Component {
1107
1395
 
1108
1396
  //上边框
1109
1397
  cobj.beginPath();
1110
- cobj.moveTo(0, 360 * this.state.listVideoPicture.length);
1111
- cobj.lineTo(640, 360 * this.state.listVideoPicture.length);
1398
+ cobj.moveTo(0, 360 * this.state.listVideoPicture.length + baseStartHeight);
1399
+ cobj.lineTo(640, 360 * this.state.listVideoPicture.length + baseStartHeight);
1112
1400
  cobj.closePath(); //闭合路径
1113
1401
  cobj.lineWidth = 5; //线的边框为10像素
1114
1402
  cobj.strokeStyle = '#d9363e';
@@ -1118,10 +1406,11 @@ class Video extends Component {
1118
1406
  let microphoneSize = 50
1119
1407
  var img = document.getElementById("icon_huatong");
1120
1408
  var img1 = document.getElementById("icon_huatong_close");
1409
+ if (!this.state.listVideoPicture[i].title.includes(IPAD_SUFFIX)) {
1121
1410
  if (this.state.listVideoPicture[i].mute) {
1122
- cobj.drawImage(img1, 10, 360 * (i + 1) - 60, microphoneSize, microphoneSize);
1411
+ cobj.drawImage(img1, 10, 360 * (i + 1) - 60 + baseStartHeight, microphoneSize, microphoneSize);
1123
1412
  } else {
1124
- cobj.drawImage(img, 10, 360 * (i + 1) - 60, microphoneSize, microphoneSize);
1413
+ cobj.drawImage(img, 10, 360 * (i + 1) - 60 + baseStartHeight, microphoneSize, microphoneSize);
1125
1414
 
1126
1415
  // 绘制实时音量
1127
1416
  let sid = document.getElementById(this.state.listVideoPicture[i].name).name
@@ -1138,9 +1427,9 @@ class Video extends Component {
1138
1427
  // 以画布左上角为坐标原点
1139
1428
  let drawArea = {
1140
1429
  x1: 28 / 50 * microphoneSize + 10, // 波动范围右下角的点坐标
1141
- y1: 25 / 50 * microphoneSize + 360 * (i + 1) - 60,
1430
+ y1: 25 / 50 * microphoneSize + 360 * (i + 1) - 60 + baseStartHeight,
1142
1431
  x2: 22 / 50 * microphoneSize + 10, // 波动范围左上角的点坐标
1143
- y2: 10 / 50 * microphoneSize + 360 * (i + 1) - 60,
1432
+ y2: 10 / 50 * microphoneSize + 360 * (i + 1) - 60 + baseStartHeight,
1144
1433
  }
1145
1434
 
1146
1435
 
@@ -1164,12 +1453,74 @@ class Video extends Component {
1164
1453
  // requestAnimationFrame(aou.bind(this, analyser))
1165
1454
  )
1166
1455
  }
1456
+ }
1457
+ }
1167
1458
 
1168
-
1169
-
1459
+ // 绘制消息
1460
+ if (videoMessageMap.get(this.state.listVideoPicture[i].userId)) {
1461
+ let str = videoMessageMap.get(this.state.listVideoPicture[i].userId).messageValue
1462
+ if (str) {
1463
+ cobj.fillStyle = '#F8F2F3';
1464
+ cobj.font = "normal lighter 30px sans-serif";
1465
+ // const textWidth = Math.min(cobj.measureText(str).width, 610)
1466
+ const startY = 360 * i + baseStartHeight
1467
+ cobj.fillRect(0, startY, 640, messageBoxHeight)
1468
+ cobj.textAlign = 'center';
1469
+ cobj.strokeStyle = 'black';
1470
+ cobj.lineWidth = 2
1471
+ cobj.strokeText(str, 320, startY + messageBoxHeight - 15);
1472
+ cobj.stroke();
1473
+ }
1170
1474
  }
1171
1475
 
1172
1476
  }
1477
+ cobj.fillStyle = '#333333';
1478
+ cobj.fillRect(0, 0, 640, baseStartHeight)
1479
+ // 录制中状态
1480
+ if (this.state.businessRecordId) {
1481
+ let str = '· 录制中'
1482
+ // cobj.fillStyle = '#F8F2F3';
1483
+ cobj.font = "normal lighter 30px sans-serif";
1484
+ // cobj.fillRect(0, 0, 640, recordBoxHeight)
1485
+ cobj.textAlign = 'center';
1486
+ cobj.strokeStyle = 'red';
1487
+ cobj.lineWidth = 2
1488
+ cobj.strokeText(str, 320, recordBoxHeight - 15);
1489
+ cobj.stroke();
1490
+ }
1491
+ // 消息提示
1492
+ if (messageValue) {
1493
+ let str = messageValue
1494
+ cobj.fillStyle = '#F8F2F3';
1495
+ cobj.font = "normal lighter 30px sans-serif";
1496
+ // const textWidth = Math.min(cobj.measureText(str).width, 610)
1497
+ cobj.fillRect(0, recordBoxHeight, 640, messageBoxHeight)
1498
+ cobj.textAlign = 'center';
1499
+ cobj.strokeStyle = 'black';
1500
+ cobj.lineWidth = 2
1501
+ cobj.strokeText(str, 320, recordBoxHeight + messageBoxHeight - 15);
1502
+ cobj.stroke();
1503
+ }
1504
+
1505
+ // 敏感词提示
1506
+ // let str = this.state.sensitiveTitle || ''
1507
+ // if (str)
1508
+ // cobj.fillStyle = 'red';
1509
+ // cobj.font = "normal lighter 32px sans-serif";
1510
+ // const textWidth = Math.min(cobj.measureText(str).width, 610)
1511
+ // cobj.fillRect(320 - textWidth/ 2, 24, textWidth, 32)
1512
+ // cobj.textAlign = 'center';
1513
+ // cobj.strokeStyle = 'white';
1514
+ // cobj.lineWidth = 2
1515
+ // for (let k = 0; k < str.length; k++) {
1516
+ // if (cobj.measureText(str.substring(0, k + 1)).width > 610) {
1517
+ // str = str.substring(0, k - 2)
1518
+ // str += '...'
1519
+ // break;
1520
+ // }
1521
+ // }
1522
+ // cobj.strokeText(str, 320, 50);
1523
+ // cobj.stroke();
1173
1524
  };
1174
1525
 
1175
1526
  const captureStream = canvas.captureStream();
@@ -1182,17 +1533,37 @@ class Video extends Component {
1182
1533
 
1183
1534
  pictureInPictureVideo.addEventListener('enterpictureinpicture', (event) => {
1184
1535
  //可获取画中画窗口的一些数据,如宽高等
1536
+ console.log('开启画中画')
1185
1537
  pictureInPictureVideo.style.display = 'block';
1186
1538
  pictureInPictureVideo.play();
1187
1539
  this.state.isPictureInPicture = true
1540
+ clearTimeout(this.loopPlayTimer)
1188
1541
  });
1189
1542
 
1190
1543
  pictureInPictureVideo.addEventListener('leavepictureinpicture', (event) => {
1544
+ console.log('关闭画中画')
1191
1545
  pictureInPictureVideo.srcObject = null;
1192
1546
  pictureInPictureVideo.style.display = "none";
1193
1547
  this.state.listVideoPicture = []
1194
1548
  worker.postMessage(false);
1195
1549
  this.state.isPictureInPicture = false
1550
+
1551
+ clearTimeout(this.loopPlayTimer)
1552
+ // 画中画循环播放逻辑
1553
+ if (document.hidden && this.state.businessRecordId) {
1554
+ this.setState({
1555
+ isPictureConfirmModalVisible: true
1556
+ })
1557
+ this.loopPlay = () => {
1558
+ console.log('loopPlay status', this.state.isPictureInPicture);
1559
+ if(!this.state.isPictureInPicture && document.getElementById("publish_streamId1")){
1560
+ let audio = new Audio(PIPictureClosedAudio)
1561
+ audio.play()
1562
+ this.loopPlayTimer = setTimeout(this.loopPlay, 3000);
1563
+ }
1564
+ }
1565
+ setTimeout(this.loopPlay, 0);
1566
+ }
1196
1567
  });
1197
1568
 
1198
1569
  }
@@ -1260,9 +1631,8 @@ class Video extends Component {
1260
1631
  })
1261
1632
  }
1262
1633
  }
1263
- mountClick = () => {
1264
- window.IMEvt = msg => {
1265
- console.log(JSON.parse(msg));
1634
+ handleReceiveMsg = (msg) => {
1635
+ console.log(JSON.parse(msg));
1266
1636
  const Mival = JSON.parse(msg);
1267
1637
  if (Mival.typeId == 1210) {
1268
1638
  // 进行初始化操作
@@ -1295,6 +1665,7 @@ class Video extends Component {
1295
1665
  }, ()=>{
1296
1666
  this.pictureInPicture('Refresh')
1297
1667
  })
1668
+ this.messageClick('客户切换其他软件', 'error', Mival.data.userId)
1298
1669
  }
1299
1670
  }
1300
1671
  else if (Mival.typeId == 3003) { // app进入前台
@@ -1311,6 +1682,80 @@ class Video extends Component {
1311
1682
  })
1312
1683
  }
1313
1684
  }
1685
+ else if (Mival.typeId == 5001) { // 客户端离框
1686
+ let TITLE = '客户'
1687
+ if (Mival.data && Mival.data.userId) {
1688
+ if (Mival.data.userId.includes(IPAD_SUFFIX)) {
1689
+ TITLE = ''
1690
+ } else {
1691
+ TITLE = this.getUserTitle(Mival.data.userId)
1692
+ }
1693
+ }
1694
+ this.messageClick(TITLE+'人脸已离框', 'error', Mival.data.userId)
1695
+ // this.saveVideoPoint('ffd', '客户人脸离框');
1696
+ }
1697
+ else if (Mival.typeId == 5002) { // 客户端背光
1698
+ let TITLE = '客户'
1699
+ if (Mival.data && Mival.data.userId) {
1700
+ if (Mival.data.userId.includes(IPAD_SUFFIX)) {
1701
+ TITLE = ''
1702
+ } else {
1703
+ TITLE = this.getUserTitle(Mival.data.userId)
1704
+ }
1705
+ }
1706
+ this.messageClick(TITLE+'背光、曝光过度', 'error', Mival.data.userId)
1707
+ // this.saveVideoPoint('env', '客户端背光、曝光过度');
1708
+ }
1709
+ else if (Mival.typeId == 5003) { // 客户端弱网
1710
+ let TITLE = '客户'
1711
+ if (Mival.data && Mival.data.userId) {
1712
+ if (Mival.data.userId.includes(IPAD_SUFFIX)) {
1713
+ TITLE = 'iPad'
1714
+ } else {
1715
+ TITLE = this.getUserTitle(Mival.data.userId)
1716
+ }
1717
+ }
1718
+ this.messageClick(TITLE+'当前网络较弱', 'error', Mival.data.userId)
1719
+ // this.saveVideoPoint('wnd', '客户端弱网');
1720
+ }
1721
+ else if (Mival.typeId == 5004) { // ipad低电量
1722
+ this.messageClick('iPad电量过低', 'error', Mival.data.userId)
1723
+
1724
+ this.setState({
1725
+ ipadLowPowerErrorModalVisible: true,
1726
+ })
1727
+ // 循环播放ipad低电量
1728
+ clearTimeout(this.ipadLowPowerPlayTimer)
1729
+ this.ipadLowPowerPlay = () => {
1730
+ if(this.state.ipadLowPowerErrorModalVisible){
1731
+ if (this.lowPowerAudio) this.lowPowerAudio.pause()
1732
+ this.lowPowerAudio = new Audio(IpadLowPowerAudio)
1733
+ this.lowPowerAudio.play()
1734
+ this.ipadLowPowerPlayTimer = setTimeout(this.ipadLowPowerPlay, 3000);
1735
+ }
1736
+ }
1737
+ setTimeout(this.ipadLowPowerPlay, 0);
1738
+ }
1739
+ else if (Mival.typeId == 5005) { // 客户端人脸数量变化
1740
+ let TITLE = '客户'
1741
+ if (Mival.data && Mival.data.userId) {
1742
+ if (Mival.data.userId.includes(IPAD_SUFFIX)) {
1743
+ TITLE = ''
1744
+ } else {
1745
+ TITLE = this.getUserTitle(Mival.data.userId)
1746
+ }
1747
+ }
1748
+ this.messageClick(TITLE+'人脸数量发生变化', 'error', Mival.data.userId)
1749
+ }
1750
+ else if (Mival.typeId == 5006) { // 内网pib检测到敏感词
1751
+ this.messageClick(Mival.content, 'error', Mival.data.userId)
1752
+ }
1753
+ else if (Mival.typeId == 5007) { // ipad充电状态
1754
+ if (Mival.type == '1') { // 1充电 2不在充电
1755
+ this.setState({ ipadLowPowerErrorModalVisible: false})
1756
+ clearTimeout(this.ipadLowPowerPlayTimer)
1757
+ }
1758
+ }
1314
1759
  else if (Mival.typeId == 1220) {
1315
1760
  // 一炒多的图片 1214
1316
1761
  if (Mival.sessionId == this.state.sessionId) {
@@ -1341,6 +1786,9 @@ class Video extends Component {
1341
1786
  if (Mival.type == 1) {
1342
1787
  this.switchExternal()
1343
1788
  this.saveLog('whiteboard start, typeId=1218,')
1789
+ if (typeof this.props.sfpCallback === 'function'){
1790
+ this.props.sfpCallback()
1791
+ }
1344
1792
  } else if (Mival.type == 2) {
1345
1793
  if (streamShare) {
1346
1794
  streamShare.getTracks().forEach(track => track.stop());
@@ -1353,7 +1801,10 @@ class Video extends Component {
1353
1801
  })
1354
1802
  } else {
1355
1803
  if (document.getElementById('video20').name) {
1804
+ this.saveLog('unPublish share, reason: receive stop whiteboard message 1218')
1805
+ console.log('unPublish share, reason: receive stop whiteboard message 1218')
1356
1806
  this.test_controller.UnPublish(document.getElementById('video20').name)
1807
+ if(this.state.drawCanvasInterval) clearInterval(this.state.drawCanvasInterval)
1357
1808
  }
1358
1809
  this.setState({
1359
1810
  isWhiteboard: false
@@ -1364,6 +1815,13 @@ class Video extends Component {
1364
1815
 
1365
1816
  }
1366
1817
 
1818
+ } else if (Mival.typeId == 1219) {
1819
+ // 传入分行信息
1820
+ if (Mival.sessionId == this.state.sessionId && this.props.recordMode == 2) {
1821
+ this.state.salesBranchCode = Mival.salesBranchCode;
1822
+ this.state.financialOffice = Mival.financialOffice;
1823
+ this.state.branchName = Mival.salesBranchName;
1824
+ }
1367
1825
  } else if (Mival.typeId == 3100) {
1368
1826
  if(Mival.data.sessionId == this.state.sessionId) {
1369
1827
  muteJson.set(Mival.data.userId, JSON.stringify(Mival))
@@ -1384,6 +1842,27 @@ class Video extends Component {
1384
1842
 
1385
1843
  }
1386
1844
  }
1845
+ if (this.state.isPictureInPicture) {
1846
+ this.pictureInPicture('Refresh')
1847
+ }
1848
+ }
1849
+ } else if (Mival.typeId == 1214) {
1850
+ if (Mival.sessionId == this.state.sessionId) {
1851
+ this.setState({
1852
+ moduleData: Mival,
1853
+ isBackdrop: false
1854
+ }, ()=>{
1855
+ this.showModal('copy')
1856
+ })
1857
+ }
1858
+ } else if (Mival.typeId == 1213) {
1859
+ if (Mival.sessionId == this.state.sessionId) {
1860
+ this.setState({
1861
+ moduleData: Mival,
1862
+ isBackdrop: false
1863
+ }, ()=>{
1864
+ this.showModal('subscribe')
1865
+ })
1387
1866
  }
1388
1867
  } else if (Mival.typeId == 121305) {
1389
1868
  if (Mival.sessionId == this.state.sessionId) {
@@ -1419,33 +1898,25 @@ class Video extends Component {
1419
1898
  });
1420
1899
  let sid = document.getElementById('publish_video1').name || document.getElementById('publish_streamId1').name;
1421
1900
  this.test_controller.SetLocalAudioEnable(0, parseInt(sid, 10));
1422
- callNimIM('sendCustomCmdMsg', {
1423
- customId: this.state.imRoomId,
1424
- content: JSON.stringify({
1901
+ this.sendMessage({
1425
1902
  'typeId': 1013,
1426
1903
  'muteStatus': 1,
1427
1904
  'data': {
1428
1905
  'sessionId': this.state.sessionId,
1429
1906
  'userId': this.props.tellerAccount
1430
1907
  }
1431
- })
1432
- }, function (code, message, data) {
1433
- // console.log(data)
1434
1908
  })
1435
1909
  }
1436
1910
  document.getElementById('audio1').muted = true
1437
1911
  console.log('音频流静音')
1438
1912
  console.log(document.getElementById('audio1').muted)
1439
1913
  setTimeout(() => {
1440
- callNimIM('sendCustomCmdMsg', {
1441
- customId: this.state.imRoomId,
1442
- content: JSON.stringify({
1443
- 'typeId': 1223,
1444
- 'state': 1, // app解除静音
1445
- 'sessionId': this.state.sessionId,
1446
- 'userId': Mival.data.userId //this.seeList(this.state.roomCustomerList, 'feedId', document.getElementById('feedId1').innerText).uid
1447
- })
1448
- });
1914
+ this.sendMessage({
1915
+ 'typeId': 1223,
1916
+ 'state': 1, // app解除静音
1917
+ 'sessionId': this.state.sessionId,
1918
+ 'userId': Mival.data.userId //this.seeList(this.state.roomCustomerList, 'feedId', document.getElementById('feedId1').innerText).uid
1919
+ })
1449
1920
  }, 1000);
1450
1921
  }
1451
1922
  } else if (Mival.typeId == 1401) {
@@ -1459,37 +1930,194 @@ class Video extends Component {
1459
1930
  this.setState({
1460
1931
  videoList: this.state.videoList
1461
1932
  })
1933
+ if (this.state.isPictureInPicture) {
1934
+ this.pictureInPicture('Refresh')
1935
+ }
1936
+ }
1937
+ } else if (Mival.typeId == 10020) {
1938
+ // 录制中断(模拟测试)
1939
+ // this.messageClick('双录异常中断,请重新开启', 'error')
1940
+ // this.setState({
1941
+ // isRecordingeErrorModalVisible: true,
1942
+ // businessRecordId: '',
1943
+ // })
1944
+ // // 循环播放录制中断语音
1945
+ // clearTimeout(this.recordLoopPlayTimer)
1946
+ // this.recordLoopPlay = () => {
1947
+ // console.log('loop recordId', this.state.recordId, 'businessRecordId ', this.state.businessRecordId)
1948
+ // if(!this.state.businessRecordId && document.getElementById("publish_video1")){
1949
+ // let audio = new Audio(recordErrorAudio)
1950
+ // audio.play()
1951
+ // this.recordLoopPlayTimer = setTimeout(this.recordLoopPlay, 3000);
1952
+ // }
1953
+ // }
1954
+ // setTimeout(this.recordLoopPlay, 0);
1955
+
1956
+ } else if (Mival.typeId == 33001 && this.state.sessionId == Mival.data.sessionId) {
1957
+ if (Mival.type == 1) {
1958
+ this.saveAuthorize(Mival.data.userId)
1959
+ this.customerFaceClick(this.state.customerList[this.state.customerSelect - 1])
1960
+ }
1961
+ console.log('33001 done')
1962
+ } else if (Mival.typeId == 2210 && this.state.sessionId == Mival.sessionId) {
1963
+ if (Mival.status == 1) {
1964
+ // 开启了业务录制
1965
+ console.log('业务录制开启')
1966
+ this.state.businessId = Mival.id;
1967
+ this.saveLog('Start business recording')
1968
+ this.enableServerRecording( Mival.id)
1969
+ if (this.state.ipadTag) this.enableIpadRecording(Mival.id)
1970
+
1971
+ if (this.props.whetherDetectFace && this.props.recordMode != 2){
1972
+ this.startFaceDetection();
1973
+ }
1974
+ if (this.props.whetherDetectLight && this.props.recordMode != 2){
1975
+ this.startImageDetection();
1976
+ }
1977
+ if (this.props.whetherNeedAsr) {
1978
+ this.startASR();
1979
+ }
1980
+ } else if (Mival.status == 2) {
1981
+ // 关闭了业务录制
1982
+ console.log('业务录制关闭', this.state.businessRecordId)
1983
+ this.saveLog('Stop business recording')
1984
+ this.test_controller.StopRemoteRecord(this.state.businessRecordId)
1985
+ if (this.state.ipadRecordId) this.test_controller.StopRemoteRecord(this.state.ipadRecordId)
1986
+
1987
+ this.state.businessId = '';
1988
+ clearInterval(this.state.faceDetectionTimer);
1989
+ clearInterval(this.state.imageDetectionTimer);
1990
+ if(this.state.isAsrStart) this.stopASR();
1462
1991
  }
1992
+ } else if (Mival.typeId == 2002 && this.state.sessionId == Mival.sessionId) {
1993
+ // 会议到时间
1994
+ console.log('会议超过时间限制')
1995
+ this.endSessionValue();
1463
1996
  }
1464
- };
1465
- window.IMOpenfire = msg => {
1466
- console.log('im登录', msg)
1467
- if (msg.status == 'error') {
1468
- this.state.imStatus = false
1469
- this.saveLog('Im connection establishment failed')
1470
- this.roomCallBack(2, 'im建立连接失败', 5)
1471
- } else if (msg.status == 'success') {
1472
- this.state.imStatus = true
1473
- setTimeout(() => {
1474
- if (this.state.imRoomId && !this.state.imJoinRoom) {
1475
- joinRoom((this.props.tellerAccount + '@' + JSON.parse(window.sessionStorage.getItem('sigData')).hostname), this.state.imRoomId)
1476
- this.state.imJoinRoom = true
1477
- console.log('IMOpenfire 加入im房间')
1997
+ }
1998
+ getUserTitle = (userId) => {
1999
+ const user = this.state.videoList.find(el => el.userId == userId)
2000
+ if (!user) return '客户'
2001
+ if (user.isPIBIntranet) return '行内人员'
2002
+ else if (user.userSide == 1) return '访客'
2003
+ else return '客户'
2004
+ }
2005
+ startFaceDetection = () => {
2006
+ console.log('startFaceDetection!!!!')
2007
+ clearInterval(this.state.faceDetectionTimer);
2008
+ const timer = setInterval( async () => {
2009
+ const path = this.test_controller.TakePicture(0, 0, 0, document.getElementById("publish_video1").name, 'png')
2010
+ try {
2011
+ let result = await API.faceDetection({
2012
+ activityId: this.props.businessNumber,
2013
+ sessionId: `${this.props.tellerAccount}_${Date.now()}`,
2014
+ // sessionId: this.state.sessionId,
2015
+ roomId: this.state.channelId + '',
2016
+ appId: this.state.appId,
2017
+ recordId: this.state.recordId,
2018
+ base64Image: path.replace('data:image/png;base64,', '')
2019
+ });
2020
+ const changeNum = lastFaceNum - result.faceNum
2021
+ if (result.faceNum == 0) {
2022
+ // 人脸出框
2023
+ this.messageClick('检测到您的人脸已出框', 'error')
2024
+ this.saveVideoPoint('ffd', 'RM端人脸离框');
2025
+ } else if (lastFaceNum == 0 && result.faceNum == 1) {
2026
+ // 0->1不需要提示
2027
+ } else if (changeNum != 0) {
2028
+ this.messageClick('检测到参会人员数量发生变化', 'error')
2029
+ this.saveVideoPoint('fcd', 'RM端人脸数量发生变化');
2030
+ }
2031
+ lastFaceNum = result.faceNum;
2032
+ } catch (err) {
2033
+ console.error(err);
2034
+ if (err.status == 502 || err.status == 404) {
1478
2035
  }
1479
- }, 200);
1480
- } else if (msg.status == 'close') {
1481
- if (!this.state.manualClose) {
1482
- this.timer && clearInterval(this.timer);
1483
- this.state.imStatus = false
1484
- console.log('IMOpenfireclose')
1485
- this.saveLog('Repeated login of account')
1486
- this.roomCallBack(2, '账号重复登录', 9)
1487
-
1488
2036
  }
2037
+ }, this.props.faceDetectInterval * 1000);
1489
2038
 
2039
+ this.state.faceDetectionTimer = timer;
2040
+ }
2041
+ startImageDetection = () => {
2042
+ console.log('startImageDetection!!!!')
2043
+ clearInterval(this.state.imageDetectionTimer);
2044
+ const timer = setInterval( async () => {
2045
+ const path = this.test_controller.TakePicture(0, 0, 0, document.getElementById("publish_video1").name, 'png')
2046
+ const img = new Image()
2047
+ img.src = path;
2048
+ img.width = 300 //
2049
+ img.onload = () => {
2050
+ const origin = cv.imread(img)
2051
+ // let start = new Date().getTime()
2052
+ const res = isLight(origin, this.props.lightSensitivity)
2053
+ if (res==1 || res== -1){
2054
+ // 背景曝光过度
2055
+ this.messageClick('检测到当前背光、曝光过度', 'error')
2056
+ this.saveVideoPoint('expDark', 'RM端背光、曝光过度');
2057
+ }
2058
+ origin.delete()
2059
+ // let end = new Date().getTime()
2060
+ // console.log('执行时间(s) ', (end - start)/1000 )
1490
2061
  }
2062
+ }, this.props.lightDetectInterval * 1000);
1491
2063
 
2064
+ this.state.imageDetectionTimer = timer;
2065
+ }
2066
+ lightDetect() {
2067
+ try {
2068
+ if (document.getElementById("publish_video1").name) {
2069
+ const path = this.test_controller.TakePicture(0, 0, 0, document.getElementById("publish_video1").name, 'png')
2070
+ console.log('检测图像长度',path.length)
2071
+ const img = new Image()
2072
+ img.src = path;
2073
+ img.width = 300 //
2074
+ img.onload = () => {
2075
+ const origin = cv.imread(img)
2076
+ // let start = new Date().getTime()
2077
+ const res = isLight(origin, this.props.lightSensitivity)
2078
+ if (res==1 || res==-1){
2079
+ // 背景曝光过度
2080
+ this.state.envInfo.lightResult = '不合格'
2081
+ } else {
2082
+ this.state.envInfo.lightResult = '合格'
2083
+ }
2084
+ this.setState({
2085
+ envInfo: this.state.envInfo
2086
+ })
2087
+ origin.delete()
2088
+ }
2089
+ }
2090
+ // else {
2091
+ // setTimeout(() => {
2092
+ // this.lightDetect()
2093
+ // }, 1000);
2094
+ // }
2095
+ }catch(err){
2096
+ console.error(err)
2097
+ }
2098
+ }
2099
+ saveVideoPoint = async (code, content, prohibitedWords) => {
2100
+ try {
2101
+ let result = await API.saveVideoPoint({
2102
+ title: POINT_TYPE[code],
2103
+ content: [content],
2104
+ code,
2105
+ activityId: this.props.businessNumber,
2106
+ sessionId: this.state.sessionId,
2107
+ roomId: this.state.channelId + '',
2108
+ appId: this.state.appId,
2109
+ recordId: this.state.recordId,
2110
+ client: 'rm',
2111
+ prohibitedWords,
2112
+ customerId: this.props.tellerAccount
2113
+ });
2114
+ } catch (err) {
2115
+ console.error(err);
2116
+ if (err.status == 502 || err.status == 404) {
2117
+ }
1492
2118
  }
2119
+ }
2120
+ mountClick = () => {
1493
2121
  let data = {
1494
2122
  account: this.props.tellerAccount,
1495
2123
  type: '2',
@@ -1585,21 +2213,34 @@ class Video extends Component {
1585
2213
  }
1586
2214
  }
1587
2215
  console.log(objList, objList1, objList2)
2216
+ const cameraList = objList.filter(el => !el.actionname.includes(RECORD_DEVICE_NAME))
2217
+ const recorderDevice = objList.find(el => el.actionname.includes(RECORD_DEVICE_NAME))
1588
2218
  this.setState({
1589
- cameraList: objList,
2219
+ cameraList: cameraList,
2220
+ recorderDevice: recorderDevice,
1590
2221
  microphoneList: objList1,
1591
2222
  speakerList: objList2.length > 0 ? [objList2[0]] : []
1592
2223
  })
1593
2224
  let indexId = 0
1594
- objList.map((item, index) => {
1595
- if (item.actionname.indexOf('Integrated Camera') != -1) {
2225
+ let microId = 0
2226
+ // 摄像头设置默认
2227
+ objList.forEach((item, index) => {
2228
+ if (item.actionname.indexOf('HP Full-HD Camera') != -1) {
1596
2229
  indexId = index
2230
+ } else if (item.actionname.indexOf('Integrated Camera') != -1) {
2231
+ indexId = index
2232
+ }
2233
+ })
2234
+ // 麦克风设置默认
2235
+ objList1.forEach((item, index) => {
2236
+ if (item.actionname.indexOf('Microphone Array (Realtek High Definition Audio(SST))') != -1) {
2237
+ microId = index
1597
2238
  }
1598
2239
  })
1599
- console.log(indexId)
2240
+ console.log(indexId, microId)
1600
2241
  this.setState({
1601
2242
  cameraValue: objList[indexId].actionid,
1602
- microphoneValue: objList1[0].actionid
2243
+ microphoneValue: objList1[microId].actionid
1603
2244
  })
1604
2245
  if (!this.state.appId && !this.state.sessionType) {
1605
2246
  console.log('cameraValue', this.state.cameraValue)
@@ -1619,6 +2260,7 @@ class Video extends Component {
1619
2260
  this.state.sessionType = false
1620
2261
  this.messageClick('获取设备失败,请检查摄像头设备是否可用或是否禁用摄像头', 'error')
1621
2262
  this.roomCallBack(2, '获取设备失败', 1)
2263
+ this.showEnvDetection()
1622
2264
  };
1623
2265
  // 建立连接成功
1624
2266
  this.test_controller.OnConnectOK = () => {
@@ -1667,6 +2309,10 @@ class Video extends Component {
1667
2309
  this.state.rtoken = rtoken
1668
2310
  this.createRoom()
1669
2311
  this.saveLog('RM mrtc create room successfully, room_id=' + room_id)
2312
+
2313
+ this.state.imStatus = true
2314
+ this.saveLog('Join im room')
2315
+ console.log('加入IM房间')
1670
2316
  };
1671
2317
  // 创建房间失败
1672
2318
  this.test_controller.OnCreateRoomFailed = (err_code, err_msg) => {
@@ -1687,13 +2333,19 @@ class Video extends Component {
1687
2333
  };
1688
2334
  // 音视频关闭通知
1689
2335
  this.test_controller.OnMediaClose = (code, sid) => {
1690
- console.log(code, sid)
2336
+ console.log('OnMediaClose',code, sid)
1691
2337
  if (code == 5003 || code == 5004 || code == 5005 || code == 5007 || code == 5009 || code == 5010 || code == 5011 || code == 5012) {
1692
- if (sid == document.getElementById('publish_video1').name) {
2338
+ if (sid == this.state.publishSid) {
1693
2339
  this.saveLog('Audio and video close notification,' + code)
1694
2340
  this.roomCallBack(2, '音视频异常关闭', 8)
1695
- } else {
2341
+ } else if (sid == this.state.publishScreenSid) {
1696
2342
  this.state.isScreenSwitching = false
2343
+ this.setSharedScreenState(false)
2344
+ if (code == 5012) {
2345
+ this.saveLog('Manual cancel share'); // 点了取消,拒绝系统授权
2346
+ } else {
2347
+ this.saveLog('System error stop share, code=' + code);
2348
+ }
1697
2349
  }
1698
2350
  }
1699
2351
  };
@@ -1701,24 +2353,38 @@ class Video extends Component {
1701
2353
  this.test_controller.OnJoinRoomSucc = () => {
1702
2354
  console.log('加入房间成功')
1703
2355
 
1704
- this.state.cameraList.forEach((el, i) => {
1705
- let publish_config = {}
1706
- publish_config.media_type = i==0? 1:3
1707
- publish_config.publish_device = 1
1708
- publish_config.videoSource = el.actionid
1709
- publish_config.audioSource = this.state.microphoneValue
1710
- publish_config.need_volume_analyser = true
1711
- // publish_config.video_profile_type = 3
1712
- publish_config.video_profile_type = 100
1713
- publish_config.video_profile_diy = { width: 640, height: 360, frameRate: 15, bitrate: 400 }
1714
- publish_config.publish_video_id = 'publish_video' + (i+1)
1715
- publish_config.publish_streamId_id = 'publish_streamId' + (i+1)
1716
- publish_config.publish_tag = 'tag' + (i+1)
1717
- this.test_controller.Publish(publish_config)
1718
- })
2356
+ let publish_config = {}
2357
+ publish_config.media_type = 1
2358
+ publish_config.publish_device = 1
2359
+ publish_config.videoSource = this.state.cameraValue
2360
+ publish_config.audioSource = this.state.microphoneValue
2361
+ publish_config.need_volume_analyser = true
2362
+ // publish_config.video_profile_type = 3
2363
+ publish_config.video_profile_type = 100
2364
+ publish_config.video_profile_diy = { width: 640, height: 360, frameRate: 15, bitrate: 400 }
2365
+ publish_config.publish_video_id = 'publish_video1'
2366
+ publish_config.publish_streamId_id = 'publish_streamId1'
2367
+ publish_config.publish_tag = 'tag1'
2368
+ if (this.props.recordMode == 2) {
2369
+ // 分行模式,只收音 不发布摄像头
2370
+ publish_config.media_type = 2
2371
+ // publish_config.publish_streamId_id = 'publish_video1'
2372
+ }
2373
+ this.test_controller.Publish(publish_config)
2374
+
2375
+ // this.publishAllScreen();
2376
+ // 单独发布录制屏幕设备的流
2377
+ // this.publishRecorderDevice()
1719
2378
 
1720
2379
  this.roomCallBack(1, '', 0)
1721
2380
  this.saveLog('mrtc join room success')
2381
+
2382
+ this.state.imStatus = true
2383
+ this.saveLog('Join im room')
2384
+ console.log('加入IM房间')
2385
+
2386
+ // 如果重新加入房间,手动重置一下投屏状态
2387
+ this.setSharedScreenState(false)
1722
2388
  };
1723
2389
  // 加入房间失败
1724
2390
  this.test_controller.OnJoinRoomFailed = (err_code, err_msg) => {
@@ -1733,12 +2399,9 @@ class Video extends Component {
1733
2399
  this.state.rtoken = '',
1734
2400
  this.state.sessionId = '',
1735
2401
  this.state.imRoomId = ''
1736
- this.state.imJoinRoom = false
1737
2402
  if (this.state.imStatus) {
1738
2403
  console.log('disconnect断开连接')
1739
- this.state.manualClose = true
1740
2404
  this.state.imStatus = false
1741
- disconnect();
1742
2405
  }
1743
2406
  this.test_controller.Disconnect()
1744
2407
  let data = {
@@ -1749,71 +2412,24 @@ class Video extends Component {
1749
2412
  this.mpaasSig(data);
1750
2413
  };
1751
2414
  this.test_controller.OnSendTextMsgSucc = (msgId) => {
1752
- console.log('发送成功', msgId)
1753
- this.setState({
1754
- documentError: '',
1755
- isModalVisibleCustomer: false,
1756
- })
1757
- this.saveLog('mrtc OnSendTextMsgSucc:' + msgId)
2415
+ // console.log('发送成功', msgId)
2416
+ // this.saveLog('mrtc OnSendTextMsgSucc:' + msgId)
1758
2417
  }
1759
2418
  this.test_controller.OnSendTextMsgFailed = (msgId, code, msg) => {
1760
2419
  console.log('发送失败', msgId, code, msg)
1761
- this.setState({
1762
- documentError: '推送授权白板失败,请重试'
1763
- })
2420
+ const Mival = JSON.parse(msg)
2421
+ // 失败处理
2422
+ if (Mival.typeId == '3300') {
2423
+ this.setState({
2424
+ documentError: '推送授权白板失败,请重试'
2425
+ })
2426
+ }
1764
2427
  this.saveLog('mrtc OnSendTextMsgFail:' + msgId +', code=' + code + ',msg=' + msg)
1765
2428
  }
1766
2429
  this.test_controller.OnReceiveTextMsg = (uid, msg) => {
1767
- console.log('收到手机端消息', uid, msg, JSON.parse(msg).typeId, JSON.parse(msg).data.sessionId, this.state.sessionId)
1768
- if (JSON.parse(msg).typeId == 33001 && this.state.sessionId == JSON.parse(msg).data.sessionId) {
1769
- if (JSON.parse(msg).type == 1) {
1770
- this.saveAuthorize(JSON.parse(msg).data.userId)
1771
- this.customerFaceClick(this.state.customerList[this.state.customerSelect - 1])
1772
- }
1773
- }
1774
- // 线下demo静音处理
1775
- if (JSON.parse(msg).typeId == 4004 && this.state.sessionId == JSON.parse(msg).data.sessionId) {
1776
- if (this.isFileSuccuse()) {
1777
- if (!this.state.voiceStatue) {
1778
- // 静音本地
1779
- this.setState({
1780
- voiceStatue: true,
1781
- voiceImg: voiceImgCloe,
1782
- voiceName: '解除静音'
1783
- });
1784
- let sid = document.getElementById('publish_video1').name || document.getElementById('publish_streamId1').name;
1785
- this.test_controller.SetLocalAudioEnable(0, parseInt(sid, 10));
1786
- callNimIM('sendCustomCmdMsg', {
1787
- customId: this.state.imRoomId,
1788
- content: JSON.stringify({
1789
- 'typeId': 1013,
1790
- 'muteStatus': 1,
1791
- 'data': {
1792
- 'sessionId': this.state.sessionId,
1793
- 'userId': this.props.tellerAccount
1794
- }
1795
- })
1796
- }, function (code, message, data) {
1797
- // console.log(data)
1798
- })
1799
- }
1800
- document.getElementById('audio1').muted = true
1801
- console.log('音频流静音')
1802
- console.log(document.getElementById('audio1').muted)
1803
- setTimeout(() => {
1804
- callNimIM('sendCustomCmdMsg', {
1805
- customId: this.state.imRoomId,
1806
- content: JSON.stringify({
1807
- 'typeId': 1223,
1808
- 'state': 1, // app解除静音
1809
- 'sessionId': this.state.sessionId,
1810
- 'userId': uid //this.seeList(this.state.roomCustomerList, 'feedId', document.getElementById('feedId1').innerText).uid
1811
- })
1812
- });
1813
- }, 1000);
1814
- }
1815
- }
1816
- this.saveLog('mrtc OnReceiveTextMsg info:' + msg)
2430
+ console.log('收到手机端消息',uid, msg, JSON.parse(msg))
2431
+ // this.saveLog('mrtc OnReceiveTextMsg info:' + msg)
2432
+ this.handleReceiveMsg(msg)
1817
2433
  }
1818
2434
  this.test_controller.StreamFilterHandler = async (publish_tag, stream, stream_type, publish_device, media_type) => {
1819
2435
  console.log(`stream processed by client, publish_device=${publish_device}, media_type=${media_type}, publish_tag=${publish_tag},stream_type=${stream_type}`);
@@ -1829,28 +2445,13 @@ class Video extends Component {
1829
2445
  if (publish_tag == 'tag1') {
1830
2446
  console.log('tag1', stream)
1831
2447
  let newStream = stream;
1832
- // if (stream.getVideoTracks()[0]) {
1833
- // await startBeauty(newStream);
1834
- // newStream = beautyCaptureStream();
1835
- // // 清理原始流
1836
- // newStream.oninactive = function () {
1837
- // clearOriginStream(stream);
1838
- // };
1839
- // newStream.getVideoTracks()[0].onended = function () {
1840
- // clearOriginStream(stream);
1841
- // };
1842
- // function clearOriginStream(stream) {
1843
- // stream.getTracks().forEach((track) => {
1844
- // track.stop();
1845
- // });
1846
- // stream = null;
1847
- // }
1848
- // };
1849
2448
  if (stream.getVideoTracks()[0]) {
1850
- await startBeauty(newStream);
1851
- newStream = beautyCaptureStream();
1852
- await startHs(newStream);
1853
- newStream = hsCaptureStream();
2449
+ if (this.state.beautyType || isSuccuseHs){
2450
+ await startBeauty(newStream);
2451
+ newStream = beautyCaptureStream();
2452
+ await startHs(newStream);
2453
+ newStream = hsCaptureStream();
2454
+ }
1854
2455
  // 清理原始流
1855
2456
  newStream.oninactive = function () {
1856
2457
  clearOriginStream(stream);
@@ -1871,11 +2472,30 @@ class Video extends Component {
1871
2472
  return newStream
1872
2473
  }
1873
2474
 
1874
- if (publish_tag == 'projectionWhiteboard' && publish_device == 2) {
1875
- // this.graffiti()
1876
- console.log('projectionWhiteboard', stream)
2475
+ if (publish_tag == 'projectionWhiteboard' && (publish_device == 2 || publish_device == 5)) {
1877
2476
  let newStream1 = stream;
1878
2477
  if (stream.getVideoTracks()[0]) {
2478
+ try {
2479
+ console.log('共享')
2480
+ console.log(stream.getVideoTracks()[0])
2481
+ if ( stream.getVideoTracks()[0] instanceof BrowserCaptureMediaStreamTrack) {
2482
+ console.log('tab共享')
2483
+ this.saveLog('Share type = tab')
2484
+ } else if (stream.getVideoTracks()[0] instanceof MediaStreamTrack && stream.getVideoTracks()[0].label.includes('screen')) {
2485
+ console.log('屏幕共享')
2486
+ this.saveLog('Share type = screen')
2487
+ } else if (stream.getVideoTracks()[0].label.includes('window')){
2488
+ console.log('窗口共享')
2489
+ this.saveLog('Share type = window')
2490
+ } else if (stream.getVideoTracks()[0] instanceof CanvasCaptureMediaStreamTrack){
2491
+ console.log('白板共享')
2492
+ this.saveLog('Share type = whiteboard')
2493
+ }
2494
+ } catch (err) {
2495
+ console.log('不支持此浏览器记录投屏类型日志')
2496
+ console.log(navigator.userAgent)
2497
+ console.log(err)
2498
+ }
1879
2499
  if (this.state.operateShow) {
1880
2500
  await startMix(newStream1, 'mix');
1881
2501
 
@@ -1887,9 +2507,12 @@ class Video extends Component {
1887
2507
  canvas.width = this.state.widthVideo
1888
2508
  } else {
1889
2509
  await startMix(newStream1, 'none');
2510
+ isGraffiti = false
1890
2511
  }
1891
2512
 
1892
2513
  newStream1 = mixCaptureStream();
2514
+ newStream1.getVideoTracks()[0].contentHint = "text"; // 解决清晰度问题
2515
+
1893
2516
  console.log('projectionWhiteboard1', newStream1)
1894
2517
  // 清理原始流
1895
2518
  newStream1.oninactive = function () {
@@ -1905,60 +2528,64 @@ class Video extends Component {
1905
2528
  stream = null;
1906
2529
  }
1907
2530
  }
2531
+ if (stream.getAudioTracks()[0] && newStream1.addTrack) {
2532
+ newStream1.addTrack(stream.getAudioTracks()[0])
2533
+ }
1908
2534
  return newStream1
1909
- } else {
1910
- return stream
1911
2535
  }
1912
-
2536
+ return stream
1913
2537
  }
1914
2538
  // 发布媒体流成功
1915
2539
  this.test_controller.OnPublishSucc = (sid) => {
1916
2540
  console.log('发布媒体流成功', sid)
1917
2541
  this.state.sessionType = true
1918
2542
  if (sid == document.getElementById('video20').name) {
1919
- callNimIM('sendCustomCmdMsg', {
1920
- customId: this.state.imRoomId,
1921
- content: JSON.stringify({
1922
- 'typeId': 2030,
1923
- 'sessionId': this.state.sessionId,
1924
- 'sharedScreen': 1,
1925
- 'tellerId': this.props.tellerAccount
1926
- })
1927
- });
2543
+ this.state.publishScreenSid = document.getElementById('video20').name
2544
+ this.setSharedScreenState(true)
2545
+ this.saveLog('Share success')
2546
+ this.sendMessage({
2547
+ 'typeId': 2030,
2548
+ 'sessionId': this.state.sessionId,
2549
+ 'sharedScreen': 1,
2550
+ 'tellerId': this.props.tellerAccount
2551
+ })
1928
2552
  if (this.state.screenName == '切换共享') {
1929
2553
  this.state.isSharedScreen = true
1930
2554
  this.state.isScreenSwitching = false
1931
2555
  }
2556
+ this.videoInfo = this.generateMediaInfo(document.getElementById("video20").name);
1932
2557
  }
1933
- if (sid == document.getElementById('publish_video1').name) {
1934
-
2558
+ if (sid == document.getElementById('publish_streamId1').name) {
2559
+ this.state.publishSid = document.getElementById('publish_streamId1').name
1935
2560
  this.setState({
1936
2561
 
1937
2562
  loading: false,
1938
2563
  });
2564
+ setTimeout(() => {
2565
+ this.showEnvDetection()
2566
+ }, 1500);
2567
+
1939
2568
 
1940
2569
  this.enterRoom()
1941
2570
  this.updateMeetingInfo()
1942
2571
  this.timer = setInterval(
1943
2572
  () => {
1944
2573
  if (!this.state.voiceStatue && this.state.analyserHeight.get(sid).toFixed(2) > 0.1) {
1945
- callNimIM('sendCustomCmdMsg', {
1946
- customId: this.state.imRoomId,
1947
- content: JSON.stringify({
1948
- 'typeId': 3200,
1949
- 'decibelValue': this.state.analyserHeight.get(sid).toFixed(2),
1950
- "data": {
1951
- 'sessionId': this.state.sessionId,
1952
- 'userId': this.props.tellerAccount,
1953
- 'data': (new Date()).valueOf()
1954
- }
1955
-
1956
- })
1957
- });
2574
+ this.sendMessage({
2575
+ 'typeId': 3200,
2576
+ 'decibelValue': this.state.analyserHeight.get(sid).toFixed(2),
2577
+ "data": {
2578
+ 'sessionId': this.state.sessionId,
2579
+ 'userId': this.props.tellerAccount,
2580
+ 'data': (new Date()).valueOf()
2581
+ }
2582
+ })
1958
2583
  }
1959
2584
  },
1960
2585
  1000
1961
2586
  );
2587
+ this.mediaInfo = this.generateMediaInfo(document.getElementById("publish_streamId1").name);
2588
+
1962
2589
  } else {
1963
2590
  var box = document.getElementById("whiteboardDIV");
1964
2591
  var box1 = document.getElementById("operate")
@@ -1980,11 +2607,13 @@ class Video extends Component {
1980
2607
  this.test_controller.OnPublishFailed = (sid, err_code, err_msg) => {
1981
2608
  this.saveLog('mrtc OnPublishFailed 发布失败, code=' + err_code)
1982
2609
  console.log('Publishing media stream failed,', sid, err_code, err_msg)
1983
- if (sid == document.getElementById('publish_video1').name) {
2610
+ if (sid == document.getElementById('publish_streamId1').name) {
1984
2611
  this.state.sessionType = false
1985
2612
  this.roomCallBack(2, '发布失败', 4)
1986
2613
  } else {
1987
2614
  this.messageClick('投屏失败请重新投屏', 'error')
2615
+ this.setSharedScreenState(false)
2616
+ this.saveLog('Share fail, code=' + err_code)
1988
2617
  }
1989
2618
 
1990
2619
  };
@@ -2033,6 +2662,14 @@ class Video extends Component {
2033
2662
  participants.map((item, index) => {
2034
2663
  if (item.uid != this.state.tellerAccount) {
2035
2664
  item.publish.map((itemOne, indexOne) => {
2665
+ if (itemOne.tag && itemOne.tag.includes('UnSubscribe_RM')) {
2666
+ console.log('过滤订阅的tag:', itemOne.tag)
2667
+ return
2668
+ }
2669
+ if (itemOne.mediaSource == 'VIDEO_SOURCE_CAMERA' && item.uid.includes(IPAD_SUFFIX)) {
2670
+ this.state.ipadTag = itemOne.tag;
2671
+ console.log('ipadTag:', itemOne.tag)
2672
+ }
2036
2673
  let array = this.state.roomCustomerList;
2037
2674
  let newArray = [...array];
2038
2675
  newArray.push({
@@ -2048,8 +2685,6 @@ class Video extends Component {
2048
2685
  config_param = {
2049
2686
  subscribe_video_id: 'video21',
2050
2687
  subscribe_audio_id: 'audio21',
2051
- subscribe_streamId_id: 'subscribe_streamId21',
2052
- feedId_id: 'feedId21',
2053
2688
  feedId: itemOne.feedId
2054
2689
  }
2055
2690
 
@@ -2063,8 +2698,6 @@ class Video extends Component {
2063
2698
  config_param = {
2064
2699
  subscribe_video_id: 'video20',
2065
2700
  subscribe_audio_id: 'audio20',
2066
- subscribe_streamId_id: 'subscribe_streamId20',
2067
- feedId_id: 'feedId20',
2068
2701
  feedId: itemOne.feedId
2069
2702
  }
2070
2703
 
@@ -2080,7 +2713,6 @@ class Video extends Component {
2080
2713
  config_param = {
2081
2714
  subscribe_video_id: 'video'+i,
2082
2715
  subscribe_audio_id: 'audio'+i,
2083
- subscribe_streamId_id: 'subscribe_streamId'+i,
2084
2716
  feedId_id: 'feedId'+i,
2085
2717
  feedId: itemOne.feedId
2086
2718
  }
@@ -2093,6 +2725,7 @@ class Video extends Component {
2093
2725
  console.log(config_param)
2094
2726
  console.log('发起订阅')
2095
2727
  this.test_controller.Subscribe(config_param)
2728
+ document.getElementById(config_param.subscribe_video_id).name = 'temp'
2096
2729
 
2097
2730
  }
2098
2731
  })
@@ -2105,27 +2738,34 @@ class Video extends Component {
2105
2738
  console.log('新加⼊房间者', participant);
2106
2739
  this.saveLog('mrtc someone joined room, userId=' + participant)
2107
2740
  this.state.isCustomer = true
2741
+
2742
+ if (participant.includes(IPAD_SUFFIX) && this.state.businessId){
2743
+ this.saveVideoPoint('padConnected', 'ipad已连接');
2744
+ }
2745
+ if (participant.includes(H5_SUFFIX)){
2746
+ this.messageClick('客户端已就绪,可进行签署', 'error')
2747
+ if (typeof this.props.h5JoinCallback === 'function'){
2748
+ this.props.h5JoinCallback()
2749
+ }
2750
+ }
2108
2751
  };
2109
2752
  // 推送“有新发布”给与会者
2110
2753
  this.test_controller.OnNewPublish = (feed) => {
2111
2754
  console.log('有新发布者', feed);
2112
2755
  console.log(new Date())
2113
- callNimIM('sendCustomCmdMsg', {
2114
- customId: this.state.imRoomId,
2115
- content: JSON.stringify({
2756
+ if (feed.tag && feed.tag.includes('UnSubscribe_RM')) {
2757
+ console.log('过滤订阅的tag:', feed.tag)
2758
+ return
2759
+ }
2760
+ this.sendMessage({
2116
2761
  'typeId': 1013,
2117
2762
  'muteStatus': this.state.voiceStatue ? 1 : 0,
2118
2763
  'data': {
2119
2764
  'sessionId': this.state.sessionId,
2120
2765
  'userId': this.props.tellerAccount
2121
2766
  }
2122
- })
2123
- }, function (code, message, data) {
2124
- console.log(data)
2125
2767
  })
2126
- callNimIM('sendCustomCmdMsg', {
2127
- customId: this.state.imRoomId,
2128
- content: JSON.stringify({
2768
+ this.sendMessage({
2129
2769
  'typeId': 1014,
2130
2770
  'sessionId': this.state.sessionId,
2131
2771
  'meetingInfo': {
@@ -2134,9 +2774,6 @@ class Video extends Component {
2134
2774
  'customers': this.props.meetingInfo.customers,
2135
2775
  'otherAttendees': this.props.meetingInfo.otherAttendees
2136
2776
  }
2137
-
2138
- })
2139
- }, function (code, message, data) {
2140
2777
  })
2141
2778
  this.sendNotification()
2142
2779
  let array = this.state.roomCustomerList;
@@ -2155,8 +2792,6 @@ class Video extends Component {
2155
2792
  config_param = {
2156
2793
  subscribe_video_id: 'video21',
2157
2794
  subscribe_audio_id: 'audio21',
2158
- subscribe_streamId_id: 'subscribe_streamId21',
2159
- feedId_id: 'feedId21',
2160
2795
  feedId: feed.feedId
2161
2796
  }
2162
2797
 
@@ -2176,8 +2811,6 @@ class Video extends Component {
2176
2811
  config_param = {
2177
2812
  subscribe_video_id: 'video20',
2178
2813
  subscribe_audio_id: 'audio20',
2179
- subscribe_streamId_id: 'subscribe_streamId20',
2180
- feedId_id: 'feedId20',
2181
2814
  feedId: feed.feedId
2182
2815
  }
2183
2816
 
@@ -2199,7 +2832,6 @@ class Video extends Component {
2199
2832
  config_param = {
2200
2833
  subscribe_video_id: 'video'+i,
2201
2834
  subscribe_audio_id: 'audio'+i,
2202
- subscribe_streamId_id: 'subscribe_streamId'+i,
2203
2835
  feedId_id: 'feedId'+i,
2204
2836
  feedId: feed.feedId
2205
2837
  }
@@ -2214,6 +2846,15 @@ class Video extends Component {
2214
2846
  }
2215
2847
 
2216
2848
  }
2849
+
2850
+ // 记录ipad摄像头流,需要单独开启录制
2851
+ if (feed.mediaSource == 'VIDEO_SOURCE_CAMERA' && feed.uid.includes(IPAD_SUFFIX)) {
2852
+ this.state.ipadTag = feed.tag;
2853
+ // 如果已经开启了业务录制且ipad未在录制,立即开启ipad录制(ipad后加入)
2854
+ if (this.state.businessId && !this.state.ipadRecordId) {
2855
+ this.enableIpadRecording(this.state.businessId)
2856
+ }
2857
+ }
2217
2858
  };
2218
2859
  // 推送“有新订阅”给与会者
2219
2860
  this.test_controller.OnNewSubscribe = (subscriber, feed) => {
@@ -2221,18 +2862,17 @@ class Video extends Component {
2221
2862
  };
2222
2863
  // 取消发布成功
2223
2864
  this.test_controller.OnUnPublishSucc = (sid) => {
2224
- console.log('取消发布成功', sid, document.getElementById('publish_video1').name)
2225
- if (document.getElementById('publish_video1').name && sid != document.getElementById('publish_video1').name) {
2226
- callNimIM('sendCustomCmdMsg', {
2227
- customId: this.state.imRoomId,
2228
- content: JSON.stringify({
2865
+ console.log('取消发布成功', sid, document.getElementById('publish_streamId1').name)
2866
+ if (document.getElementById('publish_streamId1').name && sid != document.getElementById('publish_streamId1').name) {
2867
+ this.sendMessage({
2229
2868
  'typeId': 2030,
2230
2869
  'sessionId': this.state.sessionId,
2231
2870
  'sharedScreen': 0,
2232
2871
  'tellerId': this.props.tellerAccount
2233
- })
2234
2872
  })
2235
2873
  this.state.isSharedScreen = false
2874
+ this.setSharedScreenState(false)
2875
+ this.saveLog('Stop share')
2236
2876
  this.setState({
2237
2877
 
2238
2878
  screenName: '共享模式'
@@ -2243,7 +2883,8 @@ class Video extends Component {
2243
2883
  // }
2244
2884
 
2245
2885
  }
2246
- if (sid == document.getElementById('publish_video1').name || !document.getElementById('publish_video1').name) {
2886
+ if (sid == document.getElementById('publish_streamId1').name || !document.getElementById('publish_streamId1').name) {
2887
+ console.log('OnUnPublishSucc clearStreamRemain!!!')
2247
2888
  clearStreamRemain()
2248
2889
  }
2249
2890
  };
@@ -2317,6 +2958,15 @@ class Video extends Component {
2317
2958
  }
2318
2959
 
2319
2960
  console.log('退出房间回调', leaveType);
2961
+ // if (leaveType != 1) {
2962
+ // this.props.onLeaveRoom({
2963
+ // code: LEAVE_TYPE.TELLER_DISCONNECT,
2964
+ // errMsg: '坐席断开连接'
2965
+ // })
2966
+ // this.setState({
2967
+ // isDisconnectModalVisible: true
2968
+ // })
2969
+ // }
2320
2970
  };
2321
2971
  // 推送“退出房间者”给与会者
2322
2972
  this.test_controller.OnParticipantLeaveRoom = (
@@ -2329,13 +2979,48 @@ class Video extends Component {
2329
2979
  // let audio = new Audio(src)
2330
2980
  // audio.play()
2331
2981
  // }
2982
+ if (participant.includes('UnHint')){
2983
+ console.log('过滤掉的uid', participant)
2984
+ return
2985
+ }
2986
+
2987
+ if (participant.includes(IPAD_SUFFIX) && this.state.businessId){
2988
+ // ipad单独处理,双录过程中ipad如果离开,要提示+循环播报直到ipad重新入会
2989
+ this.setState({
2990
+ IpadLeaveErrorModalVisible: true,
2991
+ ipadTag: '',
2992
+ })
2993
+ // 循环播放ipad退出语音
2994
+ clearTimeout(this.ipadLeavePlayTimer)
2995
+ this.ipadLeavePlay = () => {
2996
+ if(!this.state.ipadTag && document.getElementById("publish_streamId1")){
2997
+ let audio = new Audio(IpadLeaveAudio)
2998
+ audio.play()
2999
+ this.ipadLeavePlayTimer = setTimeout(this.ipadLeavePlay, 3000);
3000
+ }
3001
+ }
3002
+ setTimeout(this.ipadLeavePlay, 0);
3003
+ return
3004
+ } else if (participant.includes(IPAD_SUFFIX)) {
3005
+ // 非双录下ipad离开提示iPad已断开
3006
+ this.setState({
3007
+ ipadTag: '',
3008
+ })
3009
+ this.messageClick(('iPad 已断开'), 'error')
3010
+ this.saveLog('iPad leave room')
3011
+ if (this.props.isOpenSound && !this.state.businessId) {
3012
+ let audio = new Audio(ipadLeaveMeeting)
3013
+ audio.play()
3014
+ }
3015
+ return
3016
+ }
2332
3017
 
2333
3018
 
2334
3019
  this.appGetUsernameClick(participant).then((res) => {
2335
3020
  console.log('退出房间者', res)
2336
3021
  let data = res ? res.username ? res.username : '客户' : '客户'
2337
3022
  console.log(data)
2338
- this.messageClick((data + '已退出会议'), 'error')
3023
+ // this.messageClick((data + '已退出会议'), 'error')
2339
3024
  this.saveLog(data + ' leave room')
2340
3025
  if (res.userType == 1) {
2341
3026
  // 2--坐席  1--客户
@@ -2348,12 +3033,14 @@ class Video extends Component {
2348
3033
  let audio = new Audio(src)
2349
3034
  audio.play()
2350
3035
  }
3036
+ this.messageClick(('客户已退出会议'), 'error')
2351
3037
  } else if (res.userType == 2) {
2352
3038
  if (this.props.isOpenSound) {
2353
3039
  let src = internalLeft
2354
3040
  let audio = new Audio(src)
2355
3041
  audio.play()
2356
3042
  }
3043
+ this.messageClick(('内部人员已退出会议'), 'error')
2357
3044
  }
2358
3045
  // console.log('退出房间者',res)
2359
3046
  // let data = res? res : '客户'
@@ -2365,45 +3052,126 @@ class Video extends Component {
2365
3052
  // 弱网回调
2366
3053
  this.test_controller.OnNetworkWeak = (bpsSend, bpsRecv, sid) => {
2367
3054
  console.log('弱网回调', bpsSend, bpsRecv, sid)
2368
- if (sid == document.getElementById('publish_video1').name) {
2369
- this.messageClick('当前网络环境较差', 'error')
2370
- this.saveLog('mrtc OnNetworkWeak')
3055
+ if (sid == document.getElementById('publish_streamId1').name || sid == document.getElementById('video20').name) {
3056
+ const stream = sid == document.getElementById('publish_streamId1').name ? this.mediaInfo : this.videoInfo
3057
+
3058
+ this.detectNetworkWeak(stream).then((isWeak) => {
3059
+ console.log('弱网结果:' + isWeak)
3060
+ if (isWeak) {
3061
+ this.messageClick('当前网络环境较差', 'error')
3062
+ this.saveLog('mrtc OnNetworkWeak')
3063
+ this.saveVideoPoint('wnd', 'RM端弱网');
3064
+ if (this.props.isWeakSound && this.state.ablePlayNetweakAudio) {
3065
+ this.state.ablePlayNetweakAudio = false;
3066
+ let src = networkWeakAudio
3067
+ let audio = new Audio(src)
3068
+ audio.play()
3069
+ setTimeout(() => {
3070
+ this.state.ablePlayNetweakAudio = true;
3071
+ }, 30000);
3072
+ }
3073
+ if (this.props.OnNetworkWeak) {
3074
+ this.props.OnNetworkWeak(bpsSend, bpsRecv, sid)
3075
+ }
3076
+ }
3077
+ })
3078
+
2371
3079
  }
2372
3080
  };
2373
3081
  // 开始服务端录制成功
2374
- this.test_controller.OnStartRemoteRecordSucc = (record_id) => {
2375
- console.log('开始服务端录制成功', record_id);
2376
- this.state.recordId = record_id
2377
- this.videoRecordCallback('1', true)
2378
- this.saveLog('mrtc OnStartRemoteRecordSucc')
3082
+ this.test_controller.OnStartRemoteRecordSucc = (record_id, record_third_id) => {
3083
+ console.log('开始服务端录制成功', record_id, record_third_id);
3084
+ if (!record_third_id) {
3085
+ // 全局录制
3086
+ this.state.recordId = record_id
3087
+ this.videoRecordCallback('1', true)
3088
+ this.saveLog('mrtc OnStartRemoteRecordSucc')
3089
+ } else if (String(record_third_id).includes('_ipad')){
3090
+ this.state.ipadRecordId = record_id
3091
+ const busId = Number(record_third_id.split('_')[0])
3092
+ this.ipadRecordCallback('1', true, busId)
3093
+ this.saveLog('mrtc OnStartIpadRecordSucc')
3094
+ } else {
3095
+ // 业务录制
3096
+ this.state.businessRecordId = record_id
3097
+ this.businessRecordCallback('1', true, record_third_id)
3098
+ this.saveLog('mrtc OnStartRemoteBusinessRecordSucc, businessId=' + record_third_id)
3099
+ }
3100
+
3101
+ if (this.state.isRecordingeErrorModalVisible) {
3102
+ this.setState({
3103
+ isRecordingeErrorModalVisible: false
3104
+ })
3105
+ }
2379
3106
  };
2380
3107
  // 开始服务端录制失败
2381
3108
  this.test_controller.OnStartRemoteRecordFailed = (
2382
3109
  record_id,
2383
3110
  err_code,
2384
- err_msg
3111
+ err_msg,
3112
+ record_third_id
2385
3113
  ) => {
2386
- this.videoRecordCallback('1', false)
2387
- console.log('开始服务端录制失败', record_id, err_code, err_msg)
2388
- this.saveLog('mrtc OnStartRemoteRecordFailed, code='+err_code)
3114
+ console.log('开始服务端录制失败', record_id, err_code, err_msg, record_third_id)
3115
+ if (!record_third_id) {
3116
+ this.videoRecordCallback('1', false)
3117
+ this.saveLog('mrtc OnStartRemoteRecordFailed, code='+err_code)
3118
+ } else if (String(record_third_id).includes('_ipad')){
3119
+ const busId = Number(record_third_id.split('_')[0])
3120
+ this.ipadRecordCallback('1', false, busId)
3121
+ this.saveLog('mrtc OnStartIpadRecordFailed, code='+err_code)
3122
+ } else {
3123
+ this.businessRecordCallback('1', false, record_third_id)
3124
+ this.saveLog('mrtc OnStartRemoteBusinessRecordFailed, code='+err_code + ',businessId=' + record_third_id)
3125
+ }
2389
3126
  };
2390
3127
  // 结束服务端录制成功
2391
- this.test_controller.OnStopRemoteRecordSucc = (recordId) => {
2392
- console.log('结束服务端录制成功', recordId);
2393
- this.videoRecordCallback('2', true)
2394
- this.saveLog('mrtc OnStopRemoteRecordSucc, recordId='+recordId)
2395
- // this.endSessionValue()
3128
+ this.test_controller.OnStopRemoteRecordSucc = (recordId, record_third_id) => {
3129
+ console.log('结束服务端录制成功', recordId, record_third_id);
3130
+ // 重进会议前端会丢失之前的third_id,从服务端去取
3131
+ if (!record_third_id && third_id_Map.get(recordId)) {
3132
+ record_third_id = third_id_Map.get(recordId)
3133
+ }
3134
+ console.log('record_third_id=', record_third_id)
3135
+ if (!record_third_id) {
3136
+ this.videoRecordCallback('2', true)
3137
+ this.saveLog('mrtc OnStopRemoteRecordSucc, recordId='+recordId)
3138
+ this.state.recordId = '';
3139
+ } else if (String(record_third_id).includes('_ipad')){
3140
+ const busId = Number(record_third_id.split('_')[0])
3141
+ this.ipadRecordCallback('2', true, busId)
3142
+ this.saveLog('mrtc OnStopIpadRecordSucc, recordId='+recordId)
3143
+ this.state.ipadRecordId = '';
3144
+ } else {
3145
+ this.businessRecordCallback('2', true, record_third_id)
3146
+ this.saveLog('mrtc OnStopRemoteBusinessRecordSucc, recordId='+recordId + ',businessId=' + record_third_id)
3147
+ this.state.businessRecordId = '';
3148
+ }
2396
3149
  // 获取服务端录制结果
2397
3150
  };
2398
3151
  // 结束服务端录制失败
2399
3152
  this.test_controller.OnStopRemoteRecordFailed = (
2400
3153
  recordId,
2401
3154
  err_code,
2402
- err_msg
3155
+ err_msg,
3156
+ record_third_id
2403
3157
  ) => {
2404
- this.videoRecordCallback('2', false)
2405
- console.log('结束服务端录制失败', recordId, err_code, err_msg)
2406
- this.saveLog('mrtc OnStopRemoteRecordFailed, err_code='+err_code)
3158
+ console.log('结束服务端录制失败', recordId, err_code, err_msg, record_third_id)
3159
+ // 重进会议前端会丢失之前的third_id,从服务端去取
3160
+ if (!record_third_id && third_id_Map.get(recordId)) {
3161
+ record_third_id = third_id_Map.get(recordId)
3162
+ }
3163
+ if (!record_third_id) {
3164
+ this.videoRecordCallback('2', false)
3165
+ this.saveLog('mrtc OnStopRemoteRecordFailed, err_code='+err_code)
3166
+ } else if (String(record_third_id).includes('_ipad')){
3167
+ const busId = Number(record_third_id.split('_')[0])
3168
+ this.ipadRecordCallback('2', false, busId)
3169
+ this.saveLog('mrtc OnStopIpadRecordFailed, err_code='+err_code)
3170
+ } else {
3171
+ this.businessRecordCallback('2', false, record_third_id)
3172
+ this.saveLog('mrtc OnStopRemoteBusinessRecordFailed, err_code='+err_code+',businessId=' + record_third_id)
3173
+ }
3174
+
2407
3175
  };
2408
3176
  // 开启浏览器录制成功
2409
3177
  this.test_controller.OnClientStartRecordSuccess = (
@@ -2467,6 +3235,29 @@ class Video extends Component {
2467
3235
  msg
2468
3236
  ) => {
2469
3237
  console.log('服务端录制失败通知', recordId, feedId, code, msg)
3238
+ this.saveLog(`recording error, recordId=${recordId}`)
3239
+
3240
+ // 如果在业务双录中,需要重新开启;如果是full录制出错,则不用处理
3241
+ if (this.state.businessRecordId == recordId) {
3242
+ // 录制中断
3243
+ this.messageClick('双录异常中断,请重新开启', 'error')
3244
+ this.setState({
3245
+ isRecordingeErrorModalVisible: true,
3246
+ businessRecordId: '',
3247
+ })
3248
+ this.saveLog(`dual recording crash, recordId=${recordId}`);
3249
+ // 循环播放录制中断语音
3250
+ clearTimeout(this.recordLoopPlayTimer)
3251
+ this.recordLoopPlay = () => {
3252
+ console.log('loop recordId', this.state.recordId, 'businessRecordId ', this.state.businessRecordId)
3253
+ if(!this.state.businessRecordId && document.getElementById("publish_streamId1")){
3254
+ let audio = new Audio(recordErrorAudio)
3255
+ audio.play()
3256
+ this.recordLoopPlayTimer = setTimeout(this.recordLoopPlay, 3000);
3257
+ }
3258
+ }
3259
+ setTimeout(this.recordLoopPlay, 0);
3260
+ }
2470
3261
  };
2471
3262
  // 停止浏览器录制成功回调
2472
3263
  this.test_controller.OnClientStopRecordSuccess = (
@@ -2526,6 +3317,23 @@ class Video extends Component {
2526
3317
  ) => {
2527
3318
  console.log('下载失败', clientRecordId, code, msg)
2528
3319
  };
3320
+ // 日志上传成功
3321
+ this.test_controller.OnUploadLogSucc = (filePath) => {
3322
+ // const filePath = 'https://mpaas.oss-cn-hk-hsbc-d01-a.ali-ops.cloud.cn.hsbc/log/0E6C7637D9A53DF38D4CFC614EC8915C_41B8EEB302057/wmzTeller_681269134338102_1681269140267_1.log?Expires=1681269740&OSSAccessKeyId=Cq0vGDNN7WQeyn8n&Signature=avYEdwRSdblKIY7LhB6FzwpPAD8%3D'
3323
+
3324
+ console.info('OnUploadLogSucc', filePath)
3325
+ this.saveLog('mrtc OnUploadLogSucc, filePath=' + filePath)
3326
+
3327
+ // const exp1 = /.+\.log/g
3328
+ // const url = filePath.match(exp1)[0]
3329
+ // console.log(url)
3330
+ this.uploadLogCallback(filePath)
3331
+ };
3332
+ this.test_controller.OnUploadLogFail = (code, err_msg) => {
3333
+ // test_controller.trace(`upload log failed, err_code=${code}, err_msg=${JSON.stringify(err_msg)}`);
3334
+ console.info('OnUploadLogFail', code, err_msg)
3335
+ this.saveLog('mrtc OnUploadLogFail, code=' + code, ',msg=' + err_msg)
3336
+ };
2529
3337
  // 切流成功通知
2530
3338
  this.test_controller.OnChangeMediaStreamSuccess = (sid) => {
2531
3339
  console.log('切流成功通知', sid);
@@ -2539,6 +3347,8 @@ class Video extends Component {
2539
3347
  if (this.state.screenName == '切换共享') {
2540
3348
  this.state.isSharedScreen = true
2541
3349
  this.state.isScreenSwitching = false
3350
+ this.setSharedScreenState(true)
3351
+ this.saveLog('Share changed')
2542
3352
  }
2543
3353
  }
2544
3354
  };
@@ -2556,9 +3366,13 @@ class Video extends Component {
2556
3366
  })
2557
3367
  this.messageClick('切换摄像头或麦克风失败,请先检查设备', 'error')
2558
3368
  } else if (this.state.screenName == '切换共享') {
3369
+ this.saveLog('unPublish share, reason: trigger OnChangeMediaStreamFailed')
3370
+ console.log('unPublish share, reason: trigger OnChangeMediaStreamFailed')
2559
3371
  this.test_controller.UnPublish(document.getElementById('video20').name)
2560
3372
  this.state.isSharedScreen = false
2561
3373
  this.state.isScreenSwitching = false
3374
+ this.setSharedScreenState(false)
3375
+ this.saveLog('Share fail, code=' + code)
2562
3376
  this.setState({
2563
3377
  screenName: '共享模式'
2564
3378
  });
@@ -2669,7 +3483,7 @@ class Video extends Component {
2669
3483
  let startX = x2 // 绘制起始点x
2670
3484
  let startY = y1 - height // 绘制起始点y
2671
3485
  ctx.fillRect(startX, startY, width, height)
2672
- if (document.getElementById('publish_video1').name == sid && i == 39) {
3486
+ if (document.getElementById('publish_streamId1').name == sid && i == 39) {
2673
3487
  this.state.analyserHeight.set(sid, number / 40 / 70)
2674
3488
  this.state.analyserHeight = this.state.analyserHeight
2675
3489
  }
@@ -2686,18 +3500,21 @@ class Video extends Component {
2686
3500
  }
2687
3501
  // 停止共享
2688
3502
  this.test_controller.OnDesktopDisplayClosed = () => {
2689
- console.log('OnDesktopDisplayClosed', this.state.isSharedScreen, this.state.laveRoomSharedScreen)
3503
+ console.log('OnDesktopDisplayClosed', this.state.isSharedScreen, this.state.laveRoomSharedScreen, streamShare)
2690
3504
 
2691
3505
  if (this.state.isScreenSwitching) {
2692
3506
  this.state.isScreenSwitching = false
2693
3507
  } else {
2694
3508
  if (!streamShare) {
3509
+ this.saveLog('unPublish share, reason: trigger OnDesktopDisplayClosed, manually click stop or stream onended')
3510
+ console.log('unPublish share, reason: trigger OnDesktopDisplayClosed, manually click stop or stream onended')
2695
3511
  document.getElementById('video20') && document.getElementById('video20').name ? this.test_controller.UnPublish(document.getElementById('video20').name) : ''
2696
3512
  } else {
2697
3513
  console.log('白板')
2698
3514
  }
2699
3515
  this.state.isSharedScreen = false
2700
3516
  this.state.isScreenSwitching = false
3517
+ this.setSharedScreenState(false)
2701
3518
  this.setState({
2702
3519
  screenName: '共享模式'
2703
3520
  });
@@ -2715,13 +3532,51 @@ class Video extends Component {
2715
3532
 
2716
3533
 
2717
3534
  };
3535
+
3536
+
3537
+ }
3538
+ startASR() {
3539
+ // const publish_sid = document.getElementById('publish_video1').name
3540
+
3541
+ // if (media_status == 1) {
3542
+ // return
3543
+ // }
3544
+ this.asr_controller.initWebSocket(this.props.asrServerUrl)
3545
+ }
3546
+ stopASR() {
3547
+ this.state.isAsrStart = false
3548
+ // if (media_status == 0) {
3549
+ // return
3550
+ // }
3551
+ this.asr_controller.Disconnect()
3552
+
3553
+ message.success({
3554
+ content: '敏感词检测已关闭',
3555
+ icon: <img src={require("../../assets/img/tooltips1_pass.png").default} alt="" ></img>,
3556
+ className: 'successClassName',
3557
+ top: 200,
3558
+ // duration: 10
3559
+ })
2718
3560
  }
3561
+ // 全局录制
2719
3562
  videoRecordCallback = async (type, status) => {
3563
+ if (status) {
3564
+ // 全局录制且开启成功,通知app
3565
+ this.sendMessage({
3566
+ 'typeId': 1030,
3567
+ 'type': type,
3568
+ 'sessionId': this.state.sessionId,
3569
+ 'recordId': this.state.recordId
3570
+ })
3571
+ }
2720
3572
  try {
2721
3573
  let result = await API.videoRecordCallback({
2722
3574
  activityId: this.props.businessNumber,
2723
3575
  sessionId: this.state.sessionId,
2724
3576
  roomId: this.state.channelId + '',
3577
+ appId: this.state.appId,
3578
+ recordId: this.state.recordId,
3579
+ customerId: this.props.customerId,
2725
3580
  type: type,
2726
3581
  status: status
2727
3582
  });
@@ -2732,6 +3587,73 @@ class Video extends Component {
2732
3587
  }
2733
3588
  }
2734
3589
  }
3590
+ // 业务录制回调
3591
+ businessRecordCallback = async (type, status, businessId) => {
3592
+ if (status) {
3593
+ this.sendMessage({
3594
+ 'typeId': 1031,
3595
+ 'type': type,
3596
+ 'id': businessId,
3597
+ 'sessionId': this.state.sessionId,
3598
+ 'recordId': this.state.recordId,
3599
+ 'businessRecordId': this.state.businessRecordId
3600
+ })
3601
+ }
3602
+ try {
3603
+ let result = await API.videoRecordCallback({
3604
+ activityId: this.props.businessNumber,
3605
+ sessionId: this.state.sessionId,
3606
+ roomId: this.state.channelId + '',
3607
+ id: businessId,
3608
+ appId: this.state.appId,
3609
+ recordId: this.state.businessRecordId,
3610
+ customerId: this.props.customerId,
3611
+ type: type,
3612
+ status: status
3613
+ });
3614
+ console.log(result);
3615
+ } catch (err) {
3616
+ console.error(err);
3617
+ if (err.status == 502 || err.status == 404) {
3618
+ }
3619
+ }
3620
+ }
3621
+ // ipad录制回调
3622
+ ipadRecordCallback= async (type, status, businessId) => {
3623
+ try {
3624
+ let result = await API.videoRecordCallback({
3625
+ activityId: this.props.businessNumber,
3626
+ sessionId: this.state.sessionId,
3627
+ roomId: this.state.channelId + '',
3628
+ id: businessId,
3629
+ appId: this.state.appId,
3630
+ recordId: this.state.ipadRecordId,
3631
+ customerId: this.props.customerId,
3632
+ isIpad: 1,
3633
+ type: type,
3634
+ status: status
3635
+ });
3636
+ } catch (err) {
3637
+ console.error(err);
3638
+ if (err.status == 502 || err.status == 404) {
3639
+ }
3640
+ }
3641
+ }
3642
+ uploadLogCallback = async (url) => {
3643
+ try {
3644
+ let result = await API.uploadLogCallback({
3645
+ activityId: this.props.businessNumber,
3646
+ sessionId: this.state.sessionId,
3647
+ roomId: this.state.channelId + '',
3648
+ tellerAccount: this.props.tellerAccount,
3649
+ fileUrl: url
3650
+ });
3651
+ } catch (err) {
3652
+ // console.error(err);
3653
+ if (err.status == 502 || err.status == 404) {
3654
+ }
3655
+ }
3656
+ }
2735
3657
  // 保存mettingInfo
2736
3658
  updateMeetingInfo = async () => {
2737
3659
  let customers
@@ -2763,10 +3685,9 @@ class Video extends Component {
2763
3685
  type: '2'
2764
3686
  });
2765
3687
  console.log(result);
2766
- this.appGetUsername(document.getElementById('publish_video1').name)
2767
- callNimIM('sendCustomCmdMsg', {
2768
- customId: this.state.imRoomId,
2769
- content: JSON.stringify({
3688
+ this.queryRecordStatus()
3689
+ this.appGetUsername(document.getElementById('publish_streamId1').name)
3690
+ this.sendMessage({
2770
3691
  'typeId': 1014,
2771
3692
  'sessionId': this.state.sessionId,
2772
3693
  'meetingInfo': {
@@ -2775,9 +3696,6 @@ class Video extends Component {
2775
3696
  'customers': this.props.meetingInfo.customers,
2776
3697
  'otherAttendees': this.props.meetingInfo.otherAttendees
2777
3698
  }
2778
-
2779
- })
2780
- }, function (code, message, data) {
2781
3699
  })
2782
3700
  } catch (err) {
2783
3701
  console.error(err);
@@ -2786,10 +3704,15 @@ class Video extends Component {
2786
3704
  }
2787
3705
  }
2788
3706
  }
3707
+ componentDidCatch(error, info) {
3708
+ console.log('componentDidCatch')
3709
+ console.error(error, info)
3710
+ }
3711
+
2789
3712
  componentWillUnmount() {
2790
3713
  this.saveLog('Exit meeting')
2791
3714
  if (this.test_controller && this.state.sessionType) {
2792
- clearStreamRemain()
3715
+ // clearStreamRemain() // 谨慎使用,有页面crash问题
2793
3716
  this.test_controller.LeaveRoom()
2794
3717
  this.test_controller.Disconnect()
2795
3718
  try {
@@ -2797,15 +3720,30 @@ class Video extends Component {
2797
3720
  beautyStop();
2798
3721
  console.log('beautyStop!!')
2799
3722
  } catch (err){
2800
- console.error(err)
3723
+ console.log(err)
2801
3724
  }
2802
3725
  }
2803
- if (this.state.imStatus) {
2804
- console.log('disconnect断开连接')
2805
- this.state.manualClose = true
2806
- disconnect();
3726
+ if (this.state.isAsrStart){
3727
+ this.stopASR()
3728
+ this.asr_controller.Disconnect()
3729
+ }
3730
+ if (this.state.isPictureInPicture) {
3731
+ document.exitPictureInPicture()
2807
3732
  }
3733
+ worker.postMessage(false);
3734
+ worker.terminate();
2808
3735
  message.destroy()
3736
+ clearTimeout(this.loopPlayTimer)
3737
+ clearTimeout(this.recordLoopPlayTimer)
3738
+ clearTimeout(this.ipadLeavePlayTimer)
3739
+ clearTimeout(this.ipadLowPowerPlayTimer)
3740
+ clearInterval(this.state.drawCanvasInterval)
3741
+ clearInterval(this.state.faceDetectionTimer);
3742
+ clearInterval(this.state.imageDetectionTimer);
3743
+ this.removeVideoEvent(['video20', 'video21', 'publish_video1'])
3744
+ for(let i=1;i<=12;i++){
3745
+ this.removeVideoEvent(['video'+ i])
3746
+ }
2809
3747
  }
2810
3748
  finishSession = () => {
2811
3749
  // clearInterval(this.state.OnVolumeAnalyserMap.get(sid))
@@ -2821,6 +3759,7 @@ class Video extends Component {
2821
3759
  screenName: '共享模式',
2822
3760
  })
2823
3761
  this.state.isSharedScreen = false
3762
+ this.setSharedScreenState(false)
2824
3763
  this.state.laveRoomSharedScreen = true
2825
3764
  // this.test_controller.UnPublish(document.getElementById('video20').name)
2826
3765
 
@@ -2834,6 +3773,7 @@ class Video extends Component {
2834
3773
  screenName: '共享模式',
2835
3774
  });
2836
3775
  this.state.isSharedScreen = false
3776
+ this.setSharedScreenState(false)
2837
3777
  this.state.laveRoomSharedScreen = true
2838
3778
  this.props.onLeaveRoom({
2839
3779
  code: LEAVE_TYPE.TELLER_EXIT,
@@ -2862,6 +3802,21 @@ class Video extends Component {
2862
3802
  this.roomCallBack(2, '获取tiken失败', 'SYS-01')
2863
3803
  }
2864
3804
  }
3805
+ queryBranchName = async () => {
3806
+ try {
3807
+ let result = await API.getBranchName({
3808
+ branchCode: this.props.salesBranchCode
3809
+ })
3810
+ this.setState({
3811
+ branchName: result.branchName || ''
3812
+ })
3813
+ console.log('branchName', this.state.branchName)
3814
+ } catch (err) {
3815
+ console.error(err);
3816
+
3817
+ }
3818
+ }
3819
+
2865
3820
  getRoomStatus = async data => {
2866
3821
  try {
2867
3822
  let result = await API.getRoomStatus({
@@ -2909,7 +3864,7 @@ class Video extends Component {
2909
3864
  loading: true,
2910
3865
  })
2911
3866
  const that = this
2912
- axios.get(this.props.resourcePath + "/mcu.js")
3867
+ axios.get(this.props.resourcePath + `/mcu.js?v=${SDK_VERISON}`)
2913
3868
  .then(response => this.addToScriptClick()).catch(function (error) {
2914
3869
  console.log(error);
2915
3870
  that.state.sessionType = false
@@ -2923,36 +3878,50 @@ class Video extends Component {
2923
3878
 
2924
3879
  }
2925
3880
  addToScriptClick = () => {
3881
+ let params = `?v=${SDK_VERISON}`
2926
3882
  const _dependScripts = [
2927
- this.props.resourcePath + "/beauty/beauty_frame_pkg.js",
2928
- this.props.resourcePath + "/adapter.js",
2929
- this.props.resourcePath + "/getMediaInfo.js",
2930
- this.props.resourcePath + "/EBML.js",
2931
- this.props.resourcePath + "/mcu.js",
2932
- this.props.resourcePath + "/meeting_desk_stream.js",
2933
- this.props.resourcePath + "/meeting_html_stream.js",
2934
- this.props.resourcePath + "/meeting_file_stream.js",
2935
- this.props.resourcePath + "/meeting_im.js",
2936
- this.props.resourcePath + "/meeting_vod.js",
2937
- this.props.resourcePath + "/meeting_invite.js",
2938
- this.props.resourcePath + "/client_record.js",
2939
- this.props.resourcePath + "/remote_record.js",
2940
- this.props.resourcePath + "/meeting_camera_stream.js",
2941
- this.props.resourcePath + "/meeting_api.js",
2942
-
2943
- this.props.resourcePath + "/eruda.js",
2944
- this.props.resourcePath + "/iconfont.js",
2945
- this.props.resourcePath + "/html2canvas.js",
2946
- this.props.resourcePath + "/dom-to-image.js",
2947
-
2948
- this.props.resourcePath + "/hs/hs_human_segmentation_wrapper.js",
2949
- this.props.resourcePath + "/hs/hs_human_segmentation.js",
2950
- this.props.resourcePath + "/hs/hs_human_segmentation.wasm",
2951
-
2952
- this.props.resourcePath + "/mix/mix_frame.js",
2953
- this.props.resourcePath + "/mix/pageBoard.js"
3883
+ // this.props.resourcePath + "/opencv.js" + params,
3884
+ // this.props.resourcePath + "/asr_api.js" + params,
3885
+ // this.props.resourcePath + "/reconnecting-websocket.min.js" + params,
3886
+ // this.props.resourcePath + "/resampler.js" + params,
3887
+ this.props.resourcePath + "/beauty/beauty_frame_pkg.js" + params,
3888
+ this.props.resourcePath + "/adapter.js" + params,
3889
+ this.props.resourcePath + "/getMediaInfo.js" + params,
3890
+ this.props.resourcePath + "/EBML.js" + params,
3891
+ this.props.resourcePath + "/mcu.js" + params,
3892
+ this.props.resourcePath + "/meeting_desk_stream.js" + params,
3893
+ this.props.resourcePath + "/meeting_html_stream.js" + params,
3894
+ this.props.resourcePath + "/meeting_file_stream.js" + params,
3895
+ this.props.resourcePath + "/meeting_im.js" + params,
3896
+ this.props.resourcePath + "/meeting_vod.js" + params,
3897
+ this.props.resourcePath + "/meeting_invite.js" + params,
3898
+ this.props.resourcePath + "/client_record.js" + params,
3899
+ this.props.resourcePath + "/remote_record.js" + params,
3900
+ this.props.resourcePath + "/meeting_camera_stream.js" + params,
3901
+ this.props.resourcePath + "/meeting_api.js" + params,
3902
+
3903
+ this.props.resourcePath + "/eruda.js" + params,
3904
+ this.props.resourcePath + "/iconfont.js" + params,
3905
+ this.props.resourcePath + "/html2canvas.js" + params,
3906
+ this.props.resourcePath + "/dom-to-image.js" + params,
3907
+
3908
+ this.props.resourcePath + "/hs/hs_human_segmentation_wrapper.js" + params,
3909
+ this.props.resourcePath + "/hs/hs_human_segmentation.js" + params,
3910
+ this.props.resourcePath + "/hs/hs_human_segmentation.wasm" + params,
3911
+
3912
+ this.props.resourcePath + "/mix/mix_frame.js" + params,
3913
+ this.props.resourcePath + "/mix/pageBoard.js" + params,
2954
3914
 
2955
3915
  ]
3916
+ try{
3917
+ if (!cv){
3918
+ _dependScripts.unshift(this.props.resourcePath + "/opencv.js" + params)
3919
+ }
3920
+ } catch(err) {
3921
+ console.log(err)
3922
+ _dependScripts.unshift(this.props.resourcePath + "/opencv.js" + params)
3923
+ }
3924
+
2956
3925
  const that = this
2957
3926
  let i = 0
2958
3927
  scriptAdd()
@@ -2967,13 +3936,13 @@ class Video extends Component {
2967
3936
  if (document.all) { //如果是IE
2968
3937
  script.onreadystatechange = () => {
2969
3938
  if (script.readyState == 'loaded' || script.readyState == 'complete') {
2970
- that.test_controller = new McuController();
3939
+ that.test_controller = new MeetingController();
2971
3940
  that.mountClick()
2972
3941
  }
2973
3942
  }
2974
3943
  } else {
2975
3944
  script.onload = () => {
2976
- that.test_controller = new McuController();
3945
+ that.test_controller = new MeetingController();
2977
3946
  that.mountClick()
2978
3947
  }
2979
3948
  }
@@ -2996,7 +3965,7 @@ class Video extends Component {
2996
3965
  }
2997
3966
  }
2998
3967
  componentWillMount() {
2999
- console.log('hsbc_teller_sdk', '2.0.2')
3968
+ console.log('hsbc_teller_sdk', SDK_VERISON)
3000
3969
  let arr = []
3001
3970
  for(let i=1;i<=12;i++){
3002
3971
  arr.push({
@@ -3008,8 +3977,43 @@ class Video extends Component {
3008
3977
  hasOcr: 0,
3009
3978
  })
3010
3979
  }
3980
+ this.videoErrorEvent = (event) => {
3981
+ console.log(event)
3982
+ console.log(`video load ${event.type || 'error'}: sid=${event.target.name}, domid=${event.target.id}`)
3983
+ this.saveLog(`video load ${event.type || 'error'}: sid=${event.target.name}, domid=${event.target.id}`)
3984
+ }
3985
+ this.bindVideoEvent = (domArr) => {
3986
+ domArr.forEach((domId) => {
3987
+ document.getElementById(domId).addEventListener("error", this.videoErrorEvent);
3988
+ document.getElementById(domId).addEventListener("emptied", this.videoErrorEvent);
3989
+ document.getElementById(domId).addEventListener("stalled", this.videoErrorEvent);
3990
+ document.getElementById(domId).addEventListener("suspend", this.videoErrorEvent);
3991
+ })
3992
+ }
3993
+ this.removeVideoEvent = (domArr) => {
3994
+ domArr.forEach((domId) => {
3995
+ document.getElementById(domId).removeEventListener("error", this.videoErrorEvent);
3996
+ document.getElementById(domId).removeEventListener("emptied", this.videoErrorEvent);
3997
+ document.getElementById(domId).removeEventListener("stalled", this.videoErrorEvent);
3998
+ document.getElementById(domId).removeEventListener("suspend", this.videoErrorEvent);
3999
+ })
4000
+ }
3011
4001
  this.setState({
3012
4002
  videoList: arr
4003
+ }, () => {
4004
+ // 设置播放回调
4005
+ for(let i=1;i<=12;i++){
4006
+ let dom = document.getElementById('video'+ i)
4007
+ dom.addEventListener("loadedmetadata", (event) => {
4008
+ console.log('video'+ i +' loadedmetadata:' + dom.srcObject.id)
4009
+ this.saveLog('video'+ i +' loadedmetadata, id=' + dom.srcObject.id)
4010
+ // let arrItem = this.state.videoList.find(el => el.idIndex == i) || {}
4011
+ // console.log(arrItem.videoName)
4012
+
4013
+ });
4014
+ this.bindVideoEvent(['video'+ i])
4015
+ }
4016
+ this.bindVideoEvent(['video20', 'video21', 'publish_video1'])
3013
4017
  })
3014
4018
  if (this.props.sessionId) {
3015
4019
  this.getRoomStatus({
@@ -3018,8 +4022,101 @@ class Video extends Component {
3018
4022
  } else {
3019
4023
  this.addToScript()
3020
4024
  }
4025
+
4026
+ if (this.props.salesBranchCode) {
4027
+ this.queryBranchName()
4028
+ }
4029
+ window.imRoom = {
4030
+ sessionId: this.props.sessionId,
4031
+ userId: this.props.tellerAccount
4032
+ }
3021
4033
  }
4034
+ initAsrRecorder = () => {
4035
+ this.state.recorder = new Recorder({
4036
+ sampleBits: 16, // 采样位数,,默认是16
4037
+ sampleRate: 16000, //音频采样率,默认是16000Hz,
4038
+ numChannels: 1, // 声道,支持 1 或 2, 默认是1
4039
+ compiling: true // 是否边录边转换,默认是false
4040
+ })
4041
+ this.asr_controller = new MyAsrController({
4042
+ token: this.state.asrToken,
4043
+ appKey: this.state.asrAppKey,
4044
+ url: this.state.asrServerUrl,
4045
+ recorder: this.state.recorder
4046
+ })
4047
+
4048
+ let that = this;
4049
+ this.asr_controller.onConnectError = () => {
4050
+ this.messageClick('违禁词检测服务连接失败', 'error')
4051
+ }
4052
+
4053
+ this.asr_controller.onConnectOK = () => {
4054
+ message.success({
4055
+ content: '敏感词检测已开启',
4056
+ icon: <img src={require("../../assets/img/tooltips1_pass.png").default} alt="" ></img>,
4057
+ className: 'successClassName',
4058
+ top: 200,
4059
+ // duration: 10
4060
+ })
4061
+ this.state.recorder.start().then(() => {
4062
+ console.log('asr recorder 开启')
4063
+ }, (error) => {
4064
+ console.log(`出错了`);
4065
+ });
4066
+ this.state.isAsrStart = true
4067
+ this.state.sensitiveRecordMap = {}
4068
+ // this.AsrResultText = ''
4069
+ }
3022
4070
 
4071
+ this.asr_controller.onSentenceEnd = (msg) => {
4072
+ console.log('句子解析结果', msg.result)
4073
+ const resultValue = msg.result
4074
+ const sentence_id = msg.index
4075
+ API.keywordMatch({
4076
+ text: resultValue,
4077
+ appCode: `HSBCCode`
4078
+ }).then((re) => {
4079
+ if (re.data.match) {
4080
+ let matchArr = re.data.matchRawTextItems.map(el => el.matchedRawKeywords);
4081
+ let resultFormat = resultValue;
4082
+ re.data.matchRawTextItems.sort((a,b)=> b.matchedText.length - a.matchedText.length).forEach(el => {
4083
+ resultFormat = resultFormat.replace(el.matchedText, el.matchedRawKeywords)
4084
+ })
4085
+ console.log('敏感词:', resultValue, resultFormat)
4086
+ this.saveVideoPoint('pwd', `${resultFormat}`, matchArr.toString())
4087
+ if (matchArr.length>0) {
4088
+ this.messageClick('检测到敏感词:' + matchArr, 'error')
4089
+ }
4090
+ }
4091
+ });
4092
+ }
4093
+ // this.asr_controller.onAsrMessage = (msg) => {
4094
+ // console.log('收到解析结果', msg.result)
4095
+ // const resultValue = msg.result
4096
+ // const sentence_id = msg.index
4097
+ // // sentence_id相同,取最后一个值
4098
+ // let text = resultValue || ''
4099
+ // const sensitiveArr = that.props.sensitiveWords
4100
+ // let matchArr = sensitiveArr.filter(el => text.includes(el));
4101
+ // if (matchArr.length>0) {
4102
+ // matchArr.forEach(el => {
4103
+ // that.messageClick('检测到敏感词:' + matchArr, 'error')
4104
+ // that.state.sensitiveTitle = '检测到敏感词:' + matchArr
4105
+ // clearTimeout(that.state.sensitiveTitleTimer)
4106
+ // that.state.sensitiveTitleTimer = setTimeout(() => {
4107
+ // that.state.sensitiveTitle = ''
4108
+ // }, 3000);
4109
+ // if (!that.state.sensitiveRecordMap[sentence_id] || !that.state.sensitiveRecordMap[sentence_id].includes(el)){
4110
+
4111
+ // if (!that.state.sensitiveRecordMap[sentence_id]) {
4112
+ // that.state.sensitiveRecordMap[sentence_id] = []
4113
+ // }
4114
+ // that.state.sensitiveRecordMap[sentence_id].push(el)
4115
+ // }
4116
+ // })
4117
+ // }
4118
+ // }
4119
+ }
3023
4120
  voice = () => {
3024
4121
  if (this.isFileSuccuse()) {
3025
4122
  if (!this.state.voiceStatue) {
@@ -3035,20 +4132,15 @@ class Video extends Component {
3035
4132
  sid = document.getElementById('publish_streamId1').name
3036
4133
  }
3037
4134
  this.test_controller.SetLocalAudioEnable(0, parseInt(sid, 10));
3038
- callNimIM('sendCustomCmdMsg', {
3039
- customId: this.state.imRoomId,
3040
- content: JSON.stringify({
4135
+ this.saveVideoPoint('mute', 'RM端静音')
4136
+ this.sendMessage({
3041
4137
  'typeId': 1013,
3042
4138
  'muteStatus': 1,
3043
4139
  'data': {
3044
4140
  'sessionId': this.state.sessionId,
3045
4141
  'userId': this.props.tellerAccount
3046
4142
  }
3047
- })
3048
- }, function (code, message, data) {
3049
- console.log(data)
3050
4143
  })
3051
-
3052
4144
  } else if (this.state.voiceStatue) {
3053
4145
  // 打开本地
3054
4146
  this.setState({
@@ -3062,22 +4154,68 @@ class Video extends Component {
3062
4154
  sid = document.getElementById('publish_streamId1').name
3063
4155
  }
3064
4156
  this.test_controller.SetLocalAudioEnable(1, parseInt(sid, 10));
3065
- callNimIM('sendCustomCmdMsg', {
3066
- customId: this.state.imRoomId,
3067
- content: JSON.stringify({
4157
+ this.saveVideoPoint('mute', 'RM端解除静音')
4158
+ this.sendMessage({
3068
4159
  'typeId': 1013,
3069
4160
  'muteStatus': 0,
3070
4161
  'data': {
3071
4162
  'sessionId': this.state.sessionId,
3072
4163
  'userId': this.props.tellerAccount
3073
4164
  }
3074
- })
3075
- }, function (code, message, data) {
3076
- console.log(data)
3077
4165
  })
3078
4166
  }
4167
+ if (this.state.isPictureInPicture) {
4168
+ setTimeout(() => {
4169
+ this.pictureInPicture('Refresh')
4170
+ }, 0);
4171
+ }
3079
4172
  }
3080
4173
  };
4174
+ queryRecordStatus = async()=>{
4175
+ try {
4176
+ let result = await API.getRecordStatus({
4177
+ roomId: this.state.channelId + ''
4178
+ });
4179
+ console.log('RecordStatus', result)
4180
+ if (result.fullRecordStatus == 1) { // 1开启 2未开启
4181
+ // 全局录制
4182
+ this.state.recordId = result.fullRecordId
4183
+ if (result.businessRecordStatus == 1){
4184
+ // 业务录制
4185
+ this.state.businessRecordId = result.businessRecordId;
4186
+ this.state.businessId = result.businessId;
4187
+ this.state.ipadRecordId = result.businessIpadRecordId;
4188
+ third_id_Map.set(result.businessRecordId, result.businessId);
4189
+ third_id_Map.set(result.businessIpadRecordId, result.businessId+'_ipad');
4190
+ console.log("third_id_map", third_id_Map)
4191
+ if (this.props.whetherDetectFace && this.props.recordMode != 2) this.startFaceDetection();
4192
+ if (this.props.whetherDetectLight && this.props.recordMode != 2) this.startImageDetection();
4193
+ if (this.props.whetherNeedAsr) this.startASR();
4194
+ }
4195
+ } else {
4196
+ this.state.recordId = ''
4197
+ }
4198
+ } catch (err) {
4199
+ console.error(err);
4200
+ if(err.status == 502 || err.status== 404) {
4201
+ this.roomCallBack(2, '连接服务器失败','SYS-02')
4202
+ }
4203
+ }
4204
+ }
4205
+ setSharedScreenState = async (state) => {
4206
+ const status = state? 'open' : 'close'
4207
+ try {
4208
+ let result = await API.editRmScreenStatus({
4209
+ roomId: this.state.channelId + '',
4210
+ status,
4211
+ staffId: this.props.tellerAccount,
4212
+ });
4213
+ } catch (err) {
4214
+ if(err.status == 502 || err.status== 404) {
4215
+ this.roomCallBack(2, '连接服务器失败','SYS-02')
4216
+ }
4217
+ }
4218
+ }
3081
4219
  isFileSuccuse = () => {
3082
4220
  if (!this.state.sessionId || !this.state.sessionType || !this.state.imStatus) {
3083
4221
  this.messageClick('当前程序异常请先退出重开', 'error')
@@ -3100,17 +4238,12 @@ class Video extends Component {
3100
4238
  sid = document.getElementById('publish_streamId1').name
3101
4239
  }
3102
4240
  this.test_controller.SetLocalVideoEnable(0, parseInt(sid, 10));
3103
- callNimIM('sendCustomCmdMsg', {
3104
- customId: this.state.imRoomId,
3105
- content: JSON.stringify({
4241
+ this.sendMessage({
3106
4242
  'typeId': 1012,
3107
4243
  'state': 0,
3108
4244
  'sessionId': this.state.sessionId,
3109
4245
  'userId': this.props.tellerAccount
3110
- })
3111
- }, function (code, message, data) {
3112
- console.log(data)
3113
- })
4246
+ })
3114
4247
  } else if (this.state.audioed) {
3115
4248
  this.state.audioed = false,
3116
4249
  this.setState({
@@ -3122,22 +4255,21 @@ class Video extends Component {
3122
4255
  sid = document.getElementById('publish_streamId1').name
3123
4256
  }
3124
4257
  this.test_controller.SetLocalVideoEnable(1, parseInt(sid, 10));
3125
- callNimIM('sendCustomCmdMsg', {
3126
- customId: this.state.imRoomId,
3127
- content: JSON.stringify({
3128
- 'typeId': 1012,
3129
- 'state': 1,
3130
- 'sessionId': this.state.sessionId,
3131
- 'userId': this.props.tellerAccount
3132
- })
3133
- }, function (code, message, data) {
3134
- console.log(data)
4258
+ this.sendMessage({
4259
+ 'typeId': 1012,
4260
+ 'state': 1,
4261
+ 'sessionId': this.state.sessionId,
4262
+ 'userId': this.props.tellerAccount
3135
4263
  })
3136
4264
  }
3137
4265
  }
3138
4266
  };
3139
4267
  sharedScreen = () => {
3140
4268
  console.log('投屏', this.state.tabTitles.find(el => el.value == 'staffScreen'))
4269
+ if (this.state.shareLock) {
4270
+ console.log('发布共享点击太快了')
4271
+ return;
4272
+ }
3141
4273
  if (this.isFileSuccuse()) {
3142
4274
  if (!this.state.tabTitles.find(el => el.value == 'staffScreen')) {
3143
4275
  const publish_config = {};
@@ -3146,30 +4278,76 @@ class Video extends Component {
3146
4278
  streamShare = ''
3147
4279
  }
3148
4280
  if (this.state.isSharedScreen) {
3149
- const publish_config = {}
4281
+ this.saveLog('unPublish share, reason: change screen content')
4282
+ console.log('unPublish share, reason: change screen content')
4283
+ this.test_controller.UnPublish(document.getElementById('video20').name)
4284
+ this.state.shareLock = true;
4285
+ setTimeout(() => {
3150
4286
  publish_config.media_type = 1
3151
4287
  publish_config.publish_device = 2
4288
+ publish_config.need_volume_analyser = true
3152
4289
  publish_config.video_profile_type = 1
3153
- // publish_config.video_profile_type=100
3154
- // publish_config.video_profile_diy={width:1280, height:720, frameRate:8, bitrate:1500}
4290
+ publish_config.desktopStreamToCanvas = false
3155
4291
  publish_config.enableDesktopAudio = true
3156
4292
  publish_config.degradationType = 2
3157
- publish_config.desktopStreamToCanvas = false
3158
- publish_config.sid = document.getElementById('video20').name
3159
- this.test_controller.ChangeMediaStream(publish_config)
3160
- this.state.isScreenSwitching = true
4293
+ publish_config.publish_video_id = 'video20'
4294
+ publish_config.publish_streamId_id = 'subscribe_streamId20'
4295
+ publish_config.publish_tag = 'projectionWhiteboard'
4296
+ this.test_controller.Publish(publish_config)
4297
+ setTimeout(() => { this.state.shareLock = false; }, 500);
4298
+ }, 300);
4299
+ this.setState({
4300
+ screenName: '切换共享',
4301
+ isPDF: false
4302
+ })
4303
+ this.tabTitlesClick(
4304
+ {
4305
+ value: 'RMScreen',
4306
+ name: '共享内容'
4307
+ }, 'add'
4308
+ )
4309
+ // const publish_config = {}
4310
+ // publish_config.media_type = 1
4311
+ // publish_config.publish_device = 2
4312
+ // publish_config.video_profile_type = 1
4313
+ // // publish_config.video_profile_type=100
4314
+ // // publish_config.video_profile_diy={width:1280, height:720, frameRate:8, bitrate:1500}
4315
+ // publish_config.enableDesktopAudio = true
4316
+ // publish_config.degradationType = 2
4317
+ // publish_config.desktopStreamToCanvas = false
4318
+ // publish_config.sid = document.getElementById('video20').name
4319
+ // this.test_controller.ChangeMediaStream(publish_config)
4320
+ // this.state.isScreenSwitching = true
3161
4321
  } else {
3162
4322
  if (document.getElementById('video20').name) {
3163
- publish_config.media_type = 1;
3164
- publish_config.publish_device = 2;
3165
- publish_config.video_profile_type = 1
3166
- // publish_config.video_profile_type=100
3167
- // publish_config.video_profile_diy={width:1280, height:720, frameRate:8, bitrate:1500}
3168
- publish_config.enableDesktopAudio = true
3169
- publish_config.desktopStreamToCanvas = false
3170
- publish_config.degradationType = 2
3171
- publish_config.sid = document.getElementById('video20').name;
3172
- this.test_controller.ChangeMediaStream(publish_config);
4323
+ this.saveLog('unPublish share, reason: change screen content')
4324
+ console.log('unPublish share, reason: change screen content')
4325
+ this.test_controller.UnPublish(document.getElementById('video20').name)
4326
+ this.state.shareLock = true;
4327
+ setTimeout(() => {
4328
+ publish_config.media_type = 1
4329
+ publish_config.publish_device = 2
4330
+ publish_config.need_volume_analyser = true
4331
+ publish_config.video_profile_type = 1
4332
+ publish_config.desktopStreamToCanvas = false
4333
+ publish_config.enableDesktopAudio = true
4334
+ publish_config.degradationType = 2
4335
+ publish_config.publish_video_id = 'video20'
4336
+ publish_config.publish_streamId_id = 'subscribe_streamId20'
4337
+ publish_config.publish_tag = 'projectionWhiteboard'
4338
+ this.test_controller.Publish(publish_config)
4339
+ setTimeout(() => { this.state.shareLock = false; }, 500); // 这个延迟用于防止跳出弹窗后仍可以点击共享按钮,大于debounce300即可
4340
+ }, 300);// 这个延迟用于跟UnPublish 产生时差,防止标签未被释放
4341
+ // publish_config.media_type = 1;
4342
+ // publish_config.publish_device = 2;
4343
+ // publish_config.video_profile_type = 1
4344
+ // // publish_config.video_profile_type=100
4345
+ // // publish_config.video_profile_diy={width:1280, height:720, frameRate:8, bitrate:1500}
4346
+ // publish_config.enableDesktopAudio = true
4347
+ // publish_config.desktopStreamToCanvas = false
4348
+ // publish_config.degradationType = 2
4349
+ // publish_config.sid = document.getElementById('video20').name;
4350
+ // this.test_controller.ChangeMediaStream(publish_config);
3173
4351
  } else {
3174
4352
  publish_config.media_type = 1
3175
4353
  publish_config.publish_device = 2
@@ -3248,23 +4426,21 @@ class Video extends Component {
3248
4426
  sid = document.getElementById('publish_streamId1').name
3249
4427
  }
3250
4428
  this.test_controller.SetLocalAudioEnable(0, parseInt(sid, 10))
4429
+ this.saveVideoPoint('mute', 'RM端静音')
3251
4430
  } else {
3252
4431
  // 当前是
3253
4432
  this.test_controller.SetLocalAudioEnable(1, parseInt(sid, 10));
4433
+ this.saveVideoPoint('mute', 'RM端解除静音')
3254
4434
  this.setState({
3255
4435
  voiceImg: voiceImgOpen,
3256
4436
  voiceName: '静音'
3257
4437
  })
3258
4438
  }
3259
- callNimIM('sendCustomCmdMsg', {
3260
- customId: this.state.imRoomId,
3261
- content: JSON.stringify({
3262
- 'typeId': 1011,
3263
- 'state': 1,
3264
- 'sessionId': this.state.sessionId,
3265
- 'userId': this.props.tellerAccount
3266
- })
3267
- }, function (code, message, data) {
4439
+ this.sendMessage({
4440
+ 'typeId': 1011,
4441
+ 'state': 1,
4442
+ 'sessionId': this.state.sessionId,
4443
+ 'userId': this.props.tellerAccount
3268
4444
  })
3269
4445
  } else {
3270
4446
  this.setState({
@@ -3273,41 +4449,93 @@ class Video extends Component {
3273
4449
  }
3274
4450
 
3275
4451
  };
4452
+ // 打开抄录/签署面板
4453
+ showModal=(moduleName)=>{
4454
+ if (!this.state.multiModuleShow) {
4455
+ this.setState({
4456
+ multiModuleShow:true,
4457
+ multiModule: moduleName,
4458
+ },()=>{
4459
+ })
4460
+ this.tabTitlesClick(
4461
+ {
4462
+ value: 'multiModule',
4463
+ name: '签署抄录'
4464
+ },'add'
4465
+ )
4466
+ }else{
4467
+ this.closeModule()
4468
+ }
4469
+ }
4470
+ // 关闭面板
4471
+ closeModule=()=>{
4472
+ setTimeout(() => {
4473
+ this.setState({
4474
+ multiModuleShow:false,
4475
+ multiModule: '',
4476
+ })
4477
+ this.tabTitlesClick('multiModule','delect')
4478
+ }, 0);
4479
+ // const sid = document.getElementById('video20').name;
4480
+ // sid ? this.test_controller.UnPublish(sid) : ''
4481
+ }
4482
+ handleOkPictureConfirm = () => {
4483
+ this.pictureInPictureClick('add')
4484
+ this.setState({isPictureConfirmModalVisible: false})
4485
+ }
4486
+ isDisconnectModalVisible = () => {
4487
+ this.setState({isDisconnectModalVisible: false})
4488
+ }
4489
+ handleOkRecordConfirm = () => {
4490
+ if (!this.state.isPictureInPicture) {
4491
+ this.pictureInPicture()
4492
+ }
4493
+ this.saveLog('Start business recording')
4494
+ this.enableServerRecording(this.state.businessId)
4495
+ clearTimeout(this.recordLoopPlayTimer)
4496
+ }
4497
+ handleOkLowPowerConfirm = () => {
4498
+ // 通知ipad,获取是否在充电的状态
4499
+ this.sendMessage({
4500
+ 'typeId': 1224,
4501
+ 'sessionId': this.state.sessionId,
4502
+ 'userId': this.props.tellerAccount
4503
+ })
4504
+ }
4505
+ handleOkIpadLeaveConfirm = () => {
4506
+ // 检测ipad是否入会
4507
+ if (!this.state.ipadTag) {
4508
+ this.messageClick('未检测到iPad,请重新加入后再试', 'error')
4509
+ } else {
4510
+ clearTimeout(this.ipadLeavePlayTimer)
4511
+ this.setState({IpadLeaveErrorModalVisible: false})
4512
+ }
4513
+ }
3276
4514
  handleOk = () => {
3277
4515
  // 代表此时按钮是暂停会话,把isSuspend改成true变成恢复会话
3278
- callNimIM('sendCustomCmdMsg', {
3279
- customId: this.state.imRoomId,
3280
- content: JSON.stringify({
3281
- 'typeId': 1012,
3282
- 'state': 1,
3283
- 'sessionId': this.state.sessionId,
3284
- 'userId': this.props.tellerAccount
3285
- })
3286
- }, function (code, message, data) {
3287
- console.log(data)
3288
- });
4516
+ this.sendMessage({
4517
+ 'typeId': 1012,
4518
+ 'state': 1,
4519
+ 'sessionId': this.state.sessionId,
4520
+ 'userId': this.props.tellerAccount
4521
+ })
3289
4522
  this.setState({
3290
4523
  isSuspend: true,
3291
4524
  suspendName: '恢复'
3292
4525
  });
3293
- callNimIM('sendCustomCmdMsg', {
3294
- customId: this.state.imRoomId,
3295
- content: JSON.stringify({
3296
- 'typeId': 1011,
3297
- 'state': 0,
3298
- 'sessionId': this.state.sessionId,
3299
- 'userId': this.props.tellerAccount
3300
- })
3301
- }, function (code, message, data) {
3302
- console.log(data)
3303
- });
4526
+ this.sendMessage({
4527
+ 'typeId': 1011,
4528
+ 'state': 0,
4529
+ 'sessionId': this.state.sessionId,
4530
+ 'userId': this.props.tellerAccount
4531
+ })
3304
4532
  let sid = document.getElementById('publish_video1').name;
3305
4533
  if (!sid) {
3306
4534
  // 纯音频的时候sid在publish_streamId标签中
3307
4535
  sid = document.getElementById('publish_streamId1').name
3308
4536
  }
3309
4537
  this.test_controller.SetLocalAudioEnable(0, parseInt(sid, 10));
3310
- this.test_controller.SetLocalVideoEnable(0, parseInt(sid, 10));
4538
+ this.saveVideoPoint('mute', 'RM端静音')
3311
4539
  this.setState({
3312
4540
  isModalVisible: false
3313
4541
  })
@@ -3487,6 +4715,9 @@ class Video extends Component {
3487
4715
  // videoList: this.state.videoList
3488
4716
  // })
3489
4717
  this.videoListSort();
4718
+ if (this.state.isPictureInPicture) {
4719
+ this.pictureInPicture('Refresh')
4720
+ }
3490
4721
  } else {
3491
4722
  console.log('1')
3492
4723
  this.messageClick('保持信息失败', 'error')
@@ -3511,15 +4742,12 @@ class Video extends Component {
3511
4742
  console.log('ocrCallback', result.data,val)
3512
4743
  // this.messageClick('姓名:' + result.data.idCardName + ',身份证号:' + result.data.idCardNumber,'success')
3513
4744
  // this.messageClick('识别成功','success')
3514
- callNimIM('sendCustomCmdMsg', {
3515
- customId: this.state.imRoomId,
3516
- content: JSON.stringify({
3517
- 'typeId': 1020,
3518
- 'sessionId': this.state.sessionId,
3519
- 'cameraState': 1,
3520
- "userId": this.state.faceCustomerUid
3521
- })
3522
- });
4745
+ this.sendMessage({
4746
+ 'typeId': 1020,
4747
+ 'sessionId': this.state.sessionId,
4748
+ 'cameraState': 1,
4749
+ "userId": this.state.faceCustomerUid
4750
+ })
3523
4751
  if(this.state.documentType == 'ID_CARD') {
3524
4752
  if (result.data.side == 'front' && val == 1) {
3525
4753
  if(this.state.certificateValidity) {
@@ -3679,6 +4907,7 @@ class Video extends Component {
3679
4907
  })
3680
4908
  // this.messageClick('识别失败', 'error')
3681
4909
  this.errorCodeClick('ocr',result.code)
4910
+ this.saveLog('OCR failed, error code=' + result.code)
3682
4911
  }
3683
4912
  } catch (err) {
3684
4913
  this.setState({
@@ -3777,6 +5006,9 @@ class Video extends Component {
3777
5006
  // videoList: this.state.videoList
3778
5007
  // })
3779
5008
  this.videoListSort();
5009
+ if (this.state.isPictureInPicture) {
5010
+ this.pictureInPicture('Refresh')
5011
+ }
3780
5012
  } else {
3781
5013
  console.log('1')
3782
5014
  this.messageClick('保持信息失败', 'error')
@@ -3787,15 +5019,12 @@ class Video extends Component {
3787
5019
  }
3788
5020
  };
3789
5021
  handleCancelFacial = () => {
3790
- callNimIM('sendCustomCmdMsg', {
3791
- customId: this.state.imRoomId,
3792
- content: JSON.stringify({
3793
- 'typeId': 1020,
3794
- 'sessionId': this.state.sessionId,
3795
- 'cameraState': 1, // 1--打开前置 2--打开后置
3796
- "userId": this.state.faceCustomerUid
3797
- })
3798
- });
5022
+ this.sendMessage({
5023
+ 'typeId': 1020,
5024
+ 'sessionId': this.state.sessionId,
5025
+ 'cameraState': 1, // 1--打开前置 2--打开后置
5026
+ "userId": this.state.faceCustomerUid
5027
+ })
3799
5028
  this.setState({
3800
5029
  isModalVisibleFacial: false
3801
5030
  })
@@ -3820,15 +5049,12 @@ class Video extends Component {
3820
5049
  }
3821
5050
  }
3822
5051
  newFaceClick=()=>{
3823
- callNimIM('sendCustomCmdMsg', {
3824
- customId: this.state.imRoomId,
3825
- content: JSON.stringify({
3826
- 'typeId': 1020,
3827
- 'sessionId': this.state.sessionId,
3828
- 'cameraState': 2, // 1--打开前置 2--打开后置
3829
- "userId": this.state.faceCustomerUid
3830
- })
3831
- });
5052
+ this.sendMessage({
5053
+ 'typeId': 1020,
5054
+ 'sessionId': this.state.sessionId,
5055
+ 'cameraState': 2, // 1--打开前置 2--打开后置
5056
+ "userId": this.state.faceCustomerUid
5057
+ })
3832
5058
  this.setState({
3833
5059
  clickedFacial: false,
3834
5060
  clickedOcr: false,
@@ -3939,15 +5165,12 @@ class Video extends Component {
3939
5165
  } else {
3940
5166
  if (this.state.faceCustomerType == 2) {
3941
5167
  // ocr
3942
- callNimIM('sendCustomCmdMsg', {
3943
- customId: this.state.imRoomId,
3944
- content: JSON.stringify({
3945
- 'typeId': 1020,
3946
- 'sessionId': this.state.sessionId,
3947
- 'cameraState': 2, // 1--打开前置 2--打开后置
3948
- "userId": item.customId
3949
- })
3950
- });
5168
+ this.sendMessage({
5169
+ 'typeId': 1020,
5170
+ 'sessionId': this.state.sessionId,
5171
+ 'cameraState': 2, // 1--打开前置 2--打开后置
5172
+ "userId": item.customId
5173
+ })
3951
5174
  }
3952
5175
  var sid
3953
5176
  if (item.feedId == document.getElementById("feedId1").innerText) {
@@ -4018,19 +5241,25 @@ class Video extends Component {
4018
5241
  }
4019
5242
  }
4020
5243
  sgsinImage = () => {
4021
- if (this.state.IDtypeFrontOrBack == IDtypeFront) {
4022
- this.setState({
4023
- facialImg: this.test_controller.TakePicture(1, undefined, undefined, this.state.customOcrSid, 'png'),
4024
- isFaceImage: true,
4025
- facialImgFront: this.test_controller.TakePicture(1, undefined, undefined, this.state.customOcrSid, 'png'),
4026
- })
4027
- } else if (this.state.IDtypeFrontOrBack == IDtypeBack) {
4028
- this.setState({
4029
- facialImg: this.test_controller.TakePicture(1, undefined, undefined, this.state.customOcrSid, 'png'),
4030
- isFaceImage: true,
4031
- facialImgBack: this.test_controller.TakePicture(1, undefined, undefined, this.state.customOcrSid, 'png'),
4032
- })
4033
- }
5244
+ const imgBase64 = this.test_controller.TakePicture(1, undefined, undefined, this.state.customOcrSid, 'png')
5245
+ // console.log(imgBase64)
5246
+
5247
+ compressImage(imgBase64, (compressedImg)=>{
5248
+ // console.log(compressedImg)
5249
+ if (this.state.IDtypeFrontOrBack == IDtypeFront) {
5250
+ this.setState({
5251
+ facialImg: compressedImg,
5252
+ isFaceImage: true,
5253
+ facialImgFront: compressedImg,
5254
+ })
5255
+ } else if (this.state.IDtypeFrontOrBack == IDtypeBack) {
5256
+ this.setState({
5257
+ facialImg: compressedImg,
5258
+ isFaceImage: true,
5259
+ facialImgBack: compressedImg,
5260
+ })
5261
+ }
5262
+ })
4034
5263
 
4035
5264
  }
4036
5265
  handleChangeOcr = (val) => {
@@ -4042,10 +5271,10 @@ class Video extends Component {
4042
5271
  })
4043
5272
  }
4044
5273
  componentWillReceiveProps(props) {
4045
- this.state.channelId = props.roomId,
4046
- this.state.rtoken = props.mtoken,
4047
- this.state.sessionId = props.sessionId,
4048
- this.state.imRoomId = props.imRoomId
5274
+ this.state.channelId = props.roomId || this.state.channelId
5275
+ this.state.rtoken = props.mtoken || this.state.rtoken
5276
+ this.state.sessionId = props.sessionId || this.state.sessionId
5277
+ this.state.imRoomId = props.imRoomId || this.state.imRoomId
4049
5278
  }
4050
5279
  appGetUsernameClick = async (userId) => {
4051
5280
  let data = ''
@@ -4074,7 +5303,7 @@ class Video extends Component {
4074
5303
  userId = this.seeList(this.state.roomCustomerList, 'feedId', document.getElementById("feedId"+i).innerText).uid
4075
5304
  }
4076
5305
  }
4077
- if (document.getElementById('publish_video1').name == sid) {
5306
+ if (document.getElementById('publish_streamId1').name == sid) {
4078
5307
  userId = this.props.tellerAccount
4079
5308
  }
4080
5309
  try {
@@ -4094,9 +5323,15 @@ class Video extends Component {
4094
5323
  } else {
4095
5324
  this.messageClick('查询失败', 'error')
4096
5325
  }
4097
- if (this.props.isOpenSound && sid != document.getElementById('publish_video1').name) {
4098
- if (result.data.userType == 1) {
4099
- let src = autod
5326
+ if (this.props.isOpenSound && sid != document.getElementById('publish_streamId1').name) {
5327
+ if (userId.includes(IPAD_SUFFIX)) {
5328
+ if (!this.state.businessId) {
5329
+ let src = ipadjoinMeeting
5330
+ let audio = new Audio(src)
5331
+ audio.play()
5332
+ }
5333
+ } else if (result.data.userType == 1) {
5334
+ let src = joinMeeting
4100
5335
  let audio = new Audio(src)
4101
5336
  audio.play()
4102
5337
  } else if (result.data.userType == 2) {
@@ -4105,7 +5340,7 @@ class Video extends Component {
4105
5340
  audio.play()
4106
5341
  }
4107
5342
  }
4108
- if (document.getElementById('publish_video1').name == sid) {
5343
+ if (document.getElementById('publish_streamId1').name == sid) {
4109
5344
  this.setState({
4110
5345
  titleNameRm: data
4111
5346
  })
@@ -4193,6 +5428,21 @@ class Video extends Component {
4193
5428
  })
4194
5429
  }
4195
5430
  }
5431
+ changePdfRendering = () => {
5432
+ if (this.props.pdfRendering) {
5433
+ // 暂停绘制
5434
+ clearInterval(this.state.drawCanvasInterval)
5435
+ } else {
5436
+ // 继续绘制
5437
+ if (!this.drawFunction) {
5438
+ console.log('未开始远程签署')
5439
+ return
5440
+ }
5441
+ clearInterval(this.state.drawCanvasInterval)
5442
+ this.state.drawCanvasInterval = setInterval(this.drawFunction, 1000 / 20);
5443
+ }
5444
+
5445
+ }
4196
5446
  navigatorClick = () => {
4197
5447
  const that = this
4198
5448
  const publish_config = {};
@@ -4222,8 +5472,10 @@ class Video extends Component {
4222
5472
  canvas.width = 960;
4223
5473
  canvas.height = 540;
4224
5474
 
4225
-
4226
- videoMedia.addEventListener('play', (event) => {
5475
+ if (this.state.whiteboardPlayEvent) {
5476
+ videoMedia.removeEventListener('play', this.state.whiteboardPlayEvent)
5477
+ }
5478
+ this.state.whiteboardPlayEvent = (event) => {
4227
5479
  var $this = this; //cache
4228
5480
  if ($this.state.operateShow) {
4229
5481
  isGraffiti = false
@@ -4234,20 +5486,21 @@ class Video extends Component {
4234
5486
  canvas.width = this.state.whiteboardWidth
4235
5487
  }
4236
5488
  console.log('addEventListener', !$this.paused, !$this.ended, x, y, width, height)
4237
- loop()
4238
- function loop() {
4239
- if (!$this.paused && !$this.ended) {
4240
- // if(!that.state.tabTitles.find(el=>el.value == 'customerScreen')) {
4241
- cobj.drawImage(videoMedia, x, y, width, height, 0, 0, 960, 540);
4242
- // } else {
4243
- // cobj.fillStyle = 'rgb(0 0 0)'
4244
- // cobj.fillRect(0,0,960,540)
4245
- // }
4246
5489
 
4247
- setTimeout(loop, 1000 / 20); // drawing at 30fps
4248
- }
5490
+ if (this.state.drawCanvasInterval) clearInterval(this.state.drawCanvasInterval)
5491
+ $this.drawFunction = () => {
5492
+ if (!$this.paused && !$this.ended) {
5493
+ // if(!that.state.tabTitles.find(el=>el.value == 'customerScreen')) {
5494
+ cobj.drawImage(videoMedia, x, y, width, height, 0, 0, 960, 540);
5495
+ // } else {
5496
+ // cobj.fillStyle = 'rgb(0 0 0)'
5497
+ // cobj.fillRect(0,0,960,540)
5498
+ // }
5499
+ }
4249
5500
  }
4250
5501
 
5502
+ this.state.drawCanvasInterval = setInterval($this.drawFunction , 1000/ 20);
5503
+
4251
5504
  if (document.getElementById('video20').name) {
4252
5505
  // 代表已经有了进行切流
4253
5506
  publish_config.publish_device = 5
@@ -4270,10 +5523,12 @@ class Video extends Component {
4270
5523
  publish_config.publish_tag = 'projectionWhiteboard'
4271
5524
  this.test_controller.Publish(publish_config)
4272
5525
  }
4273
- }, 0);
5526
+ }
5527
+ videoMedia.addEventListener('play', this.state.whiteboardPlayEvent);
4274
5528
  navigator.mediaDevices.getDisplayMedia({
4275
5529
  video: true,
4276
5530
  preferCurrentTab: true,
5531
+ surfaceSwitching: "exclude"
4277
5532
  // audio: true
4278
5533
  // video: {
4279
5534
  // width: document.body.clientWidth,
@@ -4299,9 +5554,119 @@ class Video extends Component {
4299
5554
  //单击停止共享按钮后,触发这个事件
4300
5555
  streamShare = ''
4301
5556
  if (document.getElementById('video20').name && !this.state.isSharedScreen) {
5557
+ console.log('unPublish share, reason: click stop sharing whiteboard or stream onended')
5558
+ that.saveLog('unPublish share, reason: click stop sharing whiteboard or stream onended')
4302
5559
  that.test_controller.UnPublish(document.getElementById('video20').name)
4303
5560
  }
4304
5561
  }
5562
+
5563
+ // 关闭当前共享屏幕
5564
+ if (document.getElementById('video20') && document.getElementById('video20').name) {
5565
+ console.log('unPublish share, reason: going to share whiteboard, shared screen needs to be stopped')
5566
+ that.saveLog('unPublish share, reason: going to share whiteboard, shared screen needs to be stopped')
5567
+ that.test_controller.UnPublish(document.getElementById('video20').name)
5568
+ }
5569
+ that.state.isSharedScreen = false
5570
+ that.state.isScreenSwitching = false
5571
+ // that.setSharedScreenState(false)
5572
+ that.setState({
5573
+ screenName: '共享模式'
5574
+ });
5575
+ that.tabTitlesClick('RMScreen', 'delect')
5576
+
5577
+ }, error => {
5578
+ console.log("Unable to acquire screen capture", error);
5579
+ console.log('取消签署')
5580
+ that.saveLog('Manual cancel share')
5581
+ });
5582
+ }
5583
+ publishRecorderDevice = () => {
5584
+ if (this.state.recorderDevice){
5585
+ let publish_config = {}
5586
+ publish_config.media_type = 3
5587
+ publish_config.publish_device = 1
5588
+ publish_config.videoSource = this.state.recorderDevice.actionid
5589
+ publish_config.video_profile_type = 100
5590
+ publish_config.video_profile_diy = { width: 640, height: 360, frameRate: 15, bitrate: 400 }
5591
+ publish_config.publish_video_id = 'publish_video_record_device'
5592
+ publish_config.publish_streamId_id = 'publish_streamId_record_device'
5593
+ publish_config.publish_tag = 'sharedScreen'
5594
+ this.test_controller.Publish(publish_config)
5595
+ }
5596
+ }
5597
+ publishAllScreen = () => {
5598
+ const that = this
5599
+ const publish_config = {};
5600
+ const canvas = document.createElement('canvas');
5601
+ const videoMedia = document.getElementById('recordvideo');
5602
+ const cobj = canvas.getContext('2d'); // 获取绘图环境
5603
+ const left = document.getElementById("whiteboardDIV").getBoundingClientRect().left;
5604
+ const right = document.getElementById("whiteboardDIV").getBoundingClientRect().right
5605
+ const top = document.getElementById("whiteboardDIV").getBoundingClientRect().top
5606
+ const bottom = document.getElementById("whiteboardDIV").getBoundingClientRect().bottom
5607
+ let width = ((right - left) * window.screen.width / document.body.clientWidth) - 5
5608
+ let height = ((bottom - top) * window.screen.width / document.body.clientWidth) - 30
5609
+ let x = (left * window.screen.width / document.body.clientWidth)
5610
+ let y = (top * window.screen.width / document.body.clientWidth) + 8
5611
+ // console.error(left, right, top, bottom)
5612
+ // console.error(width,height,x,y)
5613
+
5614
+
5615
+ canvas.width = 960;
5616
+ canvas.height = 540;
5617
+
5618
+
5619
+ videoMedia.addEventListener('play', (event) => {
5620
+ var $this = this; //cache
5621
+ console.log('addEventListener', !$this.paused, !$this.ended, x, y, width, height)
5622
+ loop()
5623
+ function loop() {
5624
+ if (!$this.paused && !$this.ended) {
5625
+ cobj.drawImage(videoMedia, x, y, width, height, 0, 0, 960, 540);
5626
+ setTimeout(loop, 1000 / 20); // drawing at 30fps
5627
+ }
5628
+ }
5629
+
5630
+ publish_config.media_type = 3
5631
+ publish_config.publish_device = 5
5632
+ publish_config.need_volume_analyser = false
5633
+ publish_config.video_profile_type = 1
5634
+ publish_config.degradationType = 2
5635
+ publish_config.stream = canvas.captureStream(10)
5636
+ publish_config.publish_video_id = 'record_video'
5637
+ publish_config.publish_streamId_id = 'record_video_streamId'
5638
+ publish_config.publish_tag = 'RM_ALL_SCREEN'
5639
+ this.test_controller.Publish(publish_config)
5640
+ }, 0);
5641
+ navigator.mediaDevices.getDisplayMedia({
5642
+ video: true,
5643
+ preferCurrentTab: true,
5644
+ surfaceSwitching: "exclude"
5645
+ })
5646
+ .then((stream) => {
5647
+ if (streamRecord) {
5648
+ streamRecord.getTracks().forEach(track => track.stop());
5649
+ streamRecord = ''
5650
+ }
5651
+ videoMedia.srcObject = stream;
5652
+ stream.getVideoTracks()[0].applyConstraints({
5653
+ // width: 1280,
5654
+ // height: 720
5655
+ width: window.screen.width,
5656
+ height: window.screen.height
5657
+ })
5658
+
5659
+ streamRecord = stream
5660
+
5661
+ stream.getVideoTracks()[0].onended = async () => {
5662
+ //单击停止共享按钮后,触发这个事件
5663
+ streamRecord = ''
5664
+ if (document.getElementById('record_video').name) {
5665
+ that.saveLog('unPublish share, reason: click stop recording all screen or stream onended')
5666
+ console.log('unPublish share, reason: click stop recording all screen or stream onended')
5667
+ that.test_controller.UnPublish(document.getElementById('record_video').name)
5668
+ }
5669
+ }
4305
5670
  }, error => {
4306
5671
  console.log("Unable to acquire screen capture", error);
4307
5672
  });
@@ -4477,13 +5842,151 @@ class Video extends Component {
4477
5842
  this.test_controller.GetDevices()
4478
5843
  }
4479
5844
  }
5845
+ toggleAsr = () => {
5846
+ if (this.isFileSuccuse()) {
5847
+ if (!this.state.isAsrStart){
5848
+ this.startASR()
5849
+ } else {
5850
+ this.stopASR()
5851
+ }
5852
+ }
5853
+ }
5854
+ showEnvDetection = () => {
5855
+ this.envDetection()
5856
+ this.setState({
5857
+ isModalVisibleEnvironment: true,
5858
+ })
5859
+ }
5860
+
5861
+ envDetection = () => {
5862
+ let self = this
5863
+ let envInfo = {
5864
+ batteryCharging: '未知', // 电池充电
5865
+ batteryLevel: '未知', // 电池电量
5866
+ networkStatus: '未知', // 网络状态 (已连接/未连接)
5867
+ cameraResult: this.state.cameraList.length>0 ? '合格': '不合格', // 摄像头检测
5868
+ microResult: this.state.microphoneList.length>0 ? '合格': '不合格', // 麦克风检测
5869
+ speakerResult: this.state.speakerList.length>0 ? '合格': '不合格',
5870
+ lightResult: this.state.envInfo? this.state.envInfo.lightResult : '未知'
5871
+ }
5872
+
5873
+ // 扬声器检测
5874
+ const detectSpeaker = this.props.speakerNames instanceof Array && this.props.speakerNames.length > 0;
5875
+ if (detectSpeaker) {
5876
+ envInfo.speakerResult = (this.state.speakerList.length >0 &&
5877
+ this.props.speakerNames.find(el => (this.state.speakerList[0].actionname).includes(el)))? '合格' : '不合格';
5878
+ }
5879
+ if (navigator) {
5880
+ // 电量检测
5881
+ navigator.getBattery().then(function(battery) {
5882
+ // console.log(battery)
5883
+ // 是否正在充电,yes-充电
5884
+ envInfo.batteryCharging = (battery.charging ? "正在充电" : "不在充电")
5885
+ // 当前剩余电量
5886
+ envInfo.batteryLevel = battery.level * 100 + "%"
5887
+ envInfo.batteryResult = (battery.charging )? '合格': '不合格'
5888
+ self.setState({
5889
+ envInfo: envInfo
5890
+ })
5891
+ battery.removeEventListener("chargingchange", self.envDetection);
5892
+ battery.removeEventListener("levelchange", self.envDetection);
5893
+ battery.addEventListener("chargingchange", self.envDetection);
5894
+ battery.addEventListener("levelchange", self.envDetection);
5895
+ });
5896
+
5897
+ // 网络检测
5898
+ envInfo.networkStatus = window.navigator.onLine? '已连接': '未连接'
5899
+ envInfo.networkResult = window.navigator.onLine? '合格': '不合格'
5900
+ window.removeEventListener("offline", self.envDetection);
5901
+ window.removeEventListener("online", self.envDetection);
5902
+ window.addEventListener("offline", self.envDetection);
5903
+ window.addEventListener("online", self.envDetection);
5904
+ if (navigator.connection){
5905
+ function setNetworkInfo() {
5906
+ const { rtt, downlink, effectiveType, saveData } = navigator.connection;
5907
+ // console.log(`有效网络连接类型: ${effectiveType}`);
5908
+ // console.log(`估算的下行速度/带宽: ${downlink}Mb/s`);
5909
+ // console.log(`估算的往返时间: ${rtt}ms`);
5910
+ if (!window.navigator.onLine) {
5911
+ envInfo.networkInfo = ''}
5912
+ else {
5913
+ envInfo.networkInfo = `等效网络类型:${effectiveType};预估下行速度/带宽:${downlink}Mb/s;预估往返延时:${rtt}ms`
5914
+ envInfo.networkResult = downlink > 0.2? '合格': '不合格'
5915
+ }
5916
+ }
5917
+ setNetworkInfo()
5918
+ navigator.connection.removeEventListener('change', self.envDetection);
5919
+ navigator.connection.addEventListener('change', self.envDetection);
5920
+ }
5921
+
5922
+ }
5923
+
5924
+ // 背景曝光环境检测
5925
+ this.lightDetect()
5926
+
5927
+ this.setState({
5928
+ // isModalVisibleEnvironment: true,
5929
+ envInfo: envInfo
5930
+ })
5931
+ }
5932
+ handleRetryEnvDetection = () => {
5933
+ this.lightDetect();
5934
+ message.success({
5935
+ content: '已更新检测结果',
5936
+ icon: <img src={require("../../assets/img/tooltips1_pass.png").default} alt="" ></img>,
5937
+ className: 'successClassName',
5938
+ top: 200,
5939
+ duration: 3
5940
+ })
5941
+ }
5942
+ handleOkEnvDetection = async () => {
5943
+ this.setState({
5944
+ isModalVisibleEnvironment: false,
5945
+ })
5946
+ if (!this.state.isPictureInPicture) {
5947
+ this.pictureInPicture()
5948
+ }
5949
+ // 分行模式,需要自动开启业务录制
5950
+ if (this.props.recordMode == 2) {
5951
+ this.startBusinessRecord()
5952
+ }
5953
+ }
5954
+
5955
+ async startBusinessRecord() {
5956
+ const busData = this.props.getBusinessData()
5957
+ if (busData) {
5958
+ try {
5959
+ let result = await API.startBusinessRecord({
5960
+ sessionId: this.state.sessionId,
5961
+ roomId: this.state.channelId,
5962
+ type: 1,
5963
+ ...busData
5964
+ });
5965
+ console.log(result)
5966
+ if (result.code == 200) {
5967
+ console.log('成功')
5968
+ } else if (result.code == 500) {
5969
+ this.messageClick('服务异常,业务录制开启失败','error')
5970
+ } else {
5971
+ console.warn('业务录制开启失败', result.code, result.message)
5972
+ }
5973
+ } catch (err) {
5974
+ console.log(err)
5975
+ }
5976
+ }
5977
+ }
5978
+ // handleCancelEnvDetection = () => {
5979
+ // this.setState({
5980
+ // isModalVisibleEnvironment: false
5981
+ // })
5982
+ // }
4480
5983
  handleOkInspection = () => {
4481
5984
  this.setState({
4482
5985
  isModalVisibleInspection: false,
4483
5986
  loading: true
4484
5987
  })
4485
5988
  const config = {}
4486
- config.sid = document.getElementById('publish_video1').name
5989
+ config.sid = document.getElementById('publish_video1').name || document.getElementById('publish_streamId1').name
4487
5990
  config.videoSource = this.state.cameraValue
4488
5991
  config.audioSource = this.state.microphoneValue
4489
5992
  this.test_controller.ChangeProfile(config)
@@ -4522,16 +6025,39 @@ class Video extends Component {
4522
6025
  this.setState({
4523
6026
  beautyName: '开启美颜'
4524
6027
  })
6028
+ beautyMode = 'none'
4525
6029
  beautySetMode('none')
6030
+ beautyStop()
6031
+ if(!isSuccuseHs) {
6032
+ stopHs()
6033
+ }
4526
6034
  } else {
4527
6035
  this.state.beautyType = true
6036
+ beautyMode = 'beauty'
4528
6037
  beautySetMode('beauty')
4529
6038
  this.setState({
4530
6039
  beautyName: '关闭美颜'
4531
6040
  })
4532
6041
  }
6042
+ this.changeMediaStream();
4533
6043
 
4534
6044
  }
6045
+ changeMediaStream = () => {
6046
+ let publish_config = {}
6047
+ publish_config.sid = document.getElementById('publish_video1').name || document.getElementById('publish_streamId1').name
6048
+ publish_config.media_type = 1
6049
+ publish_config.publish_device = 1
6050
+ // publish_config.videoSource = this.state.cameraValue
6051
+ // publish_config.audioSource = this.state.microphoneValue
6052
+ publish_config.need_volume_analyser = true
6053
+ publish_config.video_profile_type = 100
6054
+ publish_config.video_profile_diy = { width: 640, height: 360, frameRate: 15, bitrate: 400 }
6055
+ // publish_config.publish_video_id = 'publish_video1'
6056
+ // publish_config.publish_streamId_id = 'publish_streamId1'
6057
+ // publish_config.publish_tag = 'tag1'
6058
+ this.test_controller.ChangeMediaStream(publish_config)
6059
+ }
6060
+
4535
6061
  componentDidMount() {
4536
6062
  var box = document.getElementById("whiteboardDIV");
4537
6063
  var box1 = document.getElementById("operate")
@@ -4549,117 +6075,81 @@ class Video extends Component {
4549
6075
  muteOpposite = (value) => {
4550
6076
  console.log(value);
4551
6077
  if (value == 'video1') {
4552
- callNimIM('sendCustomCmdMsg', {
4553
- customId: this.state.imRoomId,
4554
- content: JSON.stringify({
4555
- 'typeId': 1223,
4556
- 'sessionId': this.state.sessionId,
4557
- 'userId': this.seeList(this.state.roomCustomerList, 'feedId', document.getElementById('feedId1').innerText).uid
4558
- })
4559
- });
6078
+ this.sendMessage({
6079
+ 'typeId': 1223,
6080
+ 'sessionId': this.state.sessionId,
6081
+ 'userId': this.seeList(this.state.roomCustomerList, 'feedId', document.getElementById('feedId1').innerText).uid
6082
+ })
4560
6083
  }
4561
6084
  if (value == 'video2') {
4562
- callNimIM('sendCustomCmdMsg', {
4563
- customId: this.state.imRoomId,
4564
- content: JSON.stringify({
4565
- 'typeId': 1223,
4566
- 'sessionId': this.state.sessionId,
4567
- 'userId': this.seeList(this.state.roomCustomerList, 'feedId', document.getElementById('feedId2').innerText).uid
4568
- })
4569
- });
6085
+ this.sendMessage({
6086
+ 'typeId': 1223,
6087
+ 'sessionId': this.state.sessionId,
6088
+ 'userId': this.seeList(this.state.roomCustomerList, 'feedId', document.getElementById('feedId2').innerText).uid
6089
+ })
4570
6090
  } if (value == 'video3') {
4571
- callNimIM('sendCustomCmdMsg', {
4572
- customId: this.state.imRoomId,
4573
- content: JSON.stringify({
4574
- 'typeId': 1223,
4575
- 'sessionId': this.state.sessionId,
4576
- 'userId': this.seeList(this.state.roomCustomerList, 'feedId', document.getElementById('feedId3').innerText).uid
4577
- })
4578
- });
6091
+ this.sendMessage({
6092
+ 'typeId': 1223,
6093
+ 'sessionId': this.state.sessionId,
6094
+ 'userId': this.seeList(this.state.roomCustomerList, 'feedId', document.getElementById('feedId3').innerText).uid
6095
+ })
4579
6096
  } if (value == 'video4') {
4580
- callNimIM('sendCustomCmdMsg', {
4581
- customId: this.state.imRoomId,
4582
- content: JSON.stringify({
4583
- 'typeId': 1223,
4584
- 'sessionId': this.state.sessionId,
4585
- 'userId': this.seeList(this.state.roomCustomerList, 'feedId', document.getElementById('feedId4').innerText).uid
4586
- })
4587
- });
6097
+ this.sendMessage({
6098
+ 'typeId': 1223,
6099
+ 'sessionId': this.state.sessionId,
6100
+ 'userId': this.seeList(this.state.roomCustomerList, 'feedId', document.getElementById('feedId4').innerText).uid
6101
+ })
4588
6102
  } if (value == 'video5') {
4589
- callNimIM('sendCustomCmdMsg', {
4590
- customId: this.state.imRoomId,
4591
- content: JSON.stringify({
4592
- 'typeId': 1223,
4593
- 'sessionId': this.state.sessionId,
4594
- 'userId': this.seeList(this.state.roomCustomerList, 'feedId', document.getElementById('feedId5').innerText).uid
4595
- })
4596
- });
6103
+ this.sendMessage({
6104
+ 'typeId': 1223,
6105
+ 'sessionId': this.state.sessionId,
6106
+ 'userId': this.seeList(this.state.roomCustomerList, 'feedId', document.getElementById('feedId5').innerText).uid
6107
+ })
4597
6108
  } if (value == 'video6') {
4598
- callNimIM('sendCustomCmdMsg', {
4599
- customId: this.state.imRoomId,
4600
- content: JSON.stringify({
4601
- 'typeId': 1223,
4602
- 'sessionId': this.state.sessionId,
4603
- 'userId': this.seeList(this.state.roomCustomerList, 'feedId', document.getElementById('feedId6').innerText).uid
4604
- })
4605
- });
6109
+ this.sendMessage({
6110
+ 'typeId': 1223,
6111
+ 'sessionId': this.state.sessionId,
6112
+ 'userId': this.seeList(this.state.roomCustomerList, 'feedId', document.getElementById('feedId6').innerText).uid
6113
+ })
4606
6114
  } if (value == 'video7') {
4607
- callNimIM('sendCustomCmdMsg', {
4608
- customId: this.state.imRoomId,
4609
- content: JSON.stringify({
4610
- 'typeId': 1223,
4611
- 'sessionId': this.state.sessionId,
4612
- 'userId': this.seeList(this.state.roomCustomerList, 'feedId', document.getElementById('feedId7').innerText).uid
4613
- })
4614
- });
6115
+ this.sendMessage({
6116
+ 'typeId': 1223,
6117
+ 'sessionId': this.state.sessionId,
6118
+ 'userId': this.seeList(this.state.roomCustomerList, 'feedId', document.getElementById('feedId7').innerText).uid
6119
+ })
4615
6120
  } if (value == 'video8') {
4616
- callNimIM('sendCustomCmdMsg', {
4617
- customId: this.state.imRoomId,
4618
- content: JSON.stringify({
4619
- 'typeId': 1223,
4620
- 'sessionId': this.state.sessionId,
4621
- 'userId': this.seeList(this.state.roomCustomerList, 'feedId', document.getElementById('feedId8').innerText).uid
4622
- })
4623
- });
6121
+ this.sendMessage({
6122
+ 'typeId': 1223,
6123
+ 'sessionId': this.state.sessionId,
6124
+ 'userId': this.seeList(this.state.roomCustomerList, 'feedId', document.getElementById('feedId8').innerText).uid
6125
+ })
4624
6126
  } if (value == 'video9') {
4625
- callNimIM('sendCustomCmdMsg', {
4626
- customId: this.state.imRoomId,
4627
- content: JSON.stringify({
4628
- 'typeId': 1223,
4629
- 'sessionId': this.state.sessionId,
4630
- 'userId': this.seeList(this.state.roomCustomerList, 'feedId', document.getElementById('feedId9').innerText).uid
4631
- })
4632
- });
6127
+ this.sendMessage({
6128
+ 'typeId': 1223,
6129
+ 'sessionId': this.state.sessionId,
6130
+ 'userId': this.seeList(this.state.roomCustomerList, 'feedId', document.getElementById('feedId9').innerText).uid
6131
+ })
4633
6132
  }
4634
6133
  if (value == 'video10') {
4635
- callNimIM('sendCustomCmdMsg', {
4636
- customId: this.state.imRoomId,
4637
- content: JSON.stringify({
4638
- 'typeId': 1223,
4639
- 'sessionId': this.state.sessionId,
4640
- 'userId': this.seeList(this.state.roomCustomerList, 'feedId', document.getElementById('feedId10').innerText).uid
4641
- })
4642
- });
6134
+ this.sendMessage({
6135
+ 'typeId': 1223,
6136
+ 'sessionId': this.state.sessionId,
6137
+ 'userId': this.seeList(this.state.roomCustomerList, 'feedId', document.getElementById('feedId10').innerText).uid
6138
+ })
4643
6139
  }
4644
6140
  if (value == 'video11') {
4645
- callNimIM('sendCustomCmdMsg', {
4646
- customId: this.state.imRoomId,
4647
- content: JSON.stringify({
4648
- 'typeId': 1223,
4649
- 'sessionId': this.state.sessionId,
4650
- 'userId': this.seeList(this.state.roomCustomerList, 'feedId', document.getElementById('feedId11').innerText).uid
4651
- })
4652
- });
6141
+ this.sendMessage({
6142
+ 'typeId': 1223,
6143
+ 'sessionId': this.state.sessionId,
6144
+ 'userId': this.seeList(this.state.roomCustomerList, 'feedId', document.getElementById('feedId11').innerText).uid
6145
+ })
4653
6146
  }
4654
6147
  if (value == 'video12') {
4655
- callNimIM('sendCustomCmdMsg', {
4656
- customId: this.state.imRoomId,
4657
- content: JSON.stringify({
4658
- 'typeId': 1223,
4659
- 'sessionId': this.state.sessionId,
4660
- 'userId': this.seeList(this.state.roomCustomerList, 'feedId', document.getElementById('feedId12').innerText).uid
4661
- })
4662
- });
6148
+ this.sendMessage({
6149
+ 'typeId': 1223,
6150
+ 'sessionId': this.state.sessionId,
6151
+ 'userId': this.seeList(this.state.roomCustomerList, 'feedId', document.getElementById('feedId12').innerText).uid
6152
+ })
4663
6153
  }
4664
6154
 
4665
6155
  }
@@ -4668,14 +6158,11 @@ class Video extends Component {
4668
6158
  this.state.shareMaskState = this.props.shareMask
4669
6159
  // 加延迟是因为在关闭的时候可以看到部分rm的操作
4670
6160
  setTimeout(() => {
4671
- callNimIM('sendCustomCmdMsg', {
4672
- customId: this.state.imRoomId,
4673
- content: JSON.stringify({
4674
- 'typeId': 1230,
4675
- 'sessionId': this.state.sessionId,
4676
- 'type': this.state.shareMaskState ? 1 : 2
4677
- })
4678
- });
6161
+ this.sendMessage({
6162
+ 'typeId': 1230,
6163
+ 'sessionId': this.state.sessionId,
6164
+ 'type': this.state.shareMaskState ? 1 : 2
6165
+ })
4679
6166
  }, 100)
4680
6167
 
4681
6168
  }
@@ -4683,11 +6170,18 @@ class Video extends Component {
4683
6170
  if (!isSuccuseHs) {
4684
6171
 
4685
6172
  hsSetMode('blur')
6173
+ hsMode = 'blur'
4686
6174
  isSuccuseHs = true
4687
6175
  } else {
4688
6176
  hsSetMode('none')
6177
+ hsMode = 'none'
4689
6178
  isSuccuseHs = false
6179
+ stopHs()
6180
+ if(!this.state.beautyType) {
6181
+ beautyStop()
6182
+ }
4690
6183
  }
6184
+ this.changeMediaStream();
4691
6185
  }
4692
6186
  virtualization = () => {
4693
6187
  this.virtualizationClick()
@@ -4714,6 +6208,17 @@ class Video extends Component {
4714
6208
  return false;
4715
6209
  }
4716
6210
  }
6211
+ isHKPassValidTime=(value)=>{
6212
+ if (!value.split('.') || value.split('.').length < 3 || value.split('.').some(el => el == '')) return false;
6213
+ let start = new Date('2020.01.01').valueOf();
6214
+ let end = new Date('2023.12.31').valueOf();
6215
+ var time = new Date(value).valueOf();
6216
+ if(start<=time && end >= time ){
6217
+ return true;
6218
+ }else{
6219
+ return false;
6220
+ }
6221
+ }
4717
6222
  handleChangeCertificateValidity = (event) => {
4718
6223
  // 护照只有起始日期,单独处理
4719
6224
  if (this.state.documentType == 'PASSPORT_CARD' && event.target.value.split('.').length >2) {
@@ -4734,6 +6239,12 @@ class Video extends Component {
4734
6239
  certificateValidity: event.target.value,
4735
6240
  certificateValidityType: true
4736
6241
  });
6242
+ } else if (this.state.documentType == 'HK_MO_PASS_CARD' && this.isHKPassValidTime(event.target.value.split('-')[1])){
6243
+ // 疫情政策对港澳来往通行证放宽限制,有效期限从2020.1.1到2023.12.31都算有效
6244
+ this.setState({
6245
+ certificateValidity: event.target.value,
6246
+ certificateValidityType: true
6247
+ });
4737
6248
  } else {
4738
6249
  this.setState({
4739
6250
  certificateValidity: event.target.value,
@@ -4748,6 +6259,9 @@ class Video extends Component {
4748
6259
  if (this.props.shareMask != prevProps.shareMask) {
4749
6260
  this.sendNotification()
4750
6261
  }
6262
+ if (this.props.pdfRendering != prevProps.pdfRendering) {
6263
+ this.changePdfRendering()
6264
+ }
4751
6265
  }
4752
6266
  onChangeOCRCustomer = (e) => {
4753
6267
  console.log(e)
@@ -4848,8 +6362,10 @@ class Video extends Component {
4848
6362
 
4849
6363
  }))
4850
6364
  }
4851
-
4852
-
6365
+ this.setState({
6366
+ documentError: '',
6367
+ isModalVisibleCustomer: false,
6368
+ })
4853
6369
  }
4854
6370
  })
4855
6371
  // this.customerFaceClick(this.state.customerList[this.state.customerSelect])
@@ -5062,6 +6578,15 @@ class Video extends Component {
5062
6578
  </div>
5063
6579
  )
5064
6580
 
6581
+ const isEnvironmentOK = !this.state.loading &&
6582
+ this.state.envInfo.networkResult=='合格' &&
6583
+ this.state.envInfo.batteryResult=='合格' &&
6584
+ (this.state.envInfo.cameraResult=='合格' || this.props.recordMode == 2) &&
6585
+ this.state.envInfo.microResult=='合格' &&
6586
+ this.state.envInfo.speakerResult=='合格' &&
6587
+ (this.state.envInfo.lightResult=='合格' || this.props.recordMode == 2 ) &&
6588
+ (this.state.ipadTag || this.props.recordMode != 2)
6589
+
5065
6590
  const sectionStyle = this.state.tabTitles.length > 0 ? {
5066
6591
  zIndex: '-1',
5067
6592
  width: '100%',
@@ -5087,7 +6612,7 @@ class Video extends Component {
5087
6612
  return (
5088
6613
  <div className="all" id="allHSBC">
5089
6614
  <Spin spinning={this.state.loading} tip="视频初始化中...">
5090
- <Header></Header>
6615
+ <Header recordMode={this.props.recordMode}></Header>
5091
6616
  <div className="health">
5092
6617
  <div className="healthVideo">
5093
6618
  <div className="projection" style={{ background: this.state.tabTitles.length > 0 ? '#f0f0f0' : '#ffffff' }}>
@@ -5108,6 +6633,18 @@ class Video extends Component {
5108
6633
  }
5109
6634
  <canvas id="canvas" className="canvas"></canvas>
5110
6635
  </CanvasHome>
6636
+ <div className="videoDiv" style={{ display: (this.state.isSelect == 'multiModule') ? '' : 'none', }}>
6637
+ <div className="videoDiv">
6638
+ {/* <div style={{ display: (this.state.multiModuleShow) ? '' : 'none', height: '100%'}}> */}
6639
+ {
6640
+ this.state.multiModuleShow &&
6641
+ <div style={{ height: '100%'}}>
6642
+ <MultiModule moduleName={this.state.multiModule} data={this.state.moduleData} finish={this.closeModule} handleReceiveMsg={this.handleReceiveMsg}></MultiModule>
6643
+ </div>
6644
+ }
6645
+ </div>
6646
+
6647
+ </div>
5111
6648
  <div className="videoDiv" style={{ display: (this.state.isSelect == 'RMScreen' || this.state.isSelect == 'staffScreen') ? '' : 'none', }}>
5112
6649
  <div className="videoDiv" style={{ 'textAlign': 'center' }}>
5113
6650
  <video
@@ -5166,19 +6703,28 @@ class Video extends Component {
5166
6703
  {otherAttendeesList}
5167
6704
  </li>
5168
6705
  }
6706
+ {
6707
+ this.props.recordMode != 2 &&
5169
6708
  <li>
5170
6709
  请注意,若会议中需要客户出示证件,请客户使用手机的后置摄像头展示证件,由客户经理拍摄证件照片以完成客户身份核实。客户可点击会议主页面上的”切换摄像头“按钮切换手机摄像头
5171
6710
  </li>
6711
+ }
5172
6712
 
5173
6713
  </ul>
5174
6714
  </div>
5175
- {!this.state.loading && this.state.sessionId?
5176
- <QRCode
5177
- style={{'position': 'absolute', 'right': '10px', 'top': '-110px'}}
5178
- value={this.state.sessionId} //value参数为生成二维码的链接
5179
- size={100} //二维码的宽高尺寸
6715
+ {!this.state.loading && this.state.sessionType && this.state.sessionId && this.props.recordMode == 2?
6716
+ <div className='QRCode'>
6717
+ <QRCode
6718
+ value={JSON.stringify({
6719
+ sessionId:this.state.sessionId,
6720
+ staffId: this.props.tellerAccount,
6721
+ staffName: this.props.staffName
6722
+ })} //value参数为生成二维码的链接
6723
+ size={110} //二维码的宽高尺寸
5180
6724
  fgColor="#000000" //二维码的颜色
5181
- /> : null}
6725
+ />
6726
+ <div className='sessionDiv' style={{marginTop: '20px'}}><span>会议号码</span><div className='num'>{this.state.sessionId}</div></div>
6727
+ </div> : null}
5182
6728
  </div>
5183
6729
  }
5184
6730
 
@@ -5188,6 +6734,7 @@ class Video extends Component {
5188
6734
  <div id="videoList" className={`wrapper ${this.state.isVideoList? 'videoListClass': ''}`} style={{ width: '20%' }}>
5189
6735
  <div
5190
6736
  className={`itemed ${this.state.isVideoList? 'videoMinutuListClass': 'videoMinutuClass'}`}
6737
+ style={{ display: (this.props.recordMode == 2) ? 'none' : ''}}
5191
6738
  >
5192
6739
  <div className="publishVideoDiv">
5193
6740
 
@@ -5216,7 +6763,7 @@ class Video extends Component {
5216
6763
  </div>
5217
6764
 
5218
6765
  </div>
5219
- {
6766
+ {/* {
5220
6767
  this.state.cameraList.map((item, index) => {
5221
6768
  if (index > 0)
5222
6769
  return <div
@@ -5249,7 +6796,7 @@ class Video extends Component {
5249
6796
  </div>
5250
6797
  </div>
5251
6798
  })
5252
- }
6799
+ } */}
5253
6800
  {/* <div className={`itemed ${this.state.isVideoList? 'videoMinutuListClass': 'videoMinutuClass'}`}
5254
6801
  style={{ position: "relative", display: (this.state.videoList[0].videoName) ? '' : 'none' }}
5255
6802
  >
@@ -5298,7 +6845,8 @@ class Video extends Component {
5298
6845
  <audio id={'audio'+(item.idIndex)} autoPlay />
5299
6846
  <label style={{ display: 'none' }} id={'feedId'+(item.idIndex)} type="text" />
5300
6847
 
5301
- <div style={{ display: (item.videoName) ? '' : 'none'}} className={`customerTitle titleSamlle`}>
6848
+ <div onClick={this.muteOpposite.bind(this, 'video'+(item.idIndex))} style={{ display: (item.videoName) ? '' : 'none'}} className={`customerTitle titleSamlle`}>
6849
+ { item.videoName.includes(IPAD_SUFFIX) ? <span style={{paddingLeft: '8px'}}> </span>:<>
5302
6850
  {
5303
6851
  item.mute && <img
5304
6852
  alt=""
@@ -5307,7 +6855,7 @@ class Video extends Component {
5307
6855
  />
5308
6856
  }
5309
6857
  <canvas style={{ display: (item.videoName && !item.mute) ? '' : 'none',width: '25px',height:'25px',marginTop: '4px' }} className="canvasClassOne" id={"subscribe_volumeView"+(item.idIndex)} width="40" height="70"></canvas>
5310
-
6858
+ </>}
5311
6859
  <div className='titleName' style={{ color: this.props.titleColor,fontSize: this.props.fontSize + 'px',fontFamily : this.props.fontFamily}}>
5312
6860
  {item.videoName}
5313
6861
  </div>
@@ -5338,7 +6886,7 @@ class Video extends Component {
5338
6886
  ocrHandleVisibleChange={this.ocrHandleVisibleChange}
5339
6887
  voice={this.voice}
5340
6888
  cameraClick={this.cameraClick}
5341
- sharedScreen={this.sharedScreen}
6889
+ sharedScreen={()=> {this.saveLog('Click share button');this.sharedScreen();}}
5342
6890
  endSession={this.endSession}
5343
6891
  facialRecognition={this.facialRecognition}
5344
6892
  pictureInPicture={this.pictureInPicture}
@@ -5346,8 +6894,10 @@ class Video extends Component {
5346
6894
  invitationClick={this.invitationClick}
5347
6895
  customerFaceClick={this.customerFaceClick}
5348
6896
  ocrClick={this.ocrClick}
5349
- switchExternal={this.switchExternal}
6897
+ switchExternal={()=> {this.saveLog('Click sign button');this.switchExternal();}}
5350
6898
  inspection={this.inspection}
6899
+ toggleAsr={this.toggleAsr}
6900
+ envDetection={this.showEnvDetection}
5351
6901
  beautyClick={this.beautyClick}
5352
6902
  graffiti={this.graffiti}
5353
6903
  virtualization={this.virtualization}
@@ -5362,6 +6912,60 @@ class Video extends Component {
5362
6912
  !this.state.isSuspend && <span>确定是否暂停会话?</span>
5363
6913
  }
5364
6914
  </Modal>
6915
+ {/* 画中画重新开启确认 */}
6916
+ <Modal closable={false} centered={true} visible={this.state.isPictureConfirmModalVisible} maskClosable={false} footer={[
6917
+ <div key='end'>
6918
+ {/* <Button className="modelButtonCancel" onClick={()=> {this.setState({isPictureConfirmModalVisible: false})}}>取消</Button> */}
6919
+ <Button className="modelButtonOk" type="primary" danger onClick={this.handleOkPictureConfirm}>确定</Button>
6920
+ </div>
6921
+ ]}>
6922
+ <div className='endModal'>视频浮窗已关闭,请重新开启</div>
6923
+ </Modal>
6924
+ {/* 连接断开 */}
6925
+ {/* <Modal closable={false} centered={true} visible={this.state.isDisconnectModalVisible} maskClosable={false} footer={[
6926
+ <div key='end'>
6927
+ <Button className="modelButtonOk" type="primary" danger onClick={this.isDisconnectModalVisible}>确定</Button>
6928
+ </div>
6929
+ ]}>
6930
+ <div className='endModal'>您的连接已断开,请稍后重试</div>
6931
+ </Modal> */}
6932
+ {/* 双录中断重新开启确认 */}
6933
+ <Modal closable={false} centered={true} visible={this.state.isRecordingeErrorModalVisible} maskClosable={false} footer={[
6934
+ <div key='end'>
6935
+ <Button className="modelButtonOk" type="primary" danger onClick={this.handleOkRecordConfirm}>确定</Button>
6936
+ </div>
6937
+ ]}>
6938
+ <div className='endModal'>双录异常中断,请重新开启</div>
6939
+ </Modal>
6940
+ {/* ipad低电量确认 */}
6941
+ <Modal closable={false} centered={true} visible={this.state.ipadLowPowerErrorModalVisible} maskClosable={false} footer={[
6942
+ <div key='end'>
6943
+ <Button className="modelButtonOk" type="primary" danger onClick={this.handleOkLowPowerConfirm}>确定</Button>
6944
+ </div>
6945
+ ]}>
6946
+ <div className='endModal'>iPad电量过低,请检查</div>
6947
+ </Modal>
6948
+ {/* 双录中ipad退出确认 */}
6949
+ <Modal closable={false} centered={true} visible={this.state.IpadLeaveErrorModalVisible} maskClosable={false} width={350} footer={[
6950
+ <div key='end'>
6951
+ <Button className="modelButtonOk" type="primary" danger onClick={this.handleOkIpadLeaveConfirm}>确定</Button>
6952
+ </div>
6953
+ ]}>
6954
+ <div className='ipadModal'>iPad 摄像头异常退出,请扫码或输入会议号入会</div>
6955
+ <div className='QRCode center'>
6956
+ <QRCode
6957
+ value={JSON.stringify({
6958
+ sessionId:this.state.sessionId,
6959
+ staffId: this.props.tellerAccount,
6960
+ staffName: this.props.staffName
6961
+ })} //value参数为生成二维码的链接
6962
+ className="ipadCode"
6963
+ size={120} //二维码的宽高尺寸
6964
+ fgColor="#000000" //二维码的颜色
6965
+ />
6966
+ <div className='sessionDiv'><span>会议号码</span><div className='num'>{this.state.sessionId}</div></div>
6967
+ </div>
6968
+ </Modal>
5365
6969
  {/* 是否退出会议*/}
5366
6970
  <Modal closable={false} centered={true} visible={this.state.isModalVisibleEnd} maskClosable={false} footer={[
5367
6971
  <div key='end'>
@@ -5369,7 +6973,7 @@ class Video extends Component {
5369
6973
  <Button className="modelButtonOk" type="primary" danger onClick={this.handleOkEnd}>确定</Button>
5370
6974
  </div>
5371
6975
  ]}>
5372
- <div className='endModal'>是否要结束并退出会议?</div>
6976
+ <div className='endModal'>{this.state.businessId? '正在进行业务录制,是否确认结束并退出会议?': '是否要结束并退出会议?'}</div>
5373
6977
  </Modal>
5374
6978
  {/* ocr及人脸 */}
5375
6979
  <Modal title={this.state.titleModal} width={800} closable={true} maskClosable={false} onCancel={this.handleCancelFacial} centered={true} visible={this.state.isModalVisibleFacial} footer={[
@@ -5709,10 +7313,99 @@ class Video extends Component {
5709
7313
 
5710
7314
  </div>
5711
7315
  </Modal>
7316
+ <Modal title="环境检测" maskClosable={false} width={650} closable={false} centered={true} visible={this.state.isModalVisibleEnvironment} footer={[
7317
+ <div key='env'>
7318
+ <Button className="modelButtonCancel" onClick={this.handleRetryEnvDetection}>重新检测</Button>
7319
+ <Button className={isEnvironmentOK ?"modelButtonOk": "modelButtonNo"} type="primary" disabled={!isEnvironmentOK } danger onClick={this.handleOkEnvDetection}>确定</Button>
7320
+ </div>
7321
+ ]}>
7322
+ <Collapse defaultActiveKey={['1', '2', '3', '4', '5', '6']} ghost>
7323
+
7324
+ <Panel header={<span>网络检测 - {this.state.envInfo.networkResult } {this.state.envInfo.networkResult=='不合格'? <img src={IconFail} />: <img src={IconSuccess} />}</span>}
7325
+ key="5" className={this.state.envInfo.networkResult=='不合格'? 'panel-error':''} >
7326
+ <p className='envClass'>网络状态:{this.state.envInfo.networkStatus}</p>
7327
+ {this.state.envInfo.networkInfo?<p className='envClass'>{this.state.envInfo.networkInfo}</p>:null}
7328
+ </Panel>
7329
+ <Panel header={<span>设备电量 - {this.state.envInfo.batteryResult} {this.state.envInfo.batteryResult=='不合格'? <img src={IconFail} />: <img src={IconSuccess} />} </span>}
7330
+ key="2" className={this.state.envInfo.batteryResult=='不合格'? 'panel-error':''}>
7331
+ <p className='envClass'>电量:{this.state.envInfo.batteryLevel}({this.state.envInfo.batteryCharging})</p>
7332
+ </Panel>
7333
+ {
7334
+ this.props.recordMode != 2 &&
7335
+ <Panel header={<span>摄像头设备 - {this.state.envInfo.cameraResult}{this.state.envInfo.cameraResult=='不合格'? <img src={IconFail} />: <img src={IconSuccess} />}</span>}
7336
+ key="3" className={this.state.envInfo.cameraResult=='不合格'? 'panel-error':''}>
7337
+ <div >
7338
+ {
7339
+ this.state.cameraList.map((item, index) => {
7340
+ return <div key={index} className="envClass">
7341
+ {/* <input type="radio" name="camere" value={item.actionid} style={{ float: 'left' }} checked={this.state.cameraValue == item.actionid} readOnly disabled /><i></i> */}
7342
+ {item.actionname}{this.state.cameraValue == item.actionid ? '(当前设备)' : ''}
7343
+ </div>
7344
+ })
7345
+ }
7346
+ {this.state.cameraList.length == 0 ? <p className="envClass">获取不到设备,请检查电脑“设置”中的摄像头权限是否开启,并重启浏览器再试</p> : null}
7347
+ </div>
7348
+ </Panel>
7349
+ }
7350
+ <Panel header={<span>麦克风设备 - {this.state.envInfo.microResult} {this.state.envInfo.microResult=='不合格'? <img src={IconFail} />: <img src={IconSuccess} />}</span>} key="4" className={this.state.envInfo.microResult=='不合格'? 'panel-error':''}>
7351
+ <div>
7352
+ {
7353
+ this.state.microphoneList.map((item, index) => {
7354
+ return <div key={index} className="envClass">
7355
+ {item.actionname}{this.state.microphoneValue == item.actionid ? '(当前设备)' : ''}
7356
+ </div>
7357
+ })
7358
+ }
7359
+ {this.state.cameraList.length == 0 ? <p className="envClass">获取不到设备,请检查电脑“设置”中的麦克风权限是否开启,并重启浏览器再试</p> : null}
7360
+ </div>
7361
+ </Panel>
7362
+ <Panel header={<span>扬声器设备 - {this.state.envInfo.speakerResult} {this.state.envInfo.speakerResult=='不合格'? <img src={IconFail} />: <img src={IconSuccess} />}</span>} key="4" className={this.state.envInfo.speakerResult=='不合格'? 'panel-error':''}>
7363
+ <div>
7364
+ {
7365
+ this.state.speakerList.map((item, index) => {
7366
+ return <div key={index} className="envClass">
7367
+ {item.actionname}{'(当前设备)'}
7368
+ </div>
7369
+ })
7370
+ }
7371
+ {this.state.speakerList.length == 0 ? <p className="envClass">获取不到设备,请检查电脑“设置”中的扬声器权限是否开启,并重启浏览器再试</p> : null}
7372
+ {(this.state.speakerList.length > 0 && this.state.envInfo.speakerResult=='不合格') ? <p className="envClass" style={{marginTop: '3px'}}>未使用外放扬声器,请检查电脑“设置”中的媒体设备,并刷新或重启浏览器再试</p> : null}
7373
+ </div>
7374
+ </Panel>
7375
+ {
7376
+ this.props.recordMode == 2 &&
7377
+ <Panel header={<span>双录iPad设备 - {this.state.ipadTag? '合格':'未开启'} {this.state.ipadTag? <img src={IconSuccess} />: <img src={IconFail} />}</span>} key="6" className={this.state.ipadTag? '':'panel-error'}>
7378
+ <p className="envClass">{this.state.ipadTag? 'iPad设备已加入':'请使用双录iPAD扫描以下会议二维码或输入会议号,开启双录'}</p>
7379
+ <div className='QRCode flex' style={{display: this.state.ipadTag? 'none':''}}>
7380
+ <QRCode
7381
+ value={JSON.stringify({
7382
+ sessionId: this.state.sessionId,
7383
+ staffId: this.props.tellerAccount,
7384
+ staffName: this.props.staffName
7385
+ })}
7386
+ style={{marginTop: '8px', marginLeft: '20px'}}
7387
+ size={100}
7388
+ fgColor="#000000"
7389
+ />
7390
+ <div className='sessionDiv'><span>会议号码</span><div className='num'>{this.state.sessionId}</div></div>
7391
+ </div>
7392
+ </Panel>
7393
+ }
7394
+ {
7395
+ this.props.recordMode != 2 &&
7396
+ <Panel header={<span>背光、曝光 - {this.state.envInfo.lightResult} {this.state.envInfo.lightResult=='合格'? <img src={IconSuccess} />: <img src={IconFail} />}</span>} key="6" className={this.state.envInfo.lightResult=='合格'? '':'panel-error'}>
7397
+ <p className="envClass">{this.state.envInfo.lightResult=='合格'? '无过度背光、曝光':'过度背光、曝光'}</p>
7398
+ </Panel>
7399
+ }
7400
+ </Collapse>
7401
+ </Modal>
5712
7402
  <video className="mixedvideo" id="mixedvideo" autoPlay muted={true} width="0" height="0"></video>
5713
7403
  <video className="mixedvideo" id="manedvideo" autoPlay width="0" height="0"></video>
5714
7404
  <video className="mixedvideo" id="video30" autoPlay width="0" height="0"></video>
5715
7405
 
7406
+ <video className="mixedvideo" id="recordvideo" autoPlay width="0" height="0"></video>
7407
+ <video className="mixedvideo" id="record_video" muted autoPlay></video>
7408
+ <video className="mixedvideo" id="publish_video_record_device" muted autoPlay></video>
5716
7409
 
5717
7410
  </Spin>
5718
7411
  </div>);
@@ -5728,7 +7421,10 @@ Video.defaultProps = {
5728
7421
  callbackUrl: 'http://182.92.184.31:8720/hsbc/callback',
5729
7422
  // roomServerUrl: 'wss://app.uat.dsp.hsbcfts.com.cn/mpaas/mrtc/ws',
5730
7423
  roomServerUrl: 'wss://mrtc.mpaas.cn-hangzhou.aliyuncs.com/ws',
5731
-
7424
+ // asr公有云默认参数
7425
+ // asrServerUrl: 'wss://nls-gateway.cn-shanghai.aliyuncs.com/ws/v1',
7426
+ // asrAppKey: 'E6DAPlpMun5L2dJ7',
7427
+ // asrToken: 'a07198021d434d1288cd4ab3178712cb',
5732
7428
  resourcePath: 'https://counter-web.leimondata.cn:7199',
5733
7429
  // resourcePath: 'https://zuul.uat.dsp.hsbcfts.com.cn/wealth/js/',
5734
7430
  prohbiitPrompt: '当前无客户',
@@ -5738,18 +7434,36 @@ Video.defaultProps = {
5738
7434
  microphoneSize: 25,
5739
7435
  fontSize: '14',
5740
7436
  fontFamily: 'auto',
5741
- menus: ['BOARD', 'SHARE', 'FRIES', 'OCR', 'INVITE', 'PIP', 'BEAUTY', 'GRAFFITI', 'BACKGROUND'],
7437
+ menus: ['BOARD', 'SHARE', 'FRIES', 'OCR', 'PAPER_OCR', 'INVITE', 'PIP', 'BEAUTY', 'GRAFFITI', 'BACKGROUND'],
5742
7438
  customLeaveRoom: '客户离开房间',
7439
+ sensitiveWords: ['保本保息', '无风险'],
7440
+ // speakerNames: ['扬声器'], // null或不传,则不强制使用扬声器设备;若传入有效数组,则每项代表允许的设备名称如"xxx Speaker Device",逻辑为包含,不需要全等。
5743
7441
  meetingInfo: {
5744
7442
  title: '--',
5745
7443
  host: '--',
5746
7444
  customers: ['--'],
5747
7445
  otherAttendees: undefined
5748
7446
  },
7447
+ pdfRendering: false,
5749
7448
  isTranscribing: false,
5750
7449
  shareMask: false,
5751
7450
  isOpenSound: false, // true开启进出音效 false不开启
7451
+ isWeakSound: false,
7452
+ whetherDetectFace: false, // 是否在双录时开启人脸检测
7453
+ whetherDetectLight: false, // 是否在双录时开启背光检测
7454
+ whetherNeedAsr: false, // 是否在双录时开启违禁词检测
7455
+ faceDetectInterval: 6, // 人脸检测间隔(秒)
7456
+ lightDetectInterval: 6, // 背光检测间隔(秒)
7457
+ lightSensitivity: 1, // 光线敏感度系数,默认1
5752
7458
  userSide: 2,
7459
+ meetingDuration: null, // 会议时长,单位小时
7460
+ recordMode: 1, // 录制模式 1远程录制 2网点录制
7461
+ defaultBranchCode: "",// 员工网点缩写
7462
+ customerId: "", //客户号
7463
+ customerType: "", // 客户类型
7464
+ salesBranchCode: "", //网点编号(分行号)
7465
+ financialOffice: "", // 理财室
7466
+ staffName: '', // 坐席名称
5753
7467
  logUrl: 'http://hsbc.cn-shanghai.log.aliyuncs.com/logstores/hsbc/track?APIVersion=0.6.0&app=meeting-ui',
5754
7468
  internalUrl: 'https://wp-staff-gateway.wealth-platform.uat.ali.cloud.cn.hsbc/meeting-ui/OHB/CN/HSBC?chnlID=OHB&locale=zh_CN&chnlCC=CN&chnlGMC=HSBC&targetFunc=supervisorMeeting&sourceFunc=rmMeeting'
5755
7469
  }