react_hsbc_teller 2.0.3 → 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 +2351 -730
  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,30 +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
59
94
  let streamRecord
60
95
  let videoName
96
+ let lastFaceNum = 1
61
97
  let muteJson = new Map()
62
- let dateTime = 0
98
+ // let dateTime = 0
63
99
  let messageValue = ''
100
+ let messageValueMap = new Map()
101
+ let videoMessageMap = new Map() // 画中画消息数据
102
+ let third_id_Map = new Map()
64
103
  // let beautyType = false
65
104
  // let beautyNum = 0 // 0-关闭 1--弱 2--中 5---高
66
105
  let rateList = []
@@ -70,6 +109,8 @@ let isSuccuseHs = false
70
109
  let isGraffiti = false
71
110
  let strokeColor = '#333'
72
111
  let clearTime
112
+ let beautyMode = 'none'
113
+ let hsMode = 'none'
73
114
  let CanvasHome = styled.div`
74
115
  position: fixed;
75
116
  z-index: ${props => props.zIndexNum};
@@ -103,6 +144,7 @@ function clearStreamRemain() {
103
144
  beautyDiv.beauty_canvas = null;
104
145
  }
105
146
  if (!(beautyDiv.beauty_player == null || beautyDiv.beauty_player == undefined)) {
147
+ console.log('beautyDiv destroy')
106
148
  beautyDiv.beauty_player.destroy();
107
149
  beautyDiv.beauty_player = null;
108
150
  }
@@ -115,7 +157,7 @@ function clearStreamRemain() {
115
157
  };
116
158
  async function startBeauty(stream) {
117
159
  await beautyInit();
118
- beautyStart(stream, "none");
160
+ beautyStart(stream, beautyMode);
119
161
  }
120
162
  async function startMix(stream, onState) {
121
163
  var drawCanvas = document.getElementById('canvas');
@@ -131,21 +173,25 @@ async function startHs(stream) {
131
173
 
132
174
  await hsInit();
133
175
 
134
- hsStart(stream, 'none');
176
+ hsStart(stream, hsMode);
135
177
 
136
178
  }
137
179
 
138
180
  async function stopHs() {
139
- var stop_stream = true;//控制是否内部来进行关闭流
140
- var stream = hsStop(stop_stream);
141
- if (stream != null && stream != undefined) {
142
- stream.getTracks().forEach((track) => {
143
- track.stop();
144
- });
145
- 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)
146
194
  }
147
- isSuccuseHs = false
148
-
149
195
  }
150
196
  async function mixStopClick() {
151
197
  var stop_stream = true;//控制是否内部来进行关闭流
@@ -170,6 +216,7 @@ class Video extends Component {
170
216
  }
171
217
  cancel = axios.CancelToken.source()
172
218
  state = {
219
+ ablePlayNetweakAudio: true,
173
220
  beautyType: false,
174
221
  beautyName: '开启美颜',
175
222
  signNoClick: false,
@@ -202,6 +249,8 @@ class Video extends Component {
202
249
  isModalVisibleFacial: false,
203
250
  isModalVisibleEnd: false,
204
251
  isModalVisible: false,
252
+ isPictureConfirmModalVisible:false,
253
+ isDisconnectModalVisible: false,
205
254
  screenName: '共享模式',
206
255
  suspendName: '暂停',
207
256
  cameraImg: cameraImgOpen,
@@ -241,14 +290,14 @@ class Video extends Component {
241
290
  microphoneList: [],
242
291
  speakerList: [],
243
292
  isModalVisibleInspection: false,
293
+ envInfo: {},
294
+ isModalVisibleEnvironment: false,
244
295
  cameraValue: '',
245
296
  microphoneValue: '',
246
297
  imStatus: false,
247
- imJoinRoom: false,
248
298
  analyserData: new Map(),
249
299
  analyserHeight: new Map(),
250
300
  OnVolumeAnalyserMap: new Map(),
251
- manualClose: false,
252
301
  defaultValue: '1',
253
302
  customOcrSid: '',
254
303
  shareMaskState: false,
@@ -289,6 +338,8 @@ class Video extends Component {
289
338
  cardFailReason: '',
290
339
  videoType: '',
291
340
  certificateValidityType: true,
341
+ drawCanvasInterval: null,
342
+ faceDetectionTimer: null, // 人脸检测定时器
292
343
  };
293
344
  // eslint-disable-next-line no-undef
294
345
  test_controller = '';
@@ -296,7 +347,7 @@ class Video extends Component {
296
347
  saveLog = (val) => {
297
348
  axios({
298
349
  method: 'get',
299
- baseURL: this.props.logUrl + '&message=' + encodeURIComponent(val) + '&react_hsbc_teller=2.0.3&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,
300
351
 
301
352
  }).then(res => {
302
353
 
@@ -316,8 +367,16 @@ class Video extends Component {
316
367
  try {
317
368
  let result = await API.createRoom({
318
369
  staffId: this.props.tellerAccount,
370
+ staffName: this.props.staffName,
319
371
  activityId: this.props.businessNumber,
320
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,
321
380
  roomId: this.state.channelId,
322
381
  mtoken: this.state.rtoken,
323
382
  type: 2
@@ -325,33 +384,31 @@ class Video extends Component {
325
384
  console.log(result);
326
385
  this.state.imRoomId = result.imRoomId,
327
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()
328
411
 
329
- this.state.cameraList.forEach((el, i) => {
330
- let publish_config = {}
331
- publish_config.media_type = i==0? 1:3
332
- publish_config.publish_device = 1
333
- publish_config.videoSource = el.actionid
334
- publish_config.audioSource = this.state.microphoneValue
335
- publish_config.need_volume_analyser = true
336
- // publish_config.video_profile_type = 3
337
- publish_config.video_profile_type = 100
338
- publish_config.video_profile_diy = { width: 640, height: 360, frameRate: 15, bitrate: 400 }
339
- publish_config.publish_video_id = 'publish_video' + (i+1)
340
- publish_config.publish_streamId_id = 'publish_streamId' + (i+1)
341
- publish_config.publish_tag = 'tag' + (i+1)
342
- this.test_controller.Publish(publish_config)
343
- })
344
- this.publishAllScreen();
345
-
346
- // eslint-disable-next-line no-undef
347
- setTimeout(() => {
348
- if (this.state.imStatus && !this.state.imJoinRoom) {
349
- joinRoom((this.props.tellerAccount + '@' + JSON.parse(window.sessionStorage.getItem('sigData')).hostname), this.state.imRoomId)
350
- this.state.imJoinRoom = true
351
- this.saveLog('Join im room')
352
- console.log('加入IM房间')
353
- }
354
- })
355
412
  this.props.createRoomCallback({
356
413
  type: 1,
357
414
  errorManage: '',
@@ -440,9 +497,16 @@ class Video extends Component {
440
497
  // let result = await API.mpaasSig({account: data.account, type: data.type});
441
498
  console.log('mpaasSig', result, result.mpsSig);
442
499
  window.sessionStorage.setItem('alimpassSig', result.mpsSig);
443
- this.state.workSpaceId = result.workspaceId,
444
- this.state.appId = result.appId,
500
+ this.state.workSpaceId = result.workspaceId
501
+ this.state.appId = result.appId
445
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
+
446
510
  window.sessionStorage.setItem('sigData', JSON.stringify(result));
447
511
  if (data.sigType == 1) {
448
512
  this.handleEdit()
@@ -461,11 +525,6 @@ class Video extends Component {
461
525
  handleEdit = () => {
462
526
  console.log(JSON.parse(window.sessionStorage.getItem('sigData')));
463
527
  // eslint-disable-next-line no-undef
464
- // initWebSocket('wss://im.uat.dsp.hsbcfts.com.cn:443/wealth/im/ws/')
465
- if (!this.state.imStatus) {
466
- this.state.manualClose = false
467
- initWebSocket('wss://' + JSON.parse(window.sessionStorage.getItem('sigData')).hostname + ':' + JSON.parse(window.sessionStorage.getItem('sigData')).webPort + '/ws/');
468
- }
469
528
  const config_param = {};
470
529
  config_param.workspaceId = this.state.workSpaceId;
471
530
  config_param.uid = this.props.tellerAccount;
@@ -474,7 +533,7 @@ class Video extends Component {
474
533
  config_param.sign = window.sessionStorage.getItem('alimpassSig')
475
534
  config_param.room_server_url = this.props.roomServerUrl;
476
535
  // 允许最大断网时间 (超过未重连, 直接关闭)
477
- config_param.network_check_timeout = 10000;
536
+ config_param.network_check_timeout = 1200000; // sdk默认120秒。wpb要求一直重连,设定20分钟
478
537
  this.test_controller.Connect(config_param)
479
538
  this.saveLog('mrtc connect start')
480
539
  };
@@ -493,57 +552,56 @@ class Video extends Component {
493
552
  publish_streamId_id: 'publish_streamId1',
494
553
  publish_tag: 'tag1'
495
554
  },
496
- {
497
- publish_video_id: 'publish_video2',
498
- publish_streamId_id: 'publish_streamId2',
499
- publish_tag: 'tag2'
500
- },
501
- {
502
- publish_video_id: 'publish_video3',
503
- publish_streamId_id: 'publish_streamId3',
504
- publish_tag: 'tag3'
505
- }
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
+ // }
506
565
  ];
507
566
  config_param.initSubscribe = [
508
567
  {
509
568
  subscribe_video_id: 'video1',
510
569
  subscribe_audio_id: 'audio1',
511
- subscribe_streamId_id: 'subscribe_streamId1',
512
570
  feedId_id: 'feedId1'
513
571
  },
514
572
  {
515
573
  subscribe_video_id: 'video2',
516
574
  subscribe_audio_id: 'audio2',
517
- subscribe_streamId_id: 'subscribe_streamId2',
518
575
  feedId_id: 'feedId2'
519
576
  },
520
577
  {
521
578
  subscribe_video_id: 'video3',
522
579
  subscribe_audio_id: 'audio3',
523
- subscribe_streamId_id: 'subscribe_streamId3',
524
580
  feedId_id: 'feedId3'
525
581
  },
526
582
  {
527
583
  subscribe_video_id: 'video4',
528
584
  subscribe_audio_id: 'audio4',
529
- subscribe_streamId_id: 'subscribe_streamId4',
530
585
  feedId_id: 'feedId4'
531
586
  },
532
587
  {
533
588
  subscribe_video_id: 'video5',
534
589
  subscribe_audio_id: 'audio5',
535
- subscribe_streamId_id: 'subscribe_streamId5',
536
590
  feedId_id: 'feedId5'
537
591
  },
538
592
  {
539
593
  subscribe_video_id: 'video6',
540
594
  subscribe_audio_id: 'audio6',
541
- subscribe_streamId_id: 'subscribe_streamId6',
542
595
  feedId_id: 'feedId6'
543
596
  }
544
597
  ];
545
598
  this.test_controller.InitRoomConfig(config_param)
546
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)
547
605
  };
548
606
  rateAll = async () => {
549
607
  let data = ''
@@ -560,17 +618,18 @@ class Video extends Component {
560
618
  }
561
619
  }
562
620
  // 开启录制
563
- enableServerRecording = () => {
621
+ enableServerRecording = (record_business_id) => {
564
622
  const that = this
623
+ const SCALE = 1.5
565
624
  this.rateAll().then((res) => {
566
- console.log('退出房间者', res)
625
+ console.log('开启录制', res)
567
626
  let list = [
568
627
  {
569
628
  tag: 'projectionWhiteboard',
570
629
  xPosition: 0,
571
- yPosition: 175,
572
- width: 960,
573
- height: 540
630
+ yPosition: 175 * SCALE,
631
+ width: 1280,
632
+ height: 720
574
633
  },
575
634
  // {
576
635
  // tag: 'VIDEO_SOURCE_SCREEN_ONE',
@@ -590,75 +649,75 @@ class Video extends Component {
590
649
  tag: 'tag1',
591
650
  xPosition: 0,
592
651
  yPosition: 0,
593
- width: 213,
594
- height: 175
652
+ width: 213 * SCALE,
653
+ height: 175 * SCALE
595
654
  },
596
655
  {
597
- tag: 'tag2',
598
- xPosition: 213,
656
+ tag: 'customer1',
657
+ xPosition: 213 * SCALE,
599
658
  yPosition: 0,
600
- width: 213,
601
- height: 175
659
+ width: 213 * SCALE,
660
+ height: 175 * SCALE
602
661
  },
603
662
  {
604
- tag: 'tag3',
605
- xPosition: 426,
663
+ tag: 'customer2',
664
+ xPosition: 426 * SCALE,
606
665
  yPosition: 0,
607
- width: 213,
608
- height: 175
666
+ width: 213 * SCALE,
667
+ height: 175 * SCALE
609
668
  },
610
669
  {
611
- tag: 'customer1',
612
- xPosition: 639,
670
+ tag: 'customer3',
671
+ xPosition: 639 * SCALE,
613
672
  yPosition: 0,
614
- width: 213,
615
- height: 175
673
+ width: 213 * SCALE,
674
+ height: 175 * SCALE
616
675
  },
617
676
  {
618
- tag: 'customer2',
619
- xPosition: 852,
677
+ tag: 'customer4',
678
+ xPosition: 852 * SCALE,
620
679
  yPosition: 0,
621
- width: 213,
622
- height: 175
680
+ width: 213 * SCALE,
681
+ height: 175 * SCALE
623
682
  },
624
683
  {
625
- tag: 'customer3',
626
- xPosition: 1065,
684
+ tag: 'customer5',
685
+ xPosition: 1065 * SCALE,
627
686
  yPosition: 0,
628
- width: 213,
629
- height: 175
687
+ width: 213 * SCALE,
688
+ height: 175 * SCALE
630
689
  },
631
690
  {
632
- tag: 'customer4',
633
- xPosition: 1278,
691
+ tag: 'customer6',
692
+ xPosition: 1278 * SCALE,
634
693
  yPosition: 0,
635
- width: 213,
636
- height: 175
694
+ width: 213 * SCALE,
695
+ height: 175 * SCALE
637
696
  },
638
- {
639
- tag: 'RM_ALL_SCREEN',
640
- xPosition: 960,
641
- yPosition: 180,
642
- width: 320,
643
- height: 180
644
- }
697
+ // {
698
+ // tag: 'sharedScreen', // 一期暂时不需要录制
699
+ // xPosition: 960 * SCALE,
700
+ // yPosition: 180 * SCALE,
701
+ // width: 320 * SCALE,
702
+ // height: 180 * SCALE
703
+ // }
645
704
  ]
646
705
  Array.isArray(res) ?
647
706
  res.map((item) => {
648
707
  list.push({
649
708
  tag: item.tag,
650
- xPosition: item.xaxis,
651
- yPosition: item.yaxis,
652
- width: item.width,
653
- height: item.height
709
+ xPosition: (item.xaxis * SCALE),
710
+ yPosition: (item.yaxis * SCALE),
711
+ width: (item.width * SCALE),
712
+ height: (item.height * SCALE)
654
713
  })
655
714
  }) :
656
715
  list.push({
657
716
  tag: 'VIDEO_SOURCE_SCREEN',
658
- xPosition: 960,
659
- yPosition: 535,
660
- width: 320,
661
- height: 180
717
+ xPosition: 960 * SCALE,
718
+ yPosition: 535 * SCALE,
719
+ width: 320 * SCALE,
720
+ height: 180 * SCALE
662
721
  })
663
722
  // list.push({
664
723
  // tag: 'VIDEO_SOURCE_SCREEN_19_9',
@@ -669,33 +728,98 @@ class Video extends Component {
669
728
  // })
670
729
  const filePath = 'recordId_' + new Date().valueOf();
671
730
  const recordParam = {};
672
- recordParam.width = 1280;
673
- recordParam.height = 720;
731
+ recordParam.width = 1280 * SCALE;
732
+ recordParam.height = 720 * SCALE;
674
733
  recordParam.recordTotalStream = 0;
675
734
  recordParam.startTimeout = 10;
676
735
  recordParam.splitType = 0;
677
736
  recordParam.endType = 1;
678
737
  recordParam.crf = 26
679
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
+ },
680
750
  {
681
751
  tag: '', // 流 tag,如果不设置或为空,则为全局⽔印
682
752
  type: 1, // 1 为时间戳⽔印;2 为⽂字⽔印;3 为图⽚⽔印
683
753
  id: 1, // ⽔印 ID
684
754
  enable: true,
685
- xPosition: 1000, // x 轴位置
686
- yPosition: 10, // y 轴位置
755
+ xPosition: 1080 * SCALE, // x 轴位置
756
+ yPosition: 10 * SCALE, // y 轴位置
687
757
  text: '', // ⽔印⽂字
688
- fontSize: 16, // 字体⼤⼩
758
+ fontSize: 16 * SCALE, // 字体⼤⼩
689
759
  url: '' // ⽔印图⽚ HTTP 地址
690
760
  },
691
761
  ];
692
762
  recordParam.tagPositions = list
693
763
  console.log('recordParam', recordParam);
694
- that.test_controller.StartRemoteRecord(filePath, recordParam, '')
764
+ that.test_controller.StartRemoteRecord(filePath, recordParam, record_business_id)
695
765
 
696
766
  })
697
767
 
698
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
+ };
699
823
  // 结束会话
700
824
  endSession = value => {
701
825
  if (value == 'customerHangUp') {
@@ -707,6 +831,15 @@ class Video extends Component {
707
831
  })
708
832
  }
709
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
+ }
710
843
  errorCodeClick=(type,value)=>{
711
844
  if(type == 'ocr'){
712
845
  if(value == -1007 || value == -100701 || value == -100702 || value == -200001 || value == -300901 || value == -300902 || value == -400001) {
@@ -894,49 +1027,77 @@ class Video extends Component {
894
1027
  this.messageClick('当前暂无客户', 'error')
895
1028
  }
896
1029
  }
897
- messageClick = (value, valueOne) => {
898
- console.log(value, valueOne)
899
- if (messageValue != value) {
900
- messageValue = value
901
- dateTime = new Date().getTime()
902
- 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') {
903
1046
  message.error({
904
1047
  content: value,
905
1048
  icon: <img src={require("../../assets/img/tooltips2_fail.png").default} alt="" ></img>,
906
1049
  className: 'errorClassName',
907
1050
  top: 200,
908
- duration: 10
1051
+ duration: durationSec
909
1052
  })
910
- } else if (valueOne == 'success') {
1053
+ } else if (tipType == 'success') {
911
1054
  message.success({
912
1055
  content: value,
913
1056
  icon: <img src={require("../../assets/img/tooltips1_pass.png").default} alt="" ></img>,
914
1057
  className: 'successClassName',
915
1058
  top: 200,
916
- duration: 10
1059
+ duration: durationSec
917
1060
  })
918
1061
  }
919
- } else if (((new Date().getTime()) - dateTime) / 1000 > 30) {
920
- dateTime = new Date().getTime()
921
- if (valueOne == 'error') {
922
- message.error({
923
- content: value,
924
- icon: <img src={require("../../assets/img/tooltips2_fail.png").default} alt="" ></img>,
925
- className: 'errorClassName',
926
- top: 200,
927
- duration: 10
928
- })
929
- } else if (valueOne == 'success') {
930
- message.success({
931
- content: value,
932
- icon: <img src={require("../../assets/img/tooltips1_pass.png").default} alt="" ></img>,
933
- className: 'successClassName',
934
- top: 200,
935
- duration: 10
936
- })
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()
937
1085
  }
938
1086
  }
939
-
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
+ }
940
1101
  }
941
1102
  // 人脸识别
942
1103
  facialRecognition = () => {
@@ -948,6 +1109,112 @@ class Video extends Component {
948
1109
  this.selectCustomer('facial')
949
1110
  }
950
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
+ }
951
1218
  ocrClick = () => {
952
1219
  if (this.isFileSuccuse()) {
953
1220
  this.state.faceCustomerType = 2
@@ -1003,14 +1270,15 @@ class Video extends Component {
1003
1270
  return a.order - b.order;
1004
1271
  })
1005
1272
  for (let i =1;i<=12;i++){
1006
- if(document.getElementById('video'+i).name){
1273
+ if(sortedlist[i-1].videoName){
1007
1274
  list.push({
1008
- name: 'video' + i,
1009
- title: sortedlist[i-1].videoName,
1010
- mute: sortedlist[i-1].mute,
1011
- noVideo: sortedlist[i-1].noVideo
1012
- })
1013
- }
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
+ }
1014
1282
  }
1015
1283
  console.log(list)
1016
1284
  this.state.listVideoPicture = list
@@ -1042,11 +1310,18 @@ class Video extends Component {
1042
1310
  worker = new Worker(url);
1043
1311
  window.URL.revokeObjectURL(blob);
1044
1312
 
1045
-
1046
1313
  worker.onmessage = () => {
1047
- 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);
1048
1319
  canvas.width = 640;
1049
- 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
+ }
1050
1325
  for (let i = 0; i < this.state.listVideoPicture.length; i++) {
1051
1326
 
1052
1327
  let videoId = this.state.listVideoPicture[i].name;
@@ -1062,15 +1337,15 @@ class Video extends Component {
1062
1337
  }
1063
1338
  if (this.state.listVideoPicture[i].noVideo) {
1064
1339
  cobj.fillStyle = '#333';
1065
- cobj.fillRect((640 - newVideoWidth) / 2, 360 * i, newVideoWidth, newVideoHeight)
1340
+ cobj.fillRect((640 - newVideoWidth) / 2, 360 * i + baseStartHeight, newVideoWidth, newVideoHeight)
1066
1341
  } else {
1067
- cobj.drawImage(videoDiv, (640 - newVideoWidth) / 2, 360 * i, 640, 360);
1342
+ cobj.drawImage(videoDiv, (640 - newVideoWidth) / 2, 360 * i + baseStartHeight, 640, 360);
1068
1343
 
1069
1344
  }
1070
1345
  cobj.beginPath();
1071
1346
  cobj.strokeStyle = this.props.titleColor;
1072
1347
  cobj.fillStyle = this.props.titleBackground;
1073
- cobj.fillRect(0, 360 * (i + 1) - 60, 300, 60)
1348
+ cobj.fillRect(0, 360 * (i + 1) - 60 + baseStartHeight, 300, 60)
1074
1349
  cobj.fill();
1075
1350
  cobj.stroke();
1076
1351
  cobj.beginPath();
@@ -1088,12 +1363,12 @@ class Video extends Component {
1088
1363
  break;
1089
1364
  }
1090
1365
  }
1091
- cobj.strokeText(str, 70, 360 * (i + 1) - 20);
1366
+ cobj.strokeText(str, 70, 360 * (i + 1) - 20 + baseStartHeight);
1092
1367
  cobj.stroke();
1093
1368
  //左边框
1094
1369
  cobj.beginPath();
1095
- cobj.moveTo(0, 0);
1096
- cobj.lineTo(0, 360 * this.state.listVideoPicture.length);
1370
+ cobj.moveTo(0, 0 + baseStartHeight);
1371
+ cobj.lineTo(0, 360 * this.state.listVideoPicture.length + baseStartHeight);
1097
1372
  cobj.closePath(); //闭合路径
1098
1373
  cobj.lineWidth = 5; //线的边框为10像素
1099
1374
  cobj.strokeStyle = '#d9363e';
@@ -1101,8 +1376,8 @@ class Video extends Component {
1101
1376
 
1102
1377
  //下边框
1103
1378
  cobj.beginPath();
1104
- cobj.moveTo(0, 0);
1105
- cobj.lineTo(640, 0);
1379
+ cobj.moveTo(0, 0 + baseStartHeight);
1380
+ cobj.lineTo(640, 0 + baseStartHeight);
1106
1381
  cobj.closePath(); //闭合路径
1107
1382
  cobj.lineWidth = 5; //线的边框为10像素
1108
1383
  cobj.strokeStyle = '#d9363e';
@@ -1110,8 +1385,8 @@ class Video extends Component {
1110
1385
 
1111
1386
  //右边框
1112
1387
  cobj.beginPath();
1113
- cobj.moveTo(640, 360 * this.state.listVideoPicture.length);
1114
- cobj.lineTo(640, 0);
1388
+ cobj.moveTo(640, 360 * this.state.listVideoPicture.length + baseStartHeight);
1389
+ cobj.lineTo(640, 0 + baseStartHeight);
1115
1390
  cobj.closePath(); //闭合路径
1116
1391
  cobj.lineWidth = 5; //线的边框为10像素
1117
1392
  cobj.strokeStyle = '#d9363e';
@@ -1120,8 +1395,8 @@ class Video extends Component {
1120
1395
 
1121
1396
  //上边框
1122
1397
  cobj.beginPath();
1123
- cobj.moveTo(0, 360 * this.state.listVideoPicture.length);
1124
- 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);
1125
1400
  cobj.closePath(); //闭合路径
1126
1401
  cobj.lineWidth = 5; //线的边框为10像素
1127
1402
  cobj.strokeStyle = '#d9363e';
@@ -1131,10 +1406,11 @@ class Video extends Component {
1131
1406
  let microphoneSize = 50
1132
1407
  var img = document.getElementById("icon_huatong");
1133
1408
  var img1 = document.getElementById("icon_huatong_close");
1409
+ if (!this.state.listVideoPicture[i].title.includes(IPAD_SUFFIX)) {
1134
1410
  if (this.state.listVideoPicture[i].mute) {
1135
- cobj.drawImage(img1, 10, 360 * (i + 1) - 60, microphoneSize, microphoneSize);
1411
+ cobj.drawImage(img1, 10, 360 * (i + 1) - 60 + baseStartHeight, microphoneSize, microphoneSize);
1136
1412
  } else {
1137
- cobj.drawImage(img, 10, 360 * (i + 1) - 60, microphoneSize, microphoneSize);
1413
+ cobj.drawImage(img, 10, 360 * (i + 1) - 60 + baseStartHeight, microphoneSize, microphoneSize);
1138
1414
 
1139
1415
  // 绘制实时音量
1140
1416
  let sid = document.getElementById(this.state.listVideoPicture[i].name).name
@@ -1151,9 +1427,9 @@ class Video extends Component {
1151
1427
  // 以画布左上角为坐标原点
1152
1428
  let drawArea = {
1153
1429
  x1: 28 / 50 * microphoneSize + 10, // 波动范围右下角的点坐标
1154
- y1: 25 / 50 * microphoneSize + 360 * (i + 1) - 60,
1430
+ y1: 25 / 50 * microphoneSize + 360 * (i + 1) - 60 + baseStartHeight,
1155
1431
  x2: 22 / 50 * microphoneSize + 10, // 波动范围左上角的点坐标
1156
- y2: 10 / 50 * microphoneSize + 360 * (i + 1) - 60,
1432
+ y2: 10 / 50 * microphoneSize + 360 * (i + 1) - 60 + baseStartHeight,
1157
1433
  }
1158
1434
 
1159
1435
 
@@ -1177,12 +1453,74 @@ class Video extends Component {
1177
1453
  // requestAnimationFrame(aou.bind(this, analyser))
1178
1454
  )
1179
1455
  }
1456
+ }
1457
+ }
1180
1458
 
1181
-
1182
-
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
+ }
1183
1474
  }
1184
1475
 
1185
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();
1186
1524
  };
1187
1525
 
1188
1526
  const captureStream = canvas.captureStream();
@@ -1195,17 +1533,37 @@ class Video extends Component {
1195
1533
 
1196
1534
  pictureInPictureVideo.addEventListener('enterpictureinpicture', (event) => {
1197
1535
  //可获取画中画窗口的一些数据,如宽高等
1536
+ console.log('开启画中画')
1198
1537
  pictureInPictureVideo.style.display = 'block';
1199
1538
  pictureInPictureVideo.play();
1200
1539
  this.state.isPictureInPicture = true
1540
+ clearTimeout(this.loopPlayTimer)
1201
1541
  });
1202
1542
 
1203
1543
  pictureInPictureVideo.addEventListener('leavepictureinpicture', (event) => {
1544
+ console.log('关闭画中画')
1204
1545
  pictureInPictureVideo.srcObject = null;
1205
1546
  pictureInPictureVideo.style.display = "none";
1206
1547
  this.state.listVideoPicture = []
1207
1548
  worker.postMessage(false);
1208
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
+ }
1209
1567
  });
1210
1568
 
1211
1569
  }
@@ -1273,9 +1631,8 @@ class Video extends Component {
1273
1631
  })
1274
1632
  }
1275
1633
  }
1276
- mountClick = () => {
1277
- window.IMEvt = msg => {
1278
- console.log(JSON.parse(msg));
1634
+ handleReceiveMsg = (msg) => {
1635
+ console.log(JSON.parse(msg));
1279
1636
  const Mival = JSON.parse(msg);
1280
1637
  if (Mival.typeId == 1210) {
1281
1638
  // 进行初始化操作
@@ -1308,6 +1665,7 @@ class Video extends Component {
1308
1665
  }, ()=>{
1309
1666
  this.pictureInPicture('Refresh')
1310
1667
  })
1668
+ this.messageClick('客户切换其他软件', 'error', Mival.data.userId)
1311
1669
  }
1312
1670
  }
1313
1671
  else if (Mival.typeId == 3003) { // app进入前台
@@ -1324,6 +1682,80 @@ class Video extends Component {
1324
1682
  })
1325
1683
  }
1326
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
+ }
1327
1759
  else if (Mival.typeId == 1220) {
1328
1760
  // 一炒多的图片 1214
1329
1761
  if (Mival.sessionId == this.state.sessionId) {
@@ -1354,6 +1786,9 @@ class Video extends Component {
1354
1786
  if (Mival.type == 1) {
1355
1787
  this.switchExternal()
1356
1788
  this.saveLog('whiteboard start, typeId=1218,')
1789
+ if (typeof this.props.sfpCallback === 'function'){
1790
+ this.props.sfpCallback()
1791
+ }
1357
1792
  } else if (Mival.type == 2) {
1358
1793
  if (streamShare) {
1359
1794
  streamShare.getTracks().forEach(track => track.stop());
@@ -1366,7 +1801,10 @@ class Video extends Component {
1366
1801
  })
1367
1802
  } else {
1368
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')
1369
1806
  this.test_controller.UnPublish(document.getElementById('video20').name)
1807
+ if(this.state.drawCanvasInterval) clearInterval(this.state.drawCanvasInterval)
1370
1808
  }
1371
1809
  this.setState({
1372
1810
  isWhiteboard: false
@@ -1377,6 +1815,13 @@ class Video extends Component {
1377
1815
 
1378
1816
  }
1379
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
+ }
1380
1825
  } else if (Mival.typeId == 3100) {
1381
1826
  if(Mival.data.sessionId == this.state.sessionId) {
1382
1827
  muteJson.set(Mival.data.userId, JSON.stringify(Mival))
@@ -1397,6 +1842,27 @@ class Video extends Component {
1397
1842
 
1398
1843
  }
1399
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
+ })
1400
1866
  }
1401
1867
  } else if (Mival.typeId == 121305) {
1402
1868
  if (Mival.sessionId == this.state.sessionId) {
@@ -1432,33 +1898,25 @@ class Video extends Component {
1432
1898
  });
1433
1899
  let sid = document.getElementById('publish_video1').name || document.getElementById('publish_streamId1').name;
1434
1900
  this.test_controller.SetLocalAudioEnable(0, parseInt(sid, 10));
1435
- callNimIM('sendCustomCmdMsg', {
1436
- customId: this.state.imRoomId,
1437
- content: JSON.stringify({
1901
+ this.sendMessage({
1438
1902
  'typeId': 1013,
1439
1903
  'muteStatus': 1,
1440
1904
  'data': {
1441
1905
  'sessionId': this.state.sessionId,
1442
1906
  'userId': this.props.tellerAccount
1443
1907
  }
1444
- })
1445
- }, function (code, message, data) {
1446
- // console.log(data)
1447
1908
  })
1448
1909
  }
1449
1910
  document.getElementById('audio1').muted = true
1450
1911
  console.log('音频流静音')
1451
1912
  console.log(document.getElementById('audio1').muted)
1452
1913
  setTimeout(() => {
1453
- callNimIM('sendCustomCmdMsg', {
1454
- customId: this.state.imRoomId,
1455
- content: JSON.stringify({
1456
- 'typeId': 1223,
1457
- 'state': 1, // app解除静音
1458
- 'sessionId': this.state.sessionId,
1459
- 'userId': Mival.data.userId //this.seeList(this.state.roomCustomerList, 'feedId', document.getElementById('feedId1').innerText).uid
1460
- })
1461
- });
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
+ })
1462
1920
  }, 1000);
1463
1921
  }
1464
1922
  } else if (Mival.typeId == 1401) {
@@ -1472,37 +1930,194 @@ class Video extends Component {
1472
1930
  this.setState({
1473
1931
  videoList: this.state.videoList
1474
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();
1475
1991
  }
1992
+ } else if (Mival.typeId == 2002 && this.state.sessionId == Mival.sessionId) {
1993
+ // 会议到时间
1994
+ console.log('会议超过时间限制')
1995
+ this.endSessionValue();
1476
1996
  }
1477
- };
1478
- window.IMOpenfire = msg => {
1479
- console.log('im登录', msg)
1480
- if (msg.status == 'error') {
1481
- this.state.imStatus = false
1482
- this.saveLog('Im connection establishment failed')
1483
- this.roomCallBack(2, 'im建立连接失败', 5)
1484
- } else if (msg.status == 'success') {
1485
- this.state.imStatus = true
1486
- setTimeout(() => {
1487
- if (this.state.imRoomId && !this.state.imJoinRoom) {
1488
- joinRoom((this.props.tellerAccount + '@' + JSON.parse(window.sessionStorage.getItem('sigData')).hostname), this.state.imRoomId)
1489
- this.state.imJoinRoom = true
1490
- 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) {
1491
2035
  }
1492
- }, 200);
1493
- } else if (msg.status == 'close') {
1494
- if (!this.state.manualClose) {
1495
- this.timer && clearInterval(this.timer);
1496
- this.state.imStatus = false
1497
- console.log('IMOpenfireclose')
1498
- this.saveLog('Repeated login of account')
1499
- this.roomCallBack(2, '账号重复登录', 9)
1500
-
1501
2036
  }
2037
+ }, this.props.faceDetectInterval * 1000);
1502
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 )
1503
2061
  }
2062
+ }, this.props.lightDetectInterval * 1000);
1504
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
+ }
1505
2118
  }
2119
+ }
2120
+ mountClick = () => {
1506
2121
  let data = {
1507
2122
  account: this.props.tellerAccount,
1508
2123
  type: '2',
@@ -1598,21 +2213,34 @@ class Video extends Component {
1598
2213
  }
1599
2214
  }
1600
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))
1601
2218
  this.setState({
1602
- cameraList: objList,
2219
+ cameraList: cameraList,
2220
+ recorderDevice: recorderDevice,
1603
2221
  microphoneList: objList1,
1604
2222
  speakerList: objList2.length > 0 ? [objList2[0]] : []
1605
2223
  })
1606
2224
  let indexId = 0
1607
- objList.map((item, index) => {
1608
- 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) {
2229
+ indexId = index
2230
+ } else if (item.actionname.indexOf('Integrated Camera') != -1) {
1609
2231
  indexId = index
1610
2232
  }
1611
2233
  })
1612
- console.log(indexId)
2234
+ // 麦克风设置默认
2235
+ objList1.forEach((item, index) => {
2236
+ if (item.actionname.indexOf('Microphone Array (Realtek High Definition Audio(SST))') != -1) {
2237
+ microId = index
2238
+ }
2239
+ })
2240
+ console.log(indexId, microId)
1613
2241
  this.setState({
1614
2242
  cameraValue: objList[indexId].actionid,
1615
- microphoneValue: objList1[0].actionid
2243
+ microphoneValue: objList1[microId].actionid
1616
2244
  })
1617
2245
  if (!this.state.appId && !this.state.sessionType) {
1618
2246
  console.log('cameraValue', this.state.cameraValue)
@@ -1632,6 +2260,7 @@ class Video extends Component {
1632
2260
  this.state.sessionType = false
1633
2261
  this.messageClick('获取设备失败,请检查摄像头设备是否可用或是否禁用摄像头', 'error')
1634
2262
  this.roomCallBack(2, '获取设备失败', 1)
2263
+ this.showEnvDetection()
1635
2264
  };
1636
2265
  // 建立连接成功
1637
2266
  this.test_controller.OnConnectOK = () => {
@@ -1680,6 +2309,10 @@ class Video extends Component {
1680
2309
  this.state.rtoken = rtoken
1681
2310
  this.createRoom()
1682
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房间')
1683
2316
  };
1684
2317
  // 创建房间失败
1685
2318
  this.test_controller.OnCreateRoomFailed = (err_code, err_msg) => {
@@ -1700,13 +2333,19 @@ class Video extends Component {
1700
2333
  };
1701
2334
  // 音视频关闭通知
1702
2335
  this.test_controller.OnMediaClose = (code, sid) => {
1703
- console.log(code, sid)
2336
+ console.log('OnMediaClose',code, sid)
1704
2337
  if (code == 5003 || code == 5004 || code == 5005 || code == 5007 || code == 5009 || code == 5010 || code == 5011 || code == 5012) {
1705
- if (sid == document.getElementById('publish_video1').name) {
2338
+ if (sid == this.state.publishSid) {
1706
2339
  this.saveLog('Audio and video close notification,' + code)
1707
2340
  this.roomCallBack(2, '音视频异常关闭', 8)
1708
- } else {
2341
+ } else if (sid == this.state.publishScreenSid) {
1709
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
+ }
1710
2349
  }
1711
2350
  }
1712
2351
  };
@@ -1714,25 +2353,38 @@ class Video extends Component {
1714
2353
  this.test_controller.OnJoinRoomSucc = () => {
1715
2354
  console.log('加入房间成功')
1716
2355
 
1717
- this.state.cameraList.forEach((el, i) => {
1718
- let publish_config = {}
1719
- publish_config.media_type = i==0? 1:3
1720
- publish_config.publish_device = 1
1721
- publish_config.videoSource = el.actionid
1722
- publish_config.audioSource = this.state.microphoneValue
1723
- publish_config.need_volume_analyser = true
1724
- // publish_config.video_profile_type = 3
1725
- publish_config.video_profile_type = 100
1726
- publish_config.video_profile_diy = { width: 640, height: 360, frameRate: 15, bitrate: 400 }
1727
- publish_config.publish_video_id = 'publish_video' + (i+1)
1728
- publish_config.publish_streamId_id = 'publish_streamId' + (i+1)
1729
- publish_config.publish_tag = 'tag' + (i+1)
1730
- this.test_controller.Publish(publish_config)
1731
- })
1732
- this.publishAllScreen();
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()
1733
2378
 
1734
2379
  this.roomCallBack(1, '', 0)
1735
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)
1736
2388
  };
1737
2389
  // 加入房间失败
1738
2390
  this.test_controller.OnJoinRoomFailed = (err_code, err_msg) => {
@@ -1747,12 +2399,9 @@ class Video extends Component {
1747
2399
  this.state.rtoken = '',
1748
2400
  this.state.sessionId = '',
1749
2401
  this.state.imRoomId = ''
1750
- this.state.imJoinRoom = false
1751
2402
  if (this.state.imStatus) {
1752
2403
  console.log('disconnect断开连接')
1753
- this.state.manualClose = true
1754
2404
  this.state.imStatus = false
1755
- disconnect();
1756
2405
  }
1757
2406
  this.test_controller.Disconnect()
1758
2407
  let data = {
@@ -1763,71 +2412,24 @@ class Video extends Component {
1763
2412
  this.mpaasSig(data);
1764
2413
  };
1765
2414
  this.test_controller.OnSendTextMsgSucc = (msgId) => {
1766
- console.log('发送成功', msgId)
1767
- this.setState({
1768
- documentError: '',
1769
- isModalVisibleCustomer: false,
1770
- })
1771
- this.saveLog('mrtc OnSendTextMsgSucc:' + msgId)
2415
+ // console.log('发送成功', msgId)
2416
+ // this.saveLog('mrtc OnSendTextMsgSucc:' + msgId)
1772
2417
  }
1773
2418
  this.test_controller.OnSendTextMsgFailed = (msgId, code, msg) => {
1774
2419
  console.log('发送失败', msgId, code, msg)
1775
- this.setState({
1776
- documentError: '推送授权白板失败,请重试'
1777
- })
2420
+ const Mival = JSON.parse(msg)
2421
+ // 失败处理
2422
+ if (Mival.typeId == '3300') {
2423
+ this.setState({
2424
+ documentError: '推送授权白板失败,请重试'
2425
+ })
2426
+ }
1778
2427
  this.saveLog('mrtc OnSendTextMsgFail:' + msgId +', code=' + code + ',msg=' + msg)
1779
2428
  }
1780
2429
  this.test_controller.OnReceiveTextMsg = (uid, msg) => {
1781
- console.log('收到手机端消息', uid, msg, JSON.parse(msg).typeId, JSON.parse(msg).data.sessionId, this.state.sessionId)
1782
- if (JSON.parse(msg).typeId == 33001 && this.state.sessionId == JSON.parse(msg).data.sessionId) {
1783
- if (JSON.parse(msg).type == 1) {
1784
- this.saveAuthorize(JSON.parse(msg).data.userId)
1785
- this.customerFaceClick(this.state.customerList[this.state.customerSelect - 1])
1786
- }
1787
- }
1788
- // 线下demo静音处理
1789
- if (JSON.parse(msg).typeId == 4004 && this.state.sessionId == JSON.parse(msg).data.sessionId) {
1790
- if (this.isFileSuccuse()) {
1791
- if (!this.state.voiceStatue) {
1792
- // 静音本地
1793
- this.setState({
1794
- voiceStatue: true,
1795
- voiceImg: voiceImgCloe,
1796
- voiceName: '解除静音'
1797
- });
1798
- let sid = document.getElementById('publish_video1').name || document.getElementById('publish_streamId1').name;
1799
- this.test_controller.SetLocalAudioEnable(0, parseInt(sid, 10));
1800
- callNimIM('sendCustomCmdMsg', {
1801
- customId: this.state.imRoomId,
1802
- content: JSON.stringify({
1803
- 'typeId': 1013,
1804
- 'muteStatus': 1,
1805
- 'data': {
1806
- 'sessionId': this.state.sessionId,
1807
- 'userId': this.props.tellerAccount
1808
- }
1809
- })
1810
- }, function (code, message, data) {
1811
- // console.log(data)
1812
- })
1813
- }
1814
- document.getElementById('audio1').muted = true
1815
- console.log('音频流静音')
1816
- console.log(document.getElementById('audio1').muted)
1817
- setTimeout(() => {
1818
- callNimIM('sendCustomCmdMsg', {
1819
- customId: this.state.imRoomId,
1820
- content: JSON.stringify({
1821
- 'typeId': 1223,
1822
- 'state': 1, // app解除静音
1823
- 'sessionId': this.state.sessionId,
1824
- 'userId': uid //this.seeList(this.state.roomCustomerList, 'feedId', document.getElementById('feedId1').innerText).uid
1825
- })
1826
- });
1827
- }, 1000);
1828
- }
1829
- }
1830
- 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)
1831
2433
  }
1832
2434
  this.test_controller.StreamFilterHandler = async (publish_tag, stream, stream_type, publish_device, media_type) => {
1833
2435
  console.log(`stream processed by client, publish_device=${publish_device}, media_type=${media_type}, publish_tag=${publish_tag},stream_type=${stream_type}`);
@@ -1843,28 +2445,13 @@ class Video extends Component {
1843
2445
  if (publish_tag == 'tag1') {
1844
2446
  console.log('tag1', stream)
1845
2447
  let newStream = stream;
1846
- // if (stream.getVideoTracks()[0]) {
1847
- // await startBeauty(newStream);
1848
- // newStream = beautyCaptureStream();
1849
- // // 清理原始流
1850
- // newStream.oninactive = function () {
1851
- // clearOriginStream(stream);
1852
- // };
1853
- // newStream.getVideoTracks()[0].onended = function () {
1854
- // clearOriginStream(stream);
1855
- // };
1856
- // function clearOriginStream(stream) {
1857
- // stream.getTracks().forEach((track) => {
1858
- // track.stop();
1859
- // });
1860
- // stream = null;
1861
- // }
1862
- // };
1863
2448
  if (stream.getVideoTracks()[0]) {
1864
- await startBeauty(newStream);
1865
- newStream = beautyCaptureStream();
1866
- await startHs(newStream);
1867
- newStream = hsCaptureStream();
2449
+ if (this.state.beautyType || isSuccuseHs){
2450
+ await startBeauty(newStream);
2451
+ newStream = beautyCaptureStream();
2452
+ await startHs(newStream);
2453
+ newStream = hsCaptureStream();
2454
+ }
1868
2455
  // 清理原始流
1869
2456
  newStream.oninactive = function () {
1870
2457
  clearOriginStream(stream);
@@ -1885,11 +2472,30 @@ class Video extends Component {
1885
2472
  return newStream
1886
2473
  }
1887
2474
 
1888
- if (publish_tag == 'projectionWhiteboard' && publish_device == 2) {
1889
- // this.graffiti()
1890
- console.log('projectionWhiteboard', stream)
2475
+ if (publish_tag == 'projectionWhiteboard' && (publish_device == 2 || publish_device == 5)) {
1891
2476
  let newStream1 = stream;
1892
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
+ }
1893
2499
  if (this.state.operateShow) {
1894
2500
  await startMix(newStream1, 'mix');
1895
2501
 
@@ -1901,9 +2507,12 @@ class Video extends Component {
1901
2507
  canvas.width = this.state.widthVideo
1902
2508
  } else {
1903
2509
  await startMix(newStream1, 'none');
2510
+ isGraffiti = false
1904
2511
  }
1905
2512
 
1906
2513
  newStream1 = mixCaptureStream();
2514
+ newStream1.getVideoTracks()[0].contentHint = "text"; // 解决清晰度问题
2515
+
1907
2516
  console.log('projectionWhiteboard1', newStream1)
1908
2517
  // 清理原始流
1909
2518
  newStream1.oninactive = function () {
@@ -1919,60 +2528,64 @@ class Video extends Component {
1919
2528
  stream = null;
1920
2529
  }
1921
2530
  }
2531
+ if (stream.getAudioTracks()[0] && newStream1.addTrack) {
2532
+ newStream1.addTrack(stream.getAudioTracks()[0])
2533
+ }
1922
2534
  return newStream1
1923
- } else {
1924
- return stream
1925
2535
  }
1926
-
2536
+ return stream
1927
2537
  }
1928
2538
  // 发布媒体流成功
1929
2539
  this.test_controller.OnPublishSucc = (sid) => {
1930
2540
  console.log('发布媒体流成功', sid)
1931
2541
  this.state.sessionType = true
1932
2542
  if (sid == document.getElementById('video20').name) {
1933
- callNimIM('sendCustomCmdMsg', {
1934
- customId: this.state.imRoomId,
1935
- content: JSON.stringify({
1936
- 'typeId': 2030,
1937
- 'sessionId': this.state.sessionId,
1938
- 'sharedScreen': 1,
1939
- 'tellerId': this.props.tellerAccount
1940
- })
1941
- });
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
+ })
1942
2552
  if (this.state.screenName == '切换共享') {
1943
2553
  this.state.isSharedScreen = true
1944
2554
  this.state.isScreenSwitching = false
1945
2555
  }
2556
+ this.videoInfo = this.generateMediaInfo(document.getElementById("video20").name);
1946
2557
  }
1947
- if (sid == document.getElementById('publish_video1').name) {
1948
-
2558
+ if (sid == document.getElementById('publish_streamId1').name) {
2559
+ this.state.publishSid = document.getElementById('publish_streamId1').name
1949
2560
  this.setState({
1950
2561
 
1951
2562
  loading: false,
1952
2563
  });
2564
+ setTimeout(() => {
2565
+ this.showEnvDetection()
2566
+ }, 1500);
2567
+
1953
2568
 
1954
2569
  this.enterRoom()
1955
2570
  this.updateMeetingInfo()
1956
2571
  this.timer = setInterval(
1957
2572
  () => {
1958
2573
  if (!this.state.voiceStatue && this.state.analyserHeight.get(sid).toFixed(2) > 0.1) {
1959
- callNimIM('sendCustomCmdMsg', {
1960
- customId: this.state.imRoomId,
1961
- content: JSON.stringify({
1962
- 'typeId': 3200,
1963
- 'decibelValue': this.state.analyserHeight.get(sid).toFixed(2),
1964
- "data": {
1965
- 'sessionId': this.state.sessionId,
1966
- 'userId': this.props.tellerAccount,
1967
- 'data': (new Date()).valueOf()
1968
- }
1969
-
1970
- })
1971
- });
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
+ })
1972
2583
  }
1973
2584
  },
1974
2585
  1000
1975
2586
  );
2587
+ this.mediaInfo = this.generateMediaInfo(document.getElementById("publish_streamId1").name);
2588
+
1976
2589
  } else {
1977
2590
  var box = document.getElementById("whiteboardDIV");
1978
2591
  var box1 = document.getElementById("operate")
@@ -1994,11 +2607,13 @@ class Video extends Component {
1994
2607
  this.test_controller.OnPublishFailed = (sid, err_code, err_msg) => {
1995
2608
  this.saveLog('mrtc OnPublishFailed 发布失败, code=' + err_code)
1996
2609
  console.log('Publishing media stream failed,', sid, err_code, err_msg)
1997
- if (sid == document.getElementById('publish_video1').name) {
2610
+ if (sid == document.getElementById('publish_streamId1').name) {
1998
2611
  this.state.sessionType = false
1999
2612
  this.roomCallBack(2, '发布失败', 4)
2000
2613
  } else {
2001
2614
  this.messageClick('投屏失败请重新投屏', 'error')
2615
+ this.setSharedScreenState(false)
2616
+ this.saveLog('Share fail, code=' + err_code)
2002
2617
  }
2003
2618
 
2004
2619
  };
@@ -2047,6 +2662,14 @@ class Video extends Component {
2047
2662
  participants.map((item, index) => {
2048
2663
  if (item.uid != this.state.tellerAccount) {
2049
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
+ }
2050
2673
  let array = this.state.roomCustomerList;
2051
2674
  let newArray = [...array];
2052
2675
  newArray.push({
@@ -2062,8 +2685,6 @@ class Video extends Component {
2062
2685
  config_param = {
2063
2686
  subscribe_video_id: 'video21',
2064
2687
  subscribe_audio_id: 'audio21',
2065
- subscribe_streamId_id: 'subscribe_streamId21',
2066
- feedId_id: 'feedId21',
2067
2688
  feedId: itemOne.feedId
2068
2689
  }
2069
2690
 
@@ -2077,8 +2698,6 @@ class Video extends Component {
2077
2698
  config_param = {
2078
2699
  subscribe_video_id: 'video20',
2079
2700
  subscribe_audio_id: 'audio20',
2080
- subscribe_streamId_id: 'subscribe_streamId20',
2081
- feedId_id: 'feedId20',
2082
2701
  feedId: itemOne.feedId
2083
2702
  }
2084
2703
 
@@ -2094,7 +2713,6 @@ class Video extends Component {
2094
2713
  config_param = {
2095
2714
  subscribe_video_id: 'video'+i,
2096
2715
  subscribe_audio_id: 'audio'+i,
2097
- subscribe_streamId_id: 'subscribe_streamId'+i,
2098
2716
  feedId_id: 'feedId'+i,
2099
2717
  feedId: itemOne.feedId
2100
2718
  }
@@ -2107,6 +2725,7 @@ class Video extends Component {
2107
2725
  console.log(config_param)
2108
2726
  console.log('发起订阅')
2109
2727
  this.test_controller.Subscribe(config_param)
2728
+ document.getElementById(config_param.subscribe_video_id).name = 'temp'
2110
2729
 
2111
2730
  }
2112
2731
  })
@@ -2119,27 +2738,34 @@ class Video extends Component {
2119
2738
  console.log('新加⼊房间者', participant);
2120
2739
  this.saveLog('mrtc someone joined room, userId=' + participant)
2121
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
+ }
2122
2751
  };
2123
2752
  // 推送“有新发布”给与会者
2124
2753
  this.test_controller.OnNewPublish = (feed) => {
2125
2754
  console.log('有新发布者', feed);
2126
2755
  console.log(new Date())
2127
- callNimIM('sendCustomCmdMsg', {
2128
- customId: this.state.imRoomId,
2129
- content: JSON.stringify({
2756
+ if (feed.tag && feed.tag.includes('UnSubscribe_RM')) {
2757
+ console.log('过滤订阅的tag:', feed.tag)
2758
+ return
2759
+ }
2760
+ this.sendMessage({
2130
2761
  'typeId': 1013,
2131
2762
  'muteStatus': this.state.voiceStatue ? 1 : 0,
2132
2763
  'data': {
2133
2764
  'sessionId': this.state.sessionId,
2134
2765
  'userId': this.props.tellerAccount
2135
2766
  }
2136
- })
2137
- }, function (code, message, data) {
2138
- console.log(data)
2139
2767
  })
2140
- callNimIM('sendCustomCmdMsg', {
2141
- customId: this.state.imRoomId,
2142
- content: JSON.stringify({
2768
+ this.sendMessage({
2143
2769
  'typeId': 1014,
2144
2770
  'sessionId': this.state.sessionId,
2145
2771
  'meetingInfo': {
@@ -2148,9 +2774,6 @@ class Video extends Component {
2148
2774
  'customers': this.props.meetingInfo.customers,
2149
2775
  'otherAttendees': this.props.meetingInfo.otherAttendees
2150
2776
  }
2151
-
2152
- })
2153
- }, function (code, message, data) {
2154
2777
  })
2155
2778
  this.sendNotification()
2156
2779
  let array = this.state.roomCustomerList;
@@ -2169,8 +2792,6 @@ class Video extends Component {
2169
2792
  config_param = {
2170
2793
  subscribe_video_id: 'video21',
2171
2794
  subscribe_audio_id: 'audio21',
2172
- subscribe_streamId_id: 'subscribe_streamId21',
2173
- feedId_id: 'feedId21',
2174
2795
  feedId: feed.feedId
2175
2796
  }
2176
2797
 
@@ -2190,8 +2811,6 @@ class Video extends Component {
2190
2811
  config_param = {
2191
2812
  subscribe_video_id: 'video20',
2192
2813
  subscribe_audio_id: 'audio20',
2193
- subscribe_streamId_id: 'subscribe_streamId20',
2194
- feedId_id: 'feedId20',
2195
2814
  feedId: feed.feedId
2196
2815
  }
2197
2816
 
@@ -2213,7 +2832,6 @@ class Video extends Component {
2213
2832
  config_param = {
2214
2833
  subscribe_video_id: 'video'+i,
2215
2834
  subscribe_audio_id: 'audio'+i,
2216
- subscribe_streamId_id: 'subscribe_streamId'+i,
2217
2835
  feedId_id: 'feedId'+i,
2218
2836
  feedId: feed.feedId
2219
2837
  }
@@ -2228,6 +2846,15 @@ class Video extends Component {
2228
2846
  }
2229
2847
 
2230
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
+ }
2231
2858
  };
2232
2859
  // 推送“有新订阅”给与会者
2233
2860
  this.test_controller.OnNewSubscribe = (subscriber, feed) => {
@@ -2235,18 +2862,17 @@ class Video extends Component {
2235
2862
  };
2236
2863
  // 取消发布成功
2237
2864
  this.test_controller.OnUnPublishSucc = (sid) => {
2238
- console.log('取消发布成功', sid, document.getElementById('publish_video1').name)
2239
- if (document.getElementById('publish_video1').name && sid != document.getElementById('publish_video1').name) {
2240
- callNimIM('sendCustomCmdMsg', {
2241
- customId: this.state.imRoomId,
2242
- 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({
2243
2868
  'typeId': 2030,
2244
2869
  'sessionId': this.state.sessionId,
2245
2870
  'sharedScreen': 0,
2246
2871
  'tellerId': this.props.tellerAccount
2247
- })
2248
2872
  })
2249
2873
  this.state.isSharedScreen = false
2874
+ this.setSharedScreenState(false)
2875
+ this.saveLog('Stop share')
2250
2876
  this.setState({
2251
2877
 
2252
2878
  screenName: '共享模式'
@@ -2257,7 +2883,8 @@ class Video extends Component {
2257
2883
  // }
2258
2884
 
2259
2885
  }
2260
- 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!!!')
2261
2888
  clearStreamRemain()
2262
2889
  }
2263
2890
  };
@@ -2331,6 +2958,15 @@ class Video extends Component {
2331
2958
  }
2332
2959
 
2333
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
+ // }
2334
2970
  };
2335
2971
  // 推送“退出房间者”给与会者
2336
2972
  this.test_controller.OnParticipantLeaveRoom = (
@@ -2343,13 +2979,48 @@ class Video extends Component {
2343
2979
  // let audio = new Audio(src)
2344
2980
  // audio.play()
2345
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
+ }
2346
3017
 
2347
3018
 
2348
3019
  this.appGetUsernameClick(participant).then((res) => {
2349
3020
  console.log('退出房间者', res)
2350
3021
  let data = res ? res.username ? res.username : '客户' : '客户'
2351
3022
  console.log(data)
2352
- this.messageClick((data + '已退出会议'), 'error')
3023
+ // this.messageClick((data + '已退出会议'), 'error')
2353
3024
  this.saveLog(data + ' leave room')
2354
3025
  if (res.userType == 1) {
2355
3026
  // 2--坐席  1--客户
@@ -2362,12 +3033,14 @@ class Video extends Component {
2362
3033
  let audio = new Audio(src)
2363
3034
  audio.play()
2364
3035
  }
3036
+ this.messageClick(('客户已退出会议'), 'error')
2365
3037
  } else if (res.userType == 2) {
2366
3038
  if (this.props.isOpenSound) {
2367
3039
  let src = internalLeft
2368
3040
  let audio = new Audio(src)
2369
3041
  audio.play()
2370
3042
  }
3043
+ this.messageClick(('内部人员已退出会议'), 'error')
2371
3044
  }
2372
3045
  // console.log('退出房间者',res)
2373
3046
  // let data = res? res : '客户'
@@ -2379,45 +3052,126 @@ class Video extends Component {
2379
3052
  // 弱网回调
2380
3053
  this.test_controller.OnNetworkWeak = (bpsSend, bpsRecv, sid) => {
2381
3054
  console.log('弱网回调', bpsSend, bpsRecv, sid)
2382
- if (sid == document.getElementById('publish_video1').name) {
2383
- this.messageClick('当前网络环境较差', 'error')
2384
- 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
+
2385
3079
  }
2386
3080
  };
2387
3081
  // 开始服务端录制成功
2388
- this.test_controller.OnStartRemoteRecordSucc = (record_id) => {
2389
- console.log('开始服务端录制成功', record_id);
2390
- this.state.recordId = record_id
2391
- this.videoRecordCallback('1', true)
2392
- 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
+ }
2393
3106
  };
2394
3107
  // 开始服务端录制失败
2395
3108
  this.test_controller.OnStartRemoteRecordFailed = (
2396
3109
  record_id,
2397
3110
  err_code,
2398
- err_msg
3111
+ err_msg,
3112
+ record_third_id
2399
3113
  ) => {
2400
- this.videoRecordCallback('1', false)
2401
- console.log('开始服务端录制失败', record_id, err_code, err_msg)
2402
- 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
+ }
2403
3126
  };
2404
3127
  // 结束服务端录制成功
2405
- this.test_controller.OnStopRemoteRecordSucc = (recordId) => {
2406
- console.log('结束服务端录制成功', recordId);
2407
- this.videoRecordCallback('2', true)
2408
- this.saveLog('mrtc OnStopRemoteRecordSucc, recordId='+recordId)
2409
- // 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
+ }
2410
3149
  // 获取服务端录制结果
2411
3150
  };
2412
3151
  // 结束服务端录制失败
2413
3152
  this.test_controller.OnStopRemoteRecordFailed = (
2414
3153
  recordId,
2415
3154
  err_code,
2416
- err_msg
3155
+ err_msg,
3156
+ record_third_id
2417
3157
  ) => {
2418
- this.videoRecordCallback('2', false)
2419
- console.log('结束服务端录制失败', recordId, err_code, err_msg)
2420
- 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
+
2421
3175
  };
2422
3176
  // 开启浏览器录制成功
2423
3177
  this.test_controller.OnClientStartRecordSuccess = (
@@ -2481,6 +3235,29 @@ class Video extends Component {
2481
3235
  msg
2482
3236
  ) => {
2483
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
+ }
2484
3261
  };
2485
3262
  // 停止浏览器录制成功回调
2486
3263
  this.test_controller.OnClientStopRecordSuccess = (
@@ -2540,6 +3317,23 @@ class Video extends Component {
2540
3317
  ) => {
2541
3318
  console.log('下载失败', clientRecordId, code, msg)
2542
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
+ };
2543
3337
  // 切流成功通知
2544
3338
  this.test_controller.OnChangeMediaStreamSuccess = (sid) => {
2545
3339
  console.log('切流成功通知', sid);
@@ -2553,6 +3347,8 @@ class Video extends Component {
2553
3347
  if (this.state.screenName == '切换共享') {
2554
3348
  this.state.isSharedScreen = true
2555
3349
  this.state.isScreenSwitching = false
3350
+ this.setSharedScreenState(true)
3351
+ this.saveLog('Share changed')
2556
3352
  }
2557
3353
  }
2558
3354
  };
@@ -2570,9 +3366,13 @@ class Video extends Component {
2570
3366
  })
2571
3367
  this.messageClick('切换摄像头或麦克风失败,请先检查设备', 'error')
2572
3368
  } else if (this.state.screenName == '切换共享') {
3369
+ this.saveLog('unPublish share, reason: trigger OnChangeMediaStreamFailed')
3370
+ console.log('unPublish share, reason: trigger OnChangeMediaStreamFailed')
2573
3371
  this.test_controller.UnPublish(document.getElementById('video20').name)
2574
3372
  this.state.isSharedScreen = false
2575
3373
  this.state.isScreenSwitching = false
3374
+ this.setSharedScreenState(false)
3375
+ this.saveLog('Share fail, code=' + code)
2576
3376
  this.setState({
2577
3377
  screenName: '共享模式'
2578
3378
  });
@@ -2683,7 +3483,7 @@ class Video extends Component {
2683
3483
  let startX = x2 // 绘制起始点x
2684
3484
  let startY = y1 - height // 绘制起始点y
2685
3485
  ctx.fillRect(startX, startY, width, height)
2686
- if (document.getElementById('publish_video1').name == sid && i == 39) {
3486
+ if (document.getElementById('publish_streamId1').name == sid && i == 39) {
2687
3487
  this.state.analyserHeight.set(sid, number / 40 / 70)
2688
3488
  this.state.analyserHeight = this.state.analyserHeight
2689
3489
  }
@@ -2700,18 +3500,21 @@ class Video extends Component {
2700
3500
  }
2701
3501
  // 停止共享
2702
3502
  this.test_controller.OnDesktopDisplayClosed = () => {
2703
- console.log('OnDesktopDisplayClosed', this.state.isSharedScreen, this.state.laveRoomSharedScreen)
3503
+ console.log('OnDesktopDisplayClosed', this.state.isSharedScreen, this.state.laveRoomSharedScreen, streamShare)
2704
3504
 
2705
3505
  if (this.state.isScreenSwitching) {
2706
3506
  this.state.isScreenSwitching = false
2707
3507
  } else {
2708
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')
2709
3511
  document.getElementById('video20') && document.getElementById('video20').name ? this.test_controller.UnPublish(document.getElementById('video20').name) : ''
2710
3512
  } else {
2711
3513
  console.log('白板')
2712
3514
  }
2713
3515
  this.state.isSharedScreen = false
2714
3516
  this.state.isScreenSwitching = false
3517
+ this.setSharedScreenState(false)
2715
3518
  this.setState({
2716
3519
  screenName: '共享模式'
2717
3520
  });
@@ -2729,13 +3532,82 @@ class Video extends Component {
2729
3532
 
2730
3533
 
2731
3534
  };
3535
+
3536
+
2732
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
+ })
3560
+ }
3561
+ // 全局录制
2733
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
+ }
3572
+ try {
3573
+ let result = await API.videoRecordCallback({
3574
+ activityId: this.props.businessNumber,
3575
+ sessionId: this.state.sessionId,
3576
+ roomId: this.state.channelId + '',
3577
+ appId: this.state.appId,
3578
+ recordId: this.state.recordId,
3579
+ customerId: this.props.customerId,
3580
+ type: type,
3581
+ status: status
3582
+ });
3583
+ console.log(result);
3584
+ } catch (err) {
3585
+ console.error(err);
3586
+ if (err.status == 502 || err.status == 404) {
3587
+ }
3588
+ }
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
+ }
2734
3602
  try {
2735
3603
  let result = await API.videoRecordCallback({
2736
3604
  activityId: this.props.businessNumber,
2737
3605
  sessionId: this.state.sessionId,
2738
3606
  roomId: this.state.channelId + '',
3607
+ id: businessId,
3608
+ appId: this.state.appId,
3609
+ recordId: this.state.businessRecordId,
3610
+ customerId: this.props.customerId,
2739
3611
  type: type,
2740
3612
  status: status
2741
3613
  });
@@ -2746,6 +3618,42 @@ class Video extends Component {
2746
3618
  }
2747
3619
  }
2748
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
+ }
2749
3657
  // 保存mettingInfo
2750
3658
  updateMeetingInfo = async () => {
2751
3659
  let customers
@@ -2777,10 +3685,9 @@ class Video extends Component {
2777
3685
  type: '2'
2778
3686
  });
2779
3687
  console.log(result);
2780
- this.appGetUsername(document.getElementById('publish_video1').name)
2781
- callNimIM('sendCustomCmdMsg', {
2782
- customId: this.state.imRoomId,
2783
- content: JSON.stringify({
3688
+ this.queryRecordStatus()
3689
+ this.appGetUsername(document.getElementById('publish_streamId1').name)
3690
+ this.sendMessage({
2784
3691
  'typeId': 1014,
2785
3692
  'sessionId': this.state.sessionId,
2786
3693
  'meetingInfo': {
@@ -2789,9 +3696,6 @@ class Video extends Component {
2789
3696
  'customers': this.props.meetingInfo.customers,
2790
3697
  'otherAttendees': this.props.meetingInfo.otherAttendees
2791
3698
  }
2792
-
2793
- })
2794
- }, function (code, message, data) {
2795
3699
  })
2796
3700
  } catch (err) {
2797
3701
  console.error(err);
@@ -2800,10 +3704,15 @@ class Video extends Component {
2800
3704
  }
2801
3705
  }
2802
3706
  }
3707
+ componentDidCatch(error, info) {
3708
+ console.log('componentDidCatch')
3709
+ console.error(error, info)
3710
+ }
3711
+
2803
3712
  componentWillUnmount() {
2804
3713
  this.saveLog('Exit meeting')
2805
3714
  if (this.test_controller && this.state.sessionType) {
2806
- clearStreamRemain()
3715
+ // clearStreamRemain() // 谨慎使用,有页面crash问题
2807
3716
  this.test_controller.LeaveRoom()
2808
3717
  this.test_controller.Disconnect()
2809
3718
  try {
@@ -2811,15 +3720,30 @@ class Video extends Component {
2811
3720
  beautyStop();
2812
3721
  console.log('beautyStop!!')
2813
3722
  } catch (err){
2814
- console.error(err)
3723
+ console.log(err)
2815
3724
  }
2816
3725
  }
2817
- if (this.state.imStatus) {
2818
- console.log('disconnect断开连接')
2819
- this.state.manualClose = true
2820
- disconnect();
3726
+ if (this.state.isAsrStart){
3727
+ this.stopASR()
3728
+ this.asr_controller.Disconnect()
3729
+ }
3730
+ if (this.state.isPictureInPicture) {
3731
+ document.exitPictureInPicture()
2821
3732
  }
3733
+ worker.postMessage(false);
3734
+ worker.terminate();
2822
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
+ }
2823
3747
  }
2824
3748
  finishSession = () => {
2825
3749
  // clearInterval(this.state.OnVolumeAnalyserMap.get(sid))
@@ -2835,6 +3759,7 @@ class Video extends Component {
2835
3759
  screenName: '共享模式',
2836
3760
  })
2837
3761
  this.state.isSharedScreen = false
3762
+ this.setSharedScreenState(false)
2838
3763
  this.state.laveRoomSharedScreen = true
2839
3764
  // this.test_controller.UnPublish(document.getElementById('video20').name)
2840
3765
 
@@ -2848,6 +3773,7 @@ class Video extends Component {
2848
3773
  screenName: '共享模式',
2849
3774
  });
2850
3775
  this.state.isSharedScreen = false
3776
+ this.setSharedScreenState(false)
2851
3777
  this.state.laveRoomSharedScreen = true
2852
3778
  this.props.onLeaveRoom({
2853
3779
  code: LEAVE_TYPE.TELLER_EXIT,
@@ -2876,6 +3802,21 @@ class Video extends Component {
2876
3802
  this.roomCallBack(2, '获取tiken失败', 'SYS-01')
2877
3803
  }
2878
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
+
2879
3820
  getRoomStatus = async data => {
2880
3821
  try {
2881
3822
  let result = await API.getRoomStatus({
@@ -2923,7 +3864,7 @@ class Video extends Component {
2923
3864
  loading: true,
2924
3865
  })
2925
3866
  const that = this
2926
- axios.get(this.props.resourcePath + "/mcu.js")
3867
+ axios.get(this.props.resourcePath + `/mcu.js?v=${SDK_VERISON}`)
2927
3868
  .then(response => this.addToScriptClick()).catch(function (error) {
2928
3869
  console.log(error);
2929
3870
  that.state.sessionType = false
@@ -2937,36 +3878,50 @@ class Video extends Component {
2937
3878
 
2938
3879
  }
2939
3880
  addToScriptClick = () => {
3881
+ let params = `?v=${SDK_VERISON}`
2940
3882
  const _dependScripts = [
2941
- this.props.resourcePath + "/beauty/beauty_frame_pkg.js",
2942
- this.props.resourcePath + "/adapter.js",
2943
- this.props.resourcePath + "/getMediaInfo.js",
2944
- this.props.resourcePath + "/EBML.js",
2945
- this.props.resourcePath + "/mcu.js",
2946
- this.props.resourcePath + "/meeting_desk_stream.js",
2947
- this.props.resourcePath + "/meeting_html_stream.js",
2948
- this.props.resourcePath + "/meeting_file_stream.js",
2949
- this.props.resourcePath + "/meeting_im.js",
2950
- this.props.resourcePath + "/meeting_vod.js",
2951
- this.props.resourcePath + "/meeting_invite.js",
2952
- this.props.resourcePath + "/client_record.js",
2953
- this.props.resourcePath + "/remote_record.js",
2954
- this.props.resourcePath + "/meeting_camera_stream.js",
2955
- this.props.resourcePath + "/meeting_api.js",
2956
-
2957
- this.props.resourcePath + "/eruda.js",
2958
- this.props.resourcePath + "/iconfont.js",
2959
- this.props.resourcePath + "/html2canvas.js",
2960
- this.props.resourcePath + "/dom-to-image.js",
2961
-
2962
- this.props.resourcePath + "/hs/hs_human_segmentation_wrapper.js",
2963
- this.props.resourcePath + "/hs/hs_human_segmentation.js",
2964
- this.props.resourcePath + "/hs/hs_human_segmentation.wasm",
2965
-
2966
- this.props.resourcePath + "/mix/mix_frame.js",
2967
- 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,
2968
3914
 
2969
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
+
2970
3925
  const that = this
2971
3926
  let i = 0
2972
3927
  scriptAdd()
@@ -2981,13 +3936,13 @@ class Video extends Component {
2981
3936
  if (document.all) { //如果是IE
2982
3937
  script.onreadystatechange = () => {
2983
3938
  if (script.readyState == 'loaded' || script.readyState == 'complete') {
2984
- that.test_controller = new McuController();
3939
+ that.test_controller = new MeetingController();
2985
3940
  that.mountClick()
2986
3941
  }
2987
3942
  }
2988
3943
  } else {
2989
3944
  script.onload = () => {
2990
- that.test_controller = new McuController();
3945
+ that.test_controller = new MeetingController();
2991
3946
  that.mountClick()
2992
3947
  }
2993
3948
  }
@@ -3010,7 +3965,7 @@ class Video extends Component {
3010
3965
  }
3011
3966
  }
3012
3967
  componentWillMount() {
3013
- console.log('hsbc_teller_sdk', '2.0.3')
3968
+ console.log('hsbc_teller_sdk', SDK_VERISON)
3014
3969
  let arr = []
3015
3970
  for(let i=1;i<=12;i++){
3016
3971
  arr.push({
@@ -3022,8 +3977,43 @@ class Video extends Component {
3022
3977
  hasOcr: 0,
3023
3978
  })
3024
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
+ }
3025
4001
  this.setState({
3026
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'])
3027
4017
  })
3028
4018
  if (this.props.sessionId) {
3029
4019
  this.getRoomStatus({
@@ -3032,8 +4022,101 @@ class Video extends Component {
3032
4022
  } else {
3033
4023
  this.addToScript()
3034
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
+ }
3035
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
+ }
3036
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
+ }
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
+ }
3037
4120
  voice = () => {
3038
4121
  if (this.isFileSuccuse()) {
3039
4122
  if (!this.state.voiceStatue) {
@@ -3049,20 +4132,15 @@ class Video extends Component {
3049
4132
  sid = document.getElementById('publish_streamId1').name
3050
4133
  }
3051
4134
  this.test_controller.SetLocalAudioEnable(0, parseInt(sid, 10));
3052
- callNimIM('sendCustomCmdMsg', {
3053
- customId: this.state.imRoomId,
3054
- content: JSON.stringify({
4135
+ this.saveVideoPoint('mute', 'RM端静音')
4136
+ this.sendMessage({
3055
4137
  'typeId': 1013,
3056
4138
  'muteStatus': 1,
3057
4139
  'data': {
3058
4140
  'sessionId': this.state.sessionId,
3059
4141
  'userId': this.props.tellerAccount
3060
4142
  }
3061
- })
3062
- }, function (code, message, data) {
3063
- console.log(data)
3064
4143
  })
3065
-
3066
4144
  } else if (this.state.voiceStatue) {
3067
4145
  // 打开本地
3068
4146
  this.setState({
@@ -3076,22 +4154,68 @@ class Video extends Component {
3076
4154
  sid = document.getElementById('publish_streamId1').name
3077
4155
  }
3078
4156
  this.test_controller.SetLocalAudioEnable(1, parseInt(sid, 10));
3079
- callNimIM('sendCustomCmdMsg', {
3080
- customId: this.state.imRoomId,
3081
- content: JSON.stringify({
4157
+ this.saveVideoPoint('mute', 'RM端解除静音')
4158
+ this.sendMessage({
3082
4159
  'typeId': 1013,
3083
4160
  'muteStatus': 0,
3084
4161
  'data': {
3085
4162
  'sessionId': this.state.sessionId,
3086
4163
  'userId': this.props.tellerAccount
3087
4164
  }
3088
- })
3089
- }, function (code, message, data) {
3090
- console.log(data)
3091
4165
  })
3092
4166
  }
4167
+ if (this.state.isPictureInPicture) {
4168
+ setTimeout(() => {
4169
+ this.pictureInPicture('Refresh')
4170
+ }, 0);
4171
+ }
3093
4172
  }
3094
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
+ }
3095
4219
  isFileSuccuse = () => {
3096
4220
  if (!this.state.sessionId || !this.state.sessionType || !this.state.imStatus) {
3097
4221
  this.messageClick('当前程序异常请先退出重开', 'error')
@@ -3114,17 +4238,12 @@ class Video extends Component {
3114
4238
  sid = document.getElementById('publish_streamId1').name
3115
4239
  }
3116
4240
  this.test_controller.SetLocalVideoEnable(0, parseInt(sid, 10));
3117
- callNimIM('sendCustomCmdMsg', {
3118
- customId: this.state.imRoomId,
3119
- content: JSON.stringify({
4241
+ this.sendMessage({
3120
4242
  'typeId': 1012,
3121
4243
  'state': 0,
3122
4244
  'sessionId': this.state.sessionId,
3123
4245
  'userId': this.props.tellerAccount
3124
- })
3125
- }, function (code, message, data) {
3126
- console.log(data)
3127
- })
4246
+ })
3128
4247
  } else if (this.state.audioed) {
3129
4248
  this.state.audioed = false,
3130
4249
  this.setState({
@@ -3136,22 +4255,21 @@ class Video extends Component {
3136
4255
  sid = document.getElementById('publish_streamId1').name
3137
4256
  }
3138
4257
  this.test_controller.SetLocalVideoEnable(1, parseInt(sid, 10));
3139
- callNimIM('sendCustomCmdMsg', {
3140
- customId: this.state.imRoomId,
3141
- content: JSON.stringify({
3142
- 'typeId': 1012,
3143
- 'state': 1,
3144
- 'sessionId': this.state.sessionId,
3145
- 'userId': this.props.tellerAccount
3146
- })
3147
- }, function (code, message, data) {
3148
- console.log(data)
4258
+ this.sendMessage({
4259
+ 'typeId': 1012,
4260
+ 'state': 1,
4261
+ 'sessionId': this.state.sessionId,
4262
+ 'userId': this.props.tellerAccount
3149
4263
  })
3150
4264
  }
3151
4265
  }
3152
4266
  };
3153
4267
  sharedScreen = () => {
3154
4268
  console.log('投屏', this.state.tabTitles.find(el => el.value == 'staffScreen'))
4269
+ if (this.state.shareLock) {
4270
+ console.log('发布共享点击太快了')
4271
+ return;
4272
+ }
3155
4273
  if (this.isFileSuccuse()) {
3156
4274
  if (!this.state.tabTitles.find(el => el.value == 'staffScreen')) {
3157
4275
  const publish_config = {};
@@ -3160,30 +4278,76 @@ class Video extends Component {
3160
4278
  streamShare = ''
3161
4279
  }
3162
4280
  if (this.state.isSharedScreen) {
3163
- 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(() => {
3164
4286
  publish_config.media_type = 1
3165
4287
  publish_config.publish_device = 2
4288
+ publish_config.need_volume_analyser = true
3166
4289
  publish_config.video_profile_type = 1
3167
- // publish_config.video_profile_type=100
3168
- // publish_config.video_profile_diy={width:1280, height:720, frameRate:8, bitrate:1500}
4290
+ publish_config.desktopStreamToCanvas = false
3169
4291
  publish_config.enableDesktopAudio = true
3170
4292
  publish_config.degradationType = 2
3171
- publish_config.desktopStreamToCanvas = false
3172
- publish_config.sid = document.getElementById('video20').name
3173
- this.test_controller.ChangeMediaStream(publish_config)
3174
- 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
3175
4321
  } else {
3176
4322
  if (document.getElementById('video20').name) {
3177
- publish_config.media_type = 1;
3178
- publish_config.publish_device = 2;
3179
- publish_config.video_profile_type = 1
3180
- // publish_config.video_profile_type=100
3181
- // publish_config.video_profile_diy={width:1280, height:720, frameRate:8, bitrate:1500}
3182
- publish_config.enableDesktopAudio = true
3183
- publish_config.desktopStreamToCanvas = false
3184
- publish_config.degradationType = 2
3185
- publish_config.sid = document.getElementById('video20').name;
3186
- 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);
3187
4351
  } else {
3188
4352
  publish_config.media_type = 1
3189
4353
  publish_config.publish_device = 2
@@ -3262,23 +4426,21 @@ class Video extends Component {
3262
4426
  sid = document.getElementById('publish_streamId1').name
3263
4427
  }
3264
4428
  this.test_controller.SetLocalAudioEnable(0, parseInt(sid, 10))
4429
+ this.saveVideoPoint('mute', 'RM端静音')
3265
4430
  } else {
3266
4431
  // 当前是
3267
4432
  this.test_controller.SetLocalAudioEnable(1, parseInt(sid, 10));
4433
+ this.saveVideoPoint('mute', 'RM端解除静音')
3268
4434
  this.setState({
3269
4435
  voiceImg: voiceImgOpen,
3270
4436
  voiceName: '静音'
3271
4437
  })
3272
4438
  }
3273
- callNimIM('sendCustomCmdMsg', {
3274
- customId: this.state.imRoomId,
3275
- content: JSON.stringify({
3276
- 'typeId': 1011,
3277
- 'state': 1,
3278
- 'sessionId': this.state.sessionId,
3279
- 'userId': this.props.tellerAccount
3280
- })
3281
- }, function (code, message, data) {
4439
+ this.sendMessage({
4440
+ 'typeId': 1011,
4441
+ 'state': 1,
4442
+ 'sessionId': this.state.sessionId,
4443
+ 'userId': this.props.tellerAccount
3282
4444
  })
3283
4445
  } else {
3284
4446
  this.setState({
@@ -3287,41 +4449,93 @@ class Video extends Component {
3287
4449
  }
3288
4450
 
3289
4451
  };
3290
- handleOk = () => {
3291
- // 代表此时按钮是暂停会话,把isSuspend改成true变成恢复会话
3292
- callNimIM('sendCustomCmdMsg', {
3293
- customId: this.state.imRoomId,
3294
- content: JSON.stringify({
3295
- 'typeId': 1012,
3296
- 'state': 1,
3297
- 'sessionId': this.state.sessionId,
3298
- 'userId': this.props.tellerAccount
4452
+ // 打开抄录/签署面板
4453
+ showModal=(moduleName)=>{
4454
+ if (!this.state.multiModuleShow) {
4455
+ this.setState({
4456
+ multiModuleShow:true,
4457
+ multiModule: moduleName,
4458
+ },()=>{
3299
4459
  })
3300
- }, function (code, message, data) {
3301
- console.log(data)
3302
- });
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
+ }
4514
+ handleOk = () => {
4515
+ // 代表此时按钮是暂停会话,把isSuspend改成true变成恢复会话
4516
+ this.sendMessage({
4517
+ 'typeId': 1012,
4518
+ 'state': 1,
4519
+ 'sessionId': this.state.sessionId,
4520
+ 'userId': this.props.tellerAccount
4521
+ })
3303
4522
  this.setState({
3304
4523
  isSuspend: true,
3305
4524
  suspendName: '恢复'
3306
4525
  });
3307
- callNimIM('sendCustomCmdMsg', {
3308
- customId: this.state.imRoomId,
3309
- content: JSON.stringify({
3310
- 'typeId': 1011,
3311
- 'state': 0,
3312
- 'sessionId': this.state.sessionId,
3313
- 'userId': this.props.tellerAccount
3314
- })
3315
- }, function (code, message, data) {
3316
- console.log(data)
3317
- });
4526
+ this.sendMessage({
4527
+ 'typeId': 1011,
4528
+ 'state': 0,
4529
+ 'sessionId': this.state.sessionId,
4530
+ 'userId': this.props.tellerAccount
4531
+ })
3318
4532
  let sid = document.getElementById('publish_video1').name;
3319
4533
  if (!sid) {
3320
4534
  // 纯音频的时候sid在publish_streamId标签中
3321
4535
  sid = document.getElementById('publish_streamId1').name
3322
4536
  }
3323
4537
  this.test_controller.SetLocalAudioEnable(0, parseInt(sid, 10));
3324
- this.test_controller.SetLocalVideoEnable(0, parseInt(sid, 10));
4538
+ this.saveVideoPoint('mute', 'RM端静音')
3325
4539
  this.setState({
3326
4540
  isModalVisible: false
3327
4541
  })
@@ -3501,6 +4715,9 @@ class Video extends Component {
3501
4715
  // videoList: this.state.videoList
3502
4716
  // })
3503
4717
  this.videoListSort();
4718
+ if (this.state.isPictureInPicture) {
4719
+ this.pictureInPicture('Refresh')
4720
+ }
3504
4721
  } else {
3505
4722
  console.log('1')
3506
4723
  this.messageClick('保持信息失败', 'error')
@@ -3525,15 +4742,12 @@ class Video extends Component {
3525
4742
  console.log('ocrCallback', result.data,val)
3526
4743
  // this.messageClick('姓名:' + result.data.idCardName + ',身份证号:' + result.data.idCardNumber,'success')
3527
4744
  // this.messageClick('识别成功','success')
3528
- callNimIM('sendCustomCmdMsg', {
3529
- customId: this.state.imRoomId,
3530
- content: JSON.stringify({
3531
- 'typeId': 1020,
3532
- 'sessionId': this.state.sessionId,
3533
- 'cameraState': 1,
3534
- "userId": this.state.faceCustomerUid
3535
- })
3536
- });
4745
+ this.sendMessage({
4746
+ 'typeId': 1020,
4747
+ 'sessionId': this.state.sessionId,
4748
+ 'cameraState': 1,
4749
+ "userId": this.state.faceCustomerUid
4750
+ })
3537
4751
  if(this.state.documentType == 'ID_CARD') {
3538
4752
  if (result.data.side == 'front' && val == 1) {
3539
4753
  if(this.state.certificateValidity) {
@@ -3693,6 +4907,7 @@ class Video extends Component {
3693
4907
  })
3694
4908
  // this.messageClick('识别失败', 'error')
3695
4909
  this.errorCodeClick('ocr',result.code)
4910
+ this.saveLog('OCR failed, error code=' + result.code)
3696
4911
  }
3697
4912
  } catch (err) {
3698
4913
  this.setState({
@@ -3791,6 +5006,9 @@ class Video extends Component {
3791
5006
  // videoList: this.state.videoList
3792
5007
  // })
3793
5008
  this.videoListSort();
5009
+ if (this.state.isPictureInPicture) {
5010
+ this.pictureInPicture('Refresh')
5011
+ }
3794
5012
  } else {
3795
5013
  console.log('1')
3796
5014
  this.messageClick('保持信息失败', 'error')
@@ -3801,15 +5019,12 @@ class Video extends Component {
3801
5019
  }
3802
5020
  };
3803
5021
  handleCancelFacial = () => {
3804
- callNimIM('sendCustomCmdMsg', {
3805
- customId: this.state.imRoomId,
3806
- content: JSON.stringify({
3807
- 'typeId': 1020,
3808
- 'sessionId': this.state.sessionId,
3809
- 'cameraState': 1, // 1--打开前置 2--打开后置
3810
- "userId": this.state.faceCustomerUid
3811
- })
3812
- });
5022
+ this.sendMessage({
5023
+ 'typeId': 1020,
5024
+ 'sessionId': this.state.sessionId,
5025
+ 'cameraState': 1, // 1--打开前置 2--打开后置
5026
+ "userId": this.state.faceCustomerUid
5027
+ })
3813
5028
  this.setState({
3814
5029
  isModalVisibleFacial: false
3815
5030
  })
@@ -3834,15 +5049,12 @@ class Video extends Component {
3834
5049
  }
3835
5050
  }
3836
5051
  newFaceClick=()=>{
3837
- callNimIM('sendCustomCmdMsg', {
3838
- customId: this.state.imRoomId,
3839
- content: JSON.stringify({
3840
- 'typeId': 1020,
3841
- 'sessionId': this.state.sessionId,
3842
- 'cameraState': 2, // 1--打开前置 2--打开后置
3843
- "userId": this.state.faceCustomerUid
3844
- })
3845
- });
5052
+ this.sendMessage({
5053
+ 'typeId': 1020,
5054
+ 'sessionId': this.state.sessionId,
5055
+ 'cameraState': 2, // 1--打开前置 2--打开后置
5056
+ "userId": this.state.faceCustomerUid
5057
+ })
3846
5058
  this.setState({
3847
5059
  clickedFacial: false,
3848
5060
  clickedOcr: false,
@@ -3953,15 +5165,12 @@ class Video extends Component {
3953
5165
  } else {
3954
5166
  if (this.state.faceCustomerType == 2) {
3955
5167
  // ocr
3956
- callNimIM('sendCustomCmdMsg', {
3957
- customId: this.state.imRoomId,
3958
- content: JSON.stringify({
3959
- 'typeId': 1020,
3960
- 'sessionId': this.state.sessionId,
3961
- 'cameraState': 2, // 1--打开前置 2--打开后置
3962
- "userId": item.customId
3963
- })
3964
- });
5168
+ this.sendMessage({
5169
+ 'typeId': 1020,
5170
+ 'sessionId': this.state.sessionId,
5171
+ 'cameraState': 2, // 1--打开前置 2--打开后置
5172
+ "userId": item.customId
5173
+ })
3965
5174
  }
3966
5175
  var sid
3967
5176
  if (item.feedId == document.getElementById("feedId1").innerText) {
@@ -4032,19 +5241,25 @@ class Video extends Component {
4032
5241
  }
4033
5242
  }
4034
5243
  sgsinImage = () => {
4035
- if (this.state.IDtypeFrontOrBack == IDtypeFront) {
4036
- this.setState({
4037
- facialImg: this.test_controller.TakePicture(1, undefined, undefined, this.state.customOcrSid, 'png'),
4038
- isFaceImage: true,
4039
- facialImgFront: this.test_controller.TakePicture(1, undefined, undefined, this.state.customOcrSid, 'png'),
4040
- })
4041
- } else if (this.state.IDtypeFrontOrBack == IDtypeBack) {
4042
- this.setState({
4043
- facialImg: this.test_controller.TakePicture(1, undefined, undefined, this.state.customOcrSid, 'png'),
4044
- isFaceImage: true,
4045
- facialImgBack: this.test_controller.TakePicture(1, undefined, undefined, this.state.customOcrSid, 'png'),
4046
- })
4047
- }
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
+ })
4048
5263
 
4049
5264
  }
4050
5265
  handleChangeOcr = (val) => {
@@ -4056,10 +5271,10 @@ class Video extends Component {
4056
5271
  })
4057
5272
  }
4058
5273
  componentWillReceiveProps(props) {
4059
- this.state.channelId = props.roomId,
4060
- this.state.rtoken = props.mtoken,
4061
- this.state.sessionId = props.sessionId,
4062
- 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
4063
5278
  }
4064
5279
  appGetUsernameClick = async (userId) => {
4065
5280
  let data = ''
@@ -4088,7 +5303,7 @@ class Video extends Component {
4088
5303
  userId = this.seeList(this.state.roomCustomerList, 'feedId', document.getElementById("feedId"+i).innerText).uid
4089
5304
  }
4090
5305
  }
4091
- if (document.getElementById('publish_video1').name == sid) {
5306
+ if (document.getElementById('publish_streamId1').name == sid) {
4092
5307
  userId = this.props.tellerAccount
4093
5308
  }
4094
5309
  try {
@@ -4108,9 +5323,15 @@ class Video extends Component {
4108
5323
  } else {
4109
5324
  this.messageClick('查询失败', 'error')
4110
5325
  }
4111
- if (this.props.isOpenSound && sid != document.getElementById('publish_video1').name) {
4112
- if (result.data.userType == 1) {
4113
- 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
4114
5335
  let audio = new Audio(src)
4115
5336
  audio.play()
4116
5337
  } else if (result.data.userType == 2) {
@@ -4119,7 +5340,7 @@ class Video extends Component {
4119
5340
  audio.play()
4120
5341
  }
4121
5342
  }
4122
- if (document.getElementById('publish_video1').name == sid) {
5343
+ if (document.getElementById('publish_streamId1').name == sid) {
4123
5344
  this.setState({
4124
5345
  titleNameRm: data
4125
5346
  })
@@ -4207,6 +5428,21 @@ class Video extends Component {
4207
5428
  })
4208
5429
  }
4209
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
+ }
4210
5446
  navigatorClick = () => {
4211
5447
  const that = this
4212
5448
  const publish_config = {};
@@ -4236,8 +5472,10 @@ class Video extends Component {
4236
5472
  canvas.width = 960;
4237
5473
  canvas.height = 540;
4238
5474
 
4239
-
4240
- videoMedia.addEventListener('play', (event) => {
5475
+ if (this.state.whiteboardPlayEvent) {
5476
+ videoMedia.removeEventListener('play', this.state.whiteboardPlayEvent)
5477
+ }
5478
+ this.state.whiteboardPlayEvent = (event) => {
4241
5479
  var $this = this; //cache
4242
5480
  if ($this.state.operateShow) {
4243
5481
  isGraffiti = false
@@ -4248,20 +5486,21 @@ class Video extends Component {
4248
5486
  canvas.width = this.state.whiteboardWidth
4249
5487
  }
4250
5488
  console.log('addEventListener', !$this.paused, !$this.ended, x, y, width, height)
4251
- loop()
4252
- function loop() {
4253
- if (!$this.paused && !$this.ended) {
4254
- // if(!that.state.tabTitles.find(el=>el.value == 'customerScreen')) {
4255
- cobj.drawImage(videoMedia, x, y, width, height, 0, 0, 960, 540);
4256
- // } else {
4257
- // cobj.fillStyle = 'rgb(0 0 0)'
4258
- // cobj.fillRect(0,0,960,540)
4259
- // }
4260
5489
 
4261
- setTimeout(loop, 1000 / 20); // drawing at 30fps
4262
- }
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
+ }
4263
5500
  }
4264
5501
 
5502
+ this.state.drawCanvasInterval = setInterval($this.drawFunction , 1000/ 20);
5503
+
4265
5504
  if (document.getElementById('video20').name) {
4266
5505
  // 代表已经有了进行切流
4267
5506
  publish_config.publish_device = 5
@@ -4284,10 +5523,12 @@ class Video extends Component {
4284
5523
  publish_config.publish_tag = 'projectionWhiteboard'
4285
5524
  this.test_controller.Publish(publish_config)
4286
5525
  }
4287
- }, 0);
5526
+ }
5527
+ videoMedia.addEventListener('play', this.state.whiteboardPlayEvent);
4288
5528
  navigator.mediaDevices.getDisplayMedia({
4289
5529
  video: true,
4290
5530
  preferCurrentTab: true,
5531
+ surfaceSwitching: "exclude"
4291
5532
  // audio: true
4292
5533
  // video: {
4293
5534
  // width: document.body.clientWidth,
@@ -4313,16 +5554,46 @@ class Video extends Component {
4313
5554
  //单击停止共享按钮后,触发这个事件
4314
5555
  streamShare = ''
4315
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')
4316
5559
  that.test_controller.UnPublish(document.getElementById('video20').name)
4317
5560
  }
4318
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
+
4319
5577
  }, error => {
4320
5578
  console.log("Unable to acquire screen capture", error);
5579
+ console.log('取消签署')
5580
+ that.saveLog('Manual cancel share')
4321
5581
  });
4322
5582
  }
4323
- // publishAllScreen = () => {
4324
-
4325
- // }
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
+ }
4326
5597
  publishAllScreen = () => {
4327
5598
  const that = this
4328
5599
  const publish_config = {};
@@ -4370,6 +5641,7 @@ class Video extends Component {
4370
5641
  navigator.mediaDevices.getDisplayMedia({
4371
5642
  video: true,
4372
5643
  preferCurrentTab: true,
5644
+ surfaceSwitching: "exclude"
4373
5645
  })
4374
5646
  .then((stream) => {
4375
5647
  if (streamRecord) {
@@ -4390,6 +5662,8 @@ class Video extends Component {
4390
5662
  //单击停止共享按钮后,触发这个事件
4391
5663
  streamRecord = ''
4392
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')
4393
5667
  that.test_controller.UnPublish(document.getElementById('record_video').name)
4394
5668
  }
4395
5669
  }
@@ -4568,13 +5842,151 @@ class Video extends Component {
4568
5842
  this.test_controller.GetDevices()
4569
5843
  }
4570
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
+ // }
4571
5983
  handleOkInspection = () => {
4572
5984
  this.setState({
4573
5985
  isModalVisibleInspection: false,
4574
5986
  loading: true
4575
5987
  })
4576
5988
  const config = {}
4577
- config.sid = document.getElementById('publish_video1').name
5989
+ config.sid = document.getElementById('publish_video1').name || document.getElementById('publish_streamId1').name
4578
5990
  config.videoSource = this.state.cameraValue
4579
5991
  config.audioSource = this.state.microphoneValue
4580
5992
  this.test_controller.ChangeProfile(config)
@@ -4613,16 +6025,39 @@ class Video extends Component {
4613
6025
  this.setState({
4614
6026
  beautyName: '开启美颜'
4615
6027
  })
6028
+ beautyMode = 'none'
4616
6029
  beautySetMode('none')
6030
+ beautyStop()
6031
+ if(!isSuccuseHs) {
6032
+ stopHs()
6033
+ }
4617
6034
  } else {
4618
6035
  this.state.beautyType = true
6036
+ beautyMode = 'beauty'
4619
6037
  beautySetMode('beauty')
4620
6038
  this.setState({
4621
6039
  beautyName: '关闭美颜'
4622
6040
  })
4623
6041
  }
6042
+ this.changeMediaStream();
4624
6043
 
4625
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
+
4626
6061
  componentDidMount() {
4627
6062
  var box = document.getElementById("whiteboardDIV");
4628
6063
  var box1 = document.getElementById("operate")
@@ -4640,117 +6075,81 @@ class Video extends Component {
4640
6075
  muteOpposite = (value) => {
4641
6076
  console.log(value);
4642
6077
  if (value == 'video1') {
4643
- callNimIM('sendCustomCmdMsg', {
4644
- customId: this.state.imRoomId,
4645
- content: JSON.stringify({
4646
- 'typeId': 1223,
4647
- 'sessionId': this.state.sessionId,
4648
- 'userId': this.seeList(this.state.roomCustomerList, 'feedId', document.getElementById('feedId1').innerText).uid
4649
- })
4650
- });
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
+ })
4651
6083
  }
4652
6084
  if (value == 'video2') {
4653
- callNimIM('sendCustomCmdMsg', {
4654
- customId: this.state.imRoomId,
4655
- content: JSON.stringify({
4656
- 'typeId': 1223,
4657
- 'sessionId': this.state.sessionId,
4658
- 'userId': this.seeList(this.state.roomCustomerList, 'feedId', document.getElementById('feedId2').innerText).uid
4659
- })
4660
- });
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
+ })
4661
6090
  } if (value == 'video3') {
4662
- callNimIM('sendCustomCmdMsg', {
4663
- customId: this.state.imRoomId,
4664
- content: JSON.stringify({
4665
- 'typeId': 1223,
4666
- 'sessionId': this.state.sessionId,
4667
- 'userId': this.seeList(this.state.roomCustomerList, 'feedId', document.getElementById('feedId3').innerText).uid
4668
- })
4669
- });
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
+ })
4670
6096
  } if (value == 'video4') {
4671
- callNimIM('sendCustomCmdMsg', {
4672
- customId: this.state.imRoomId,
4673
- content: JSON.stringify({
4674
- 'typeId': 1223,
4675
- 'sessionId': this.state.sessionId,
4676
- 'userId': this.seeList(this.state.roomCustomerList, 'feedId', document.getElementById('feedId4').innerText).uid
4677
- })
4678
- });
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
+ })
4679
6102
  } if (value == 'video5') {
4680
- callNimIM('sendCustomCmdMsg', {
4681
- customId: this.state.imRoomId,
4682
- content: JSON.stringify({
4683
- 'typeId': 1223,
4684
- 'sessionId': this.state.sessionId,
4685
- 'userId': this.seeList(this.state.roomCustomerList, 'feedId', document.getElementById('feedId5').innerText).uid
4686
- })
4687
- });
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
+ })
4688
6108
  } if (value == 'video6') {
4689
- callNimIM('sendCustomCmdMsg', {
4690
- customId: this.state.imRoomId,
4691
- content: JSON.stringify({
4692
- 'typeId': 1223,
4693
- 'sessionId': this.state.sessionId,
4694
- 'userId': this.seeList(this.state.roomCustomerList, 'feedId', document.getElementById('feedId6').innerText).uid
4695
- })
4696
- });
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
+ })
4697
6114
  } if (value == 'video7') {
4698
- callNimIM('sendCustomCmdMsg', {
4699
- customId: this.state.imRoomId,
4700
- content: JSON.stringify({
4701
- 'typeId': 1223,
4702
- 'sessionId': this.state.sessionId,
4703
- 'userId': this.seeList(this.state.roomCustomerList, 'feedId', document.getElementById('feedId7').innerText).uid
4704
- })
4705
- });
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
+ })
4706
6120
  } if (value == 'video8') {
4707
- callNimIM('sendCustomCmdMsg', {
4708
- customId: this.state.imRoomId,
4709
- content: JSON.stringify({
4710
- 'typeId': 1223,
4711
- 'sessionId': this.state.sessionId,
4712
- 'userId': this.seeList(this.state.roomCustomerList, 'feedId', document.getElementById('feedId8').innerText).uid
4713
- })
4714
- });
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
+ })
4715
6126
  } if (value == 'video9') {
4716
- callNimIM('sendCustomCmdMsg', {
4717
- customId: this.state.imRoomId,
4718
- content: JSON.stringify({
4719
- 'typeId': 1223,
4720
- 'sessionId': this.state.sessionId,
4721
- 'userId': this.seeList(this.state.roomCustomerList, 'feedId', document.getElementById('feedId9').innerText).uid
4722
- })
4723
- });
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
+ })
4724
6132
  }
4725
6133
  if (value == 'video10') {
4726
- callNimIM('sendCustomCmdMsg', {
4727
- customId: this.state.imRoomId,
4728
- content: JSON.stringify({
4729
- 'typeId': 1223,
4730
- 'sessionId': this.state.sessionId,
4731
- 'userId': this.seeList(this.state.roomCustomerList, 'feedId', document.getElementById('feedId10').innerText).uid
4732
- })
4733
- });
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
+ })
4734
6139
  }
4735
6140
  if (value == 'video11') {
4736
- callNimIM('sendCustomCmdMsg', {
4737
- customId: this.state.imRoomId,
4738
- content: JSON.stringify({
4739
- 'typeId': 1223,
4740
- 'sessionId': this.state.sessionId,
4741
- 'userId': this.seeList(this.state.roomCustomerList, 'feedId', document.getElementById('feedId11').innerText).uid
4742
- })
4743
- });
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
+ })
4744
6146
  }
4745
6147
  if (value == 'video12') {
4746
- callNimIM('sendCustomCmdMsg', {
4747
- customId: this.state.imRoomId,
4748
- content: JSON.stringify({
4749
- 'typeId': 1223,
4750
- 'sessionId': this.state.sessionId,
4751
- 'userId': this.seeList(this.state.roomCustomerList, 'feedId', document.getElementById('feedId12').innerText).uid
4752
- })
4753
- });
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
+ })
4754
6153
  }
4755
6154
 
4756
6155
  }
@@ -4759,14 +6158,11 @@ class Video extends Component {
4759
6158
  this.state.shareMaskState = this.props.shareMask
4760
6159
  // 加延迟是因为在关闭的时候可以看到部分rm的操作
4761
6160
  setTimeout(() => {
4762
- callNimIM('sendCustomCmdMsg', {
4763
- customId: this.state.imRoomId,
4764
- content: JSON.stringify({
4765
- 'typeId': 1230,
4766
- 'sessionId': this.state.sessionId,
4767
- 'type': this.state.shareMaskState ? 1 : 2
4768
- })
4769
- });
6161
+ this.sendMessage({
6162
+ 'typeId': 1230,
6163
+ 'sessionId': this.state.sessionId,
6164
+ 'type': this.state.shareMaskState ? 1 : 2
6165
+ })
4770
6166
  }, 100)
4771
6167
 
4772
6168
  }
@@ -4774,11 +6170,18 @@ class Video extends Component {
4774
6170
  if (!isSuccuseHs) {
4775
6171
 
4776
6172
  hsSetMode('blur')
6173
+ hsMode = 'blur'
4777
6174
  isSuccuseHs = true
4778
6175
  } else {
4779
6176
  hsSetMode('none')
6177
+ hsMode = 'none'
4780
6178
  isSuccuseHs = false
6179
+ stopHs()
6180
+ if(!this.state.beautyType) {
6181
+ beautyStop()
6182
+ }
4781
6183
  }
6184
+ this.changeMediaStream();
4782
6185
  }
4783
6186
  virtualization = () => {
4784
6187
  this.virtualizationClick()
@@ -4805,6 +6208,17 @@ class Video extends Component {
4805
6208
  return false;
4806
6209
  }
4807
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
+ }
4808
6222
  handleChangeCertificateValidity = (event) => {
4809
6223
  // 护照只有起始日期,单独处理
4810
6224
  if (this.state.documentType == 'PASSPORT_CARD' && event.target.value.split('.').length >2) {
@@ -4825,6 +6239,12 @@ class Video extends Component {
4825
6239
  certificateValidity: event.target.value,
4826
6240
  certificateValidityType: true
4827
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
+ });
4828
6248
  } else {
4829
6249
  this.setState({
4830
6250
  certificateValidity: event.target.value,
@@ -4839,6 +6259,9 @@ class Video extends Component {
4839
6259
  if (this.props.shareMask != prevProps.shareMask) {
4840
6260
  this.sendNotification()
4841
6261
  }
6262
+ if (this.props.pdfRendering != prevProps.pdfRendering) {
6263
+ this.changePdfRendering()
6264
+ }
4842
6265
  }
4843
6266
  onChangeOCRCustomer = (e) => {
4844
6267
  console.log(e)
@@ -4939,8 +6362,10 @@ class Video extends Component {
4939
6362
 
4940
6363
  }))
4941
6364
  }
4942
-
4943
-
6365
+ this.setState({
6366
+ documentError: '',
6367
+ isModalVisibleCustomer: false,
6368
+ })
4944
6369
  }
4945
6370
  })
4946
6371
  // this.customerFaceClick(this.state.customerList[this.state.customerSelect])
@@ -5153,6 +6578,15 @@ class Video extends Component {
5153
6578
  </div>
5154
6579
  )
5155
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
+
5156
6590
  const sectionStyle = this.state.tabTitles.length > 0 ? {
5157
6591
  zIndex: '-1',
5158
6592
  width: '100%',
@@ -5178,7 +6612,7 @@ class Video extends Component {
5178
6612
  return (
5179
6613
  <div className="all" id="allHSBC">
5180
6614
  <Spin spinning={this.state.loading} tip="视频初始化中...">
5181
- <Header></Header>
6615
+ <Header recordMode={this.props.recordMode}></Header>
5182
6616
  <div className="health">
5183
6617
  <div className="healthVideo">
5184
6618
  <div className="projection" style={{ background: this.state.tabTitles.length > 0 ? '#f0f0f0' : '#ffffff' }}>
@@ -5199,6 +6633,18 @@ class Video extends Component {
5199
6633
  }
5200
6634
  <canvas id="canvas" className="canvas"></canvas>
5201
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>
5202
6648
  <div className="videoDiv" style={{ display: (this.state.isSelect == 'RMScreen' || this.state.isSelect == 'staffScreen') ? '' : 'none', }}>
5203
6649
  <div className="videoDiv" style={{ 'textAlign': 'center' }}>
5204
6650
  <video
@@ -5257,19 +6703,28 @@ class Video extends Component {
5257
6703
  {otherAttendeesList}
5258
6704
  </li>
5259
6705
  }
6706
+ {
6707
+ this.props.recordMode != 2 &&
5260
6708
  <li>
5261
6709
  请注意,若会议中需要客户出示证件,请客户使用手机的后置摄像头展示证件,由客户经理拍摄证件照片以完成客户身份核实。客户可点击会议主页面上的”切换摄像头“按钮切换手机摄像头
5262
6710
  </li>
6711
+ }
5263
6712
 
5264
6713
  </ul>
5265
6714
  </div>
5266
- {!this.state.loading && this.state.sessionId?
5267
- <QRCode
5268
- style={{'position': 'absolute', 'right': '10px', 'top': '-110px'}}
5269
- value={this.state.sessionId} //value参数为生成二维码的链接
5270
- 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} //二维码的宽高尺寸
5271
6724
  fgColor="#000000" //二维码的颜色
5272
- /> : null}
6725
+ />
6726
+ <div className='sessionDiv' style={{marginTop: '20px'}}><span>会议号码</span><div className='num'>{this.state.sessionId}</div></div>
6727
+ </div> : null}
5273
6728
  </div>
5274
6729
  }
5275
6730
 
@@ -5279,6 +6734,7 @@ class Video extends Component {
5279
6734
  <div id="videoList" className={`wrapper ${this.state.isVideoList? 'videoListClass': ''}`} style={{ width: '20%' }}>
5280
6735
  <div
5281
6736
  className={`itemed ${this.state.isVideoList? 'videoMinutuListClass': 'videoMinutuClass'}`}
6737
+ style={{ display: (this.props.recordMode == 2) ? 'none' : ''}}
5282
6738
  >
5283
6739
  <div className="publishVideoDiv">
5284
6740
 
@@ -5307,7 +6763,7 @@ class Video extends Component {
5307
6763
  </div>
5308
6764
 
5309
6765
  </div>
5310
- {
6766
+ {/* {
5311
6767
  this.state.cameraList.map((item, index) => {
5312
6768
  if (index > 0)
5313
6769
  return <div
@@ -5340,7 +6796,7 @@ class Video extends Component {
5340
6796
  </div>
5341
6797
  </div>
5342
6798
  })
5343
- }
6799
+ } */}
5344
6800
  {/* <div className={`itemed ${this.state.isVideoList? 'videoMinutuListClass': 'videoMinutuClass'}`}
5345
6801
  style={{ position: "relative", display: (this.state.videoList[0].videoName) ? '' : 'none' }}
5346
6802
  >
@@ -5389,7 +6845,8 @@ class Video extends Component {
5389
6845
  <audio id={'audio'+(item.idIndex)} autoPlay />
5390
6846
  <label style={{ display: 'none' }} id={'feedId'+(item.idIndex)} type="text" />
5391
6847
 
5392
- <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>:<>
5393
6850
  {
5394
6851
  item.mute && <img
5395
6852
  alt=""
@@ -5398,7 +6855,7 @@ class Video extends Component {
5398
6855
  />
5399
6856
  }
5400
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>
5401
-
6858
+ </>}
5402
6859
  <div className='titleName' style={{ color: this.props.titleColor,fontSize: this.props.fontSize + 'px',fontFamily : this.props.fontFamily}}>
5403
6860
  {item.videoName}
5404
6861
  </div>
@@ -5429,7 +6886,7 @@ class Video extends Component {
5429
6886
  ocrHandleVisibleChange={this.ocrHandleVisibleChange}
5430
6887
  voice={this.voice}
5431
6888
  cameraClick={this.cameraClick}
5432
- sharedScreen={this.sharedScreen}
6889
+ sharedScreen={()=> {this.saveLog('Click share button');this.sharedScreen();}}
5433
6890
  endSession={this.endSession}
5434
6891
  facialRecognition={this.facialRecognition}
5435
6892
  pictureInPicture={this.pictureInPicture}
@@ -5437,8 +6894,10 @@ class Video extends Component {
5437
6894
  invitationClick={this.invitationClick}
5438
6895
  customerFaceClick={this.customerFaceClick}
5439
6896
  ocrClick={this.ocrClick}
5440
- switchExternal={this.switchExternal}
6897
+ switchExternal={()=> {this.saveLog('Click sign button');this.switchExternal();}}
5441
6898
  inspection={this.inspection}
6899
+ toggleAsr={this.toggleAsr}
6900
+ envDetection={this.showEnvDetection}
5442
6901
  beautyClick={this.beautyClick}
5443
6902
  graffiti={this.graffiti}
5444
6903
  virtualization={this.virtualization}
@@ -5453,6 +6912,60 @@ class Video extends Component {
5453
6912
  !this.state.isSuspend && <span>确定是否暂停会话?</span>
5454
6913
  }
5455
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>
5456
6969
  {/* 是否退出会议*/}
5457
6970
  <Modal closable={false} centered={true} visible={this.state.isModalVisibleEnd} maskClosable={false} footer={[
5458
6971
  <div key='end'>
@@ -5460,7 +6973,7 @@ class Video extends Component {
5460
6973
  <Button className="modelButtonOk" type="primary" danger onClick={this.handleOkEnd}>确定</Button>
5461
6974
  </div>
5462
6975
  ]}>
5463
- <div className='endModal'>是否要结束并退出会议?</div>
6976
+ <div className='endModal'>{this.state.businessId? '正在进行业务录制,是否确认结束并退出会议?': '是否要结束并退出会议?'}</div>
5464
6977
  </Modal>
5465
6978
  {/* ocr及人脸 */}
5466
6979
  <Modal title={this.state.titleModal} width={800} closable={true} maskClosable={false} onCancel={this.handleCancelFacial} centered={true} visible={this.state.isModalVisibleFacial} footer={[
@@ -5800,12 +7313,99 @@ class Video extends Component {
5800
7313
 
5801
7314
  </div>
5802
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>
5803
7402
  <video className="mixedvideo" id="mixedvideo" autoPlay muted={true} width="0" height="0"></video>
5804
7403
  <video className="mixedvideo" id="manedvideo" autoPlay width="0" height="0"></video>
5805
7404
  <video className="mixedvideo" id="video30" autoPlay width="0" height="0"></video>
5806
7405
 
5807
7406
  <video className="mixedvideo" id="recordvideo" autoPlay width="0" height="0"></video>
5808
7407
  <video className="mixedvideo" id="record_video" muted autoPlay></video>
7408
+ <video className="mixedvideo" id="publish_video_record_device" muted autoPlay></video>
5809
7409
 
5810
7410
  </Spin>
5811
7411
  </div>);
@@ -5821,7 +7421,10 @@ Video.defaultProps = {
5821
7421
  callbackUrl: 'http://182.92.184.31:8720/hsbc/callback',
5822
7422
  // roomServerUrl: 'wss://app.uat.dsp.hsbcfts.com.cn/mpaas/mrtc/ws',
5823
7423
  roomServerUrl: 'wss://mrtc.mpaas.cn-hangzhou.aliyuncs.com/ws',
5824
-
7424
+ // asr公有云默认参数
7425
+ // asrServerUrl: 'wss://nls-gateway.cn-shanghai.aliyuncs.com/ws/v1',
7426
+ // asrAppKey: 'E6DAPlpMun5L2dJ7',
7427
+ // asrToken: 'a07198021d434d1288cd4ab3178712cb',
5825
7428
  resourcePath: 'https://counter-web.leimondata.cn:7199',
5826
7429
  // resourcePath: 'https://zuul.uat.dsp.hsbcfts.com.cn/wealth/js/',
5827
7430
  prohbiitPrompt: '当前无客户',
@@ -5831,18 +7434,36 @@ Video.defaultProps = {
5831
7434
  microphoneSize: 25,
5832
7435
  fontSize: '14',
5833
7436
  fontFamily: 'auto',
5834
- menus: ['BOARD', 'SHARE', 'FRIES', 'OCR', 'INVITE', 'PIP', 'BEAUTY', 'GRAFFITI', 'BACKGROUND'],
7437
+ menus: ['BOARD', 'SHARE', 'FRIES', 'OCR', 'PAPER_OCR', 'INVITE', 'PIP', 'BEAUTY', 'GRAFFITI', 'BACKGROUND'],
5835
7438
  customLeaveRoom: '客户离开房间',
7439
+ sensitiveWords: ['保本保息', '无风险'],
7440
+ // speakerNames: ['扬声器'], // null或不传,则不强制使用扬声器设备;若传入有效数组,则每项代表允许的设备名称如"xxx Speaker Device",逻辑为包含,不需要全等。
5836
7441
  meetingInfo: {
5837
7442
  title: '--',
5838
7443
  host: '--',
5839
7444
  customers: ['--'],
5840
7445
  otherAttendees: undefined
5841
7446
  },
7447
+ pdfRendering: false,
5842
7448
  isTranscribing: false,
5843
7449
  shareMask: false,
5844
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
5845
7458
  userSide: 2,
7459
+ meetingDuration: null, // 会议时长,单位小时
7460
+ recordMode: 1, // 录制模式 1远程录制 2网点录制
7461
+ defaultBranchCode: "",// 员工网点缩写
7462
+ customerId: "", //客户号
7463
+ customerType: "", // 客户类型
7464
+ salesBranchCode: "", //网点编号(分行号)
7465
+ financialOffice: "", // 理财室
7466
+ staffName: '', // 坐席名称
5846
7467
  logUrl: 'http://hsbc.cn-shanghai.log.aliyuncs.com/logstores/hsbc/track?APIVersion=0.6.0&app=meeting-ui',
5847
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'
5848
7469
  }