ConsultationRecipientV2.cs 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Threading;
  5. using Vinno.IUS.Common.Log;
  6. using Vinno.vCloud.Common.FIS.Helper;
  7. using Vinno.vCloud.FIS.CrossPlatform.Common.LiveVideo;
  8. using Vinno.vCloud.Protocol.Infrastructures;
  9. using Vinno.vCloud.Protocol.Messages.Client.LiveTalking;
  10. using WingInterfaceLibrary.Interface;
  11. using WingInterfaceLibrary.LiveConsultation;
  12. using WingInterfaceLibrary.Request.Device;
  13. using WingInterfaceLibrary.Request.User;
  14. namespace Vinno.vCloud.Common.FIS.Consultation
  15. {
  16. internal class ConsultationRecipientV2 : ConsultationClientV2
  17. {
  18. private readonly string _deviceId;
  19. /// <summary>
  20. /// Raised when receive a Consultation request from server.
  21. /// </summary>
  22. public event EventHandler<ConsultationInfo> ConsultationRequestArrived;
  23. /// <summary>
  24. /// 当开始Web会诊时
  25. /// </summary>
  26. public event EventHandler<string> StartWebConsultationEvent;
  27. /// <summary>
  28. /// 当切换病人时触发,病人信息与会诊code变更
  29. /// </summary>
  30. public event EventHandler<ChangeLiveConsultationrResult> ChangeLiveConsultationEvent;
  31. /// <summary>
  32. /// 当扫查手法摄像头开启或关闭时触发
  33. /// </summary>
  34. public event EventHandler<TerminalInfo> TerminalInfoChangedEvent;
  35. public ConsultationRecipientV2(ConsultationLiveVideoProviderV2 videoProvider, ConsultationManagerV2 consultationManager, string deviceId, ILiveConsultationService liveConsultationService, IUserService userService, IDeviceService deviceService) : base(videoProvider, consultationManager, liveConsultationService, userService, deviceService)
  36. {
  37. _deviceId = deviceId;
  38. LiveVideoStatusChecker.Instance.CurrentMachineConsultationStopPushingEvent += OnCurrentMachineConsultationStopPushingEvent;
  39. }
  40. private void OnCurrentMachineConsultationStopPushingEvent(object sender, EventArgs e)
  41. {
  42. TerminalInfo terminalInfo;
  43. try
  44. {
  45. Thread.Sleep(1000);
  46. if (ConsultationInfo != null && ConsultationInfo.IsCurrentTerminal)
  47. {
  48. var joinLiveConsultationRequest = new JoinLiveConsultationRequest
  49. {
  50. Token = AccountToken,
  51. CheckOnly = false,
  52. ConsultationCode = ConsultationInfo.ConsultationId,
  53. };
  54. var liveConsultationMember = JsonRpcHelper.DeviceJoinInLiveConsultation(LiveConsultationService, joinLiveConsultationRequest);
  55. if (liveConsultationMember == null)
  56. {
  57. Logger.WriteLineError($"DeviceJoinInLiveConsultation Error: result is null");
  58. return;
  59. }
  60. terminalInfo = DTOConverter.ConvertLiveConsultationMemberToTerminalInfo(liveConsultationMember, ConsultationInfo.LiveProtocol);
  61. lock (ConsultationInfoLocker)
  62. {
  63. if (ConsultationInfo != null && ConsultationInfo.IsCurrentTerminal)
  64. {
  65. ConsultationInfo.TerminalInfo = terminalInfo;
  66. }
  67. }
  68. UpdateTerminalInfo();
  69. TerminalInfoChangedEvent?.Invoke(this, terminalInfo);
  70. }
  71. }
  72. catch (Exception ex)
  73. {
  74. Logger.WriteLineError($"StopLiveVideoPushing Event Error:{ex}");
  75. }
  76. }
  77. /// <summary>
  78. /// 非本机第二窗口会诊,RTMP之后还会触发StartLiveConsultation
  79. /// </summary>
  80. /// <returns></returns>
  81. public ResultInfoDTO StartWebConsultation(FlutterLiveConsultationInfo flutterLiveConsultationInfo)
  82. {
  83. try
  84. {
  85. if (CurrentLiveStatus == LiveStates.RecipientAcceptting || CurrentLiveStatus == LiveStates.RecipientAcceptted)
  86. {
  87. Logger.WriteLineInfo($"Consultation Live-- accept Consultation failed due to CurrentLiveStatus is {CurrentLiveStatus}");
  88. return new ResultInfoDTO
  89. {
  90. IsSuccess = false,
  91. FailMessage = $"StartWebConsultation Fail,Consultation is busy.",
  92. ErrorCode = 861,
  93. };
  94. }
  95. if (string.IsNullOrEmpty(flutterLiveConsultationInfo.ConsulationId))
  96. {
  97. return new ResultInfoDTO
  98. {
  99. IsSuccess = false,
  100. FailMessage = $"StartWebConsultation Fail,Consultation id is null.",
  101. };
  102. }
  103. IsSecondViewMode = true;
  104. ConsultationInfo consultationInfo = new ConsultationInfo(ChatRole.Recipient)
  105. {
  106. ConsultationId = flutterLiveConsultationInfo.ConsulationId,
  107. };
  108. consultationInfo.PatientInfo = ConsultationManager.FindConsultationDetail(flutterLiveConsultationInfo.ConsulationId, AccountToken, out _);
  109. lock (ConsultationInfoLocker)
  110. {
  111. ConsultationInfo = consultationInfo;
  112. }
  113. StartWebConsultationEvent?.Invoke(this, flutterLiveConsultationInfo.LiveConsultationFlutterUrl);
  114. return new ResultInfoDTO
  115. {
  116. IsSuccess = true,
  117. };
  118. }
  119. catch (Exception ex)
  120. {
  121. Logger.WriteLineError($"Exception happened when StartWebConsultation {ex}");
  122. Hangup(true);
  123. return new ResultInfoDTO
  124. {
  125. IsSuccess = false,
  126. FailMessage = $"StartWebConsultation Error:{ex}",
  127. };
  128. }
  129. }
  130. /// <summary>
  131. /// 本机RTC/RTMP会诊
  132. /// </summary>
  133. /// <returns></returns>
  134. public ResultInfoDTO StartLiveConsultation(LiveConsultationRequestDTO liveConsultationRequestDTO, string cameraHardwareId, string micHardwareId, string speakerHardwareId)
  135. {
  136. try
  137. {
  138. if (CurrentLiveStatus == LiveStates.RecipientAcceptting || CurrentLiveStatus == LiveStates.RecipientAcceptted || IsSecondViewMode)
  139. {
  140. Logger.WriteLineInfo($"Consultation Live-- accept Consultation failed due to CurrentLiveStatus is {CurrentLiveStatus},IsSecondViewMode:{IsSecondViewMode}");
  141. if (liveConsultationRequestDTO.IsInvite)
  142. {
  143. return new ResultInfoDTO
  144. {
  145. IsSuccess = false,
  146. FailMessage = $"AcceptConsultation Fail,Consultation is busy.",
  147. ErrorCode = 852,
  148. };
  149. }
  150. else
  151. {
  152. return new ResultInfoDTO
  153. {
  154. IsSuccess = false,
  155. FailMessage = $"AcceptConsultation Fail,Consultation is busy.",
  156. ErrorCode = 861,
  157. };
  158. }
  159. }
  160. if (string.IsNullOrEmpty(AccountId))
  161. {
  162. CurrentLiveStatus = LiveStates.UnknowException;
  163. return new ResultInfoDTO
  164. {
  165. IsSuccess = false,
  166. FailMessage = $"AcceptConsultation Fail,AccountId is Null.",
  167. };
  168. }
  169. string deviceId = null;
  170. CurrentLiveStatus = LiveStates.RecipientAcceptting;
  171. Logger.WriteLineInfo($"Consultation Live-- {AccountName} start Consultation request begin");
  172. ConsultationInfo consultationInfo;
  173. List<WhiteBoardDataDTO> whiteBoardDataDTOList = new List<WhiteBoardDataDTO>();
  174. if (liveConsultationRequestDTO.IsInvite)
  175. {
  176. var initiateLiveConsultationRequest = new InitiateLiveConsultationRequest
  177. {
  178. ConsultationCode = liveConsultationRequestDTO.ConsultationCode,
  179. Token = AccountToken,
  180. CheckOnly = false,
  181. };
  182. var initiateLiveConsultationResult = JsonRpcHelper.InitiateLiveConsultation(LiveConsultationService, initiateLiveConsultationRequest, out var errorCode);
  183. if (initiateLiveConsultationResult == null)
  184. {
  185. CurrentLiveStatus = LiveStates.UnknowException;
  186. return new ResultInfoDTO
  187. {
  188. IsSuccess = false,
  189. FailMessage = $"Initiate Consultation Fail,result is null",
  190. ErrorCode = errorCode
  191. };
  192. }
  193. consultationInfo = DTOConverter.ConvertInitiateLiveConsultationResultToConsultationInfo(initiateLiveConsultationResult);
  194. consultationInfo.PatientInfo = ConsultationManager.FindConsultationDetail(liveConsultationRequestDTO.ConsultationCode, AccountToken, out deviceId);
  195. }
  196. else if (liveConsultationRequestDTO.IsJoin)
  197. {
  198. var joinLiveConsultationRequest = new JoinLiveConsultationRequest
  199. {
  200. ConsultationCode = liveConsultationRequestDTO.ConsultationCode,
  201. Token = AccountToken,
  202. CheckOnly = false,
  203. };
  204. var joinLiveConsultationResult = JsonRpcHelper.JoinInLiveConsultation(LiveConsultationService, joinLiveConsultationRequest, out var errorCode);
  205. if (joinLiveConsultationResult == null)
  206. {
  207. CurrentLiveStatus = LiveStates.UnknowException;
  208. return new ResultInfoDTO
  209. {
  210. IsSuccess = false,
  211. FailMessage = $"Join Consultation Fail,result is null",
  212. ErrorCode = errorCode
  213. };
  214. }
  215. consultationInfo = DTOConverter.ConvertJoinLiveConsultationResultToConsultationInfo(joinLiveConsultationResult);
  216. consultationInfo.PatientInfo = ConsultationManager.FindConsultationDetail(liveConsultationRequestDTO.ConsultationCode, AccountToken, out deviceId);
  217. whiteBoardDataDTOList = DTOConverter.ConvertListInteractiveBoardDataDTOToListWhiteBoardDataDTO(joinLiveConsultationResult.InteractiveBoardDatas);
  218. }
  219. else
  220. {
  221. var acceptLiveConsultationRequest = new AcceptLiveConsultationRequest
  222. {
  223. CheckOnly = false,
  224. ConsultationCode = liveConsultationRequestDTO.ConsultationCode,
  225. Token = liveConsultationRequestDTO.Token,
  226. };
  227. var acceptLiveConsultationResult = JsonRpcHelper.AcceptLiveConsultation(LiveConsultationService, acceptLiveConsultationRequest, out var errorCode);
  228. if (acceptLiveConsultationResult == null)
  229. {
  230. CurrentLiveStatus = LiveStates.UnknowException;
  231. return new ResultInfoDTO
  232. {
  233. IsSuccess = false,
  234. FailMessage = $"AcceptConsultation Fail,result is null",
  235. ErrorCode = errorCode
  236. };
  237. }
  238. consultationInfo = DTOConverter.ConvertAcceptLiveConsultationResultToConsultationInfo(acceptLiveConsultationResult);
  239. consultationInfo.PatientInfo = ConsultationManager.FindConsultationDetail(liveConsultationRequestDTO.ConsultationCode, AccountToken, out deviceId);
  240. whiteBoardDataDTOList = DTOConverter.ConvertListInteractiveBoardDataDTOToListWhiteBoardDataDTO(acceptLiveConsultationResult.InteractiveBoardDatas);
  241. }
  242. if (consultationInfo.TerminalInfo != null && !string.IsNullOrEmpty(deviceId))
  243. {
  244. var getDeviceRequest = new GetDeviceRequest
  245. {
  246. DeviceCode = deviceId,
  247. Token = AccountToken,
  248. };
  249. var deviceModel = JsonRpcHelper.GetDeviceInfo(DeviceService, getDeviceRequest);
  250. consultationInfo.TerminalInfo.Model = deviceModel?.DeviceModel;
  251. }
  252. lock (ConsultationInfoLocker)
  253. {
  254. ConsultationInfo = consultationInfo;
  255. }
  256. StartConsultation(cameraHardwareId, micHardwareId, speakerHardwareId, false);
  257. CurrentLiveStatus = LiveStates.RecipientAcceptted;
  258. Logger.WriteLineInfo($"Consultation Live-- {AccountName} accept meeConsultationting request end");
  259. ConsultationRequestArrived?.Invoke(this, ConsultationInfo);
  260. if (whiteBoardDataDTOList != null)
  261. {
  262. foreach (var whiteBoardData in whiteBoardDataDTOList)
  263. {
  264. ReceiveWhiteBoardData(whiteBoardData);
  265. }
  266. }
  267. return new ResultInfoDTO
  268. {
  269. IsSuccess = true,
  270. };
  271. }
  272. catch (Exception ex)
  273. {
  274. Logger.WriteLineError($"Exception happened when accept Consultation{ex}");
  275. Hangup();
  276. return new ResultInfoDTO
  277. {
  278. IsSuccess = false,
  279. FailMessage = $"AcceptConsultation Error:{ex}",
  280. };
  281. }
  282. }
  283. /// <summary>
  284. /// 非本机情况仅RTMP推流会诊
  285. /// </summary>
  286. /// <returns></returns>
  287. public ResultInfoDTO StartLiveConsultation(StartOnlyForRtmpPushingDTO startOnlyForRtmpPushingDTO, string cameraHardwareId, string micHardwareId)
  288. {
  289. try
  290. {
  291. if (CurrentLiveStatus == LiveStates.RecipientAcceptting || CurrentLiveStatus == LiveStates.RecipientAcceptted)
  292. {
  293. Logger.WriteLineInfo($"Consultation Live-- accept Consultation failed due to CurrentLiveStatus is {CurrentLiveStatus}");
  294. return new ResultInfoDTO
  295. {
  296. IsSuccess = false,
  297. FailMessage = $"AcceptConsultation Fail,Consultation is busy.",
  298. ErrorCode = 861,
  299. };
  300. }
  301. if (string.IsNullOrEmpty(AccountId))
  302. {
  303. CurrentLiveStatus = LiveStates.UnknowException;
  304. return new ResultInfoDTO
  305. {
  306. IsSuccess = false,
  307. FailMessage = $"AcceptConsultation Fail,AccountId is Null.",
  308. };
  309. }
  310. CurrentLiveStatus = LiveStates.RecipientAcceptting;
  311. Logger.WriteLineInfo($"Consultation Live-- {AccountName} start Consultation request begin");
  312. ConsultationInfo consultationInfo;
  313. consultationInfo = new ConsultationInfo(ChatRole.Recipient)
  314. {
  315. ConsultationId = startOnlyForRtmpPushingDTO.ConsultationCode,
  316. State = LiveStates.OK,
  317. LiveProtocol = LiveProtocol.Rtmp,
  318. LiveTalkingMode = LiveTalkingMode.Video,
  319. IsCurrentTerminal = false,
  320. ConsultationMemberInfos = new List<ConsultationMemberInfo>
  321. {
  322. new ConsultationMemberInfo
  323. {
  324. PushLiveState = LiveStates.OK,
  325. PushUrl = startOnlyForRtmpPushingDTO.RtmpPushingUrl,
  326. Id = AccountId,
  327. Name = AccountName,
  328. DisplayName = AccountName,
  329. },
  330. },
  331. };
  332. consultationInfo.PatientInfo = ConsultationManager.FindConsultationDetail(startOnlyForRtmpPushingDTO.ConsultationCode, AccountToken, out _);
  333. lock (ConsultationInfoLocker)
  334. {
  335. ConsultationInfo = consultationInfo;
  336. }
  337. StartConsultation(cameraHardwareId, micHardwareId, null, true);
  338. IsOnlyForRtmpPushing = true;
  339. CurrentLiveStatus = LiveStates.RecipientAcceptted;
  340. Logger.WriteLineInfo($"Consultation Live-- {AccountName} accept only rtmp pushing end");
  341. return new ResultInfoDTO
  342. {
  343. IsSuccess = true,
  344. };
  345. }
  346. catch (Exception ex)
  347. {
  348. Logger.WriteLineError($"Exception happened when only rtmp pushing:{ex}");
  349. Hangup();
  350. return new ResultInfoDTO
  351. {
  352. IsSuccess = false,
  353. FailMessage = $"AcceptConsultation Error:{ex}",
  354. };
  355. }
  356. }
  357. internal ResultInfoDTO ChangeLiveConsultation(ChangeLiveConsultationRequestDTO changeLiveConsultation0RequestDTO)
  358. {
  359. try
  360. {
  361. if (ConsultationInfo == null)
  362. {
  363. Logger.WriteLineWarn($"ChangeLiveConsultation Fail: Current is not Consultating");
  364. return new ResultInfoDTO
  365. {
  366. IsSuccess = false,
  367. FailMessage = "ChangeLiveConsultation Fail: Current is not Consultating"
  368. };
  369. }
  370. ConsultationInfo.ConsultationId = changeLiveConsultation0RequestDTO.ConsultationCode;
  371. var patientInfo = ConsultationManager.FindConsultationDetail(changeLiveConsultation0RequestDTO.ConsultationCode, AccountToken, out _);
  372. lock (ConsultationInfoLocker)
  373. {
  374. ConsultationInfo.PatientInfo = patientInfo;
  375. }
  376. if (IsSecondViewMode && !IsOnlyForRtmpPushing)//第二屏且不是rtmp推流的情况下
  377. {
  378. return new ResultInfoDTO
  379. {
  380. IsSuccess = true,
  381. };
  382. }
  383. VideoProvider.ChangeConsultationCodeForConsultationConnectionKeeper(changeLiveConsultation0RequestDTO.ConsultationCode);
  384. if (IsOnlyForRtmpPushing)
  385. {
  386. return new ResultInfoDTO
  387. {
  388. IsSuccess = true,
  389. };
  390. }
  391. ClearAllWhiteBoards();
  392. ChangeLiveConsultationEvent?.Invoke(this, new ChangeLiveConsultationrResult(changeLiveConsultation0RequestDTO.ConsultationCode, ConsultationInfo.PatientInfo));
  393. var currentConsultationMembers = ConsultationInfo?.ConsultationMemberInfos?.ToList();
  394. var leaveMemberList = currentConsultationMembers.Where(x => !changeLiveConsultation0RequestDTO.Members.Any(y => y.Id == x.Id));
  395. if (leaveMemberList != null)
  396. {
  397. foreach (var member in leaveMemberList)
  398. {
  399. member.OperationType = ClientMessageOperationType.Delete;
  400. var consultationMemberChangeDTO = new ConsultationMemberChangeDTO()
  401. {
  402. ConsultationCode = changeLiveConsultation0RequestDTO.ConsultationCode,
  403. MemberInfo = member
  404. };
  405. ConsultationMemberChange(consultationMemberChangeDTO);
  406. var memberInfo = ConsultationInfo?.ConsultationMemberInfos.FirstOrDefault(f => f.Id == consultationMemberChangeDTO.MemberInfo.Id);
  407. if (memberInfo != null)
  408. {
  409. memberInfo.OperationType = ClientMessageOperationType.Delete;
  410. ConsultationInfo?.ConsultationMemberInfos.Remove(memberInfo);
  411. }
  412. var meetingChangeMember = DTOConverter.ConvertConsultationMemberChangeDTOToConsultationMemberNotificaiton(consultationMemberChangeDTO);
  413. HandleConsultationMemberNotificationArrived(meetingChangeMember);
  414. }
  415. }
  416. currentConsultationMembers = ConsultationInfo?.ConsultationMemberInfos?.ToList();
  417. var addMemberList = changeLiveConsultation0RequestDTO.Members.Where(x => !currentConsultationMembers.Any(y => y.Id == x.Id));
  418. if (addMemberList != null)
  419. {
  420. foreach (var member in addMemberList)
  421. {
  422. member.OperationType = ClientMessageOperationType.Add;
  423. var consultationMemberChangeDTO = new ConsultationMemberChangeDTO()
  424. {
  425. ConsultationCode = changeLiveConsultation0RequestDTO.ConsultationCode,
  426. MemberInfo = member
  427. };
  428. ConsultationMemberChange(consultationMemberChangeDTO);
  429. var memberInfo = ConsultationInfo?.ConsultationMemberInfos.FirstOrDefault(f => f.Id == consultationMemberChangeDTO.MemberInfo.Id);
  430. if (memberInfo == null)
  431. {
  432. ConsultationInfo?.ConsultationMemberInfos.Add(member);
  433. }
  434. var meetingChangeMember = DTOConverter.ConvertConsultationMemberChangeDTOToConsultationMemberNotificaiton(consultationMemberChangeDTO);
  435. HandleConsultationMemberNotificationArrived(meetingChangeMember);
  436. }
  437. }
  438. return new ResultInfoDTO
  439. {
  440. IsSuccess = true,
  441. };
  442. }
  443. catch (Exception ex)
  444. {
  445. Logger.WriteLineWarn($"ChangeLiveConsultation error: {ex}");
  446. return new ResultInfoDTO
  447. {
  448. IsSuccess = false,
  449. FailMessage = $"ChangeLiveConsultation Fail: {ex}"
  450. };
  451. }
  452. }
  453. public string GetUserInfo(string token)
  454. {
  455. AccountToken = token;
  456. var getUserRequest = new GetUserInfoRequest
  457. {
  458. Token = token,
  459. };
  460. var userDTO = JsonRpcHelper.GetUserInfo(UserService, getUserRequest);
  461. if (userDTO == null)
  462. {
  463. AccountName = null;
  464. AccountId = null;
  465. Logger.WriteLineError($"GetUserInfo Error,result is null");
  466. return null;
  467. }
  468. else
  469. {
  470. AccountName = userDTO.DisplayName;
  471. AccountId = userDTO.UserCode;
  472. return AccountId;
  473. }
  474. }
  475. public override void Dispose()
  476. {
  477. Logger.WriteLineInfo("Consultation Recipient is dispose begin");
  478. LiveVideoStatusChecker.Instance.CurrentMachineConsultationStopPushingEvent -= OnCurrentMachineConsultationStopPushingEvent;
  479. base.Dispose();
  480. Logger.WriteLineInfo("Consultation Recipient is dispose end");
  481. }
  482. internal ResultInfoDTO LiveConsultationMemberChanged(ConsultationMemberChangeDTO consultationMemberChangeDTO)
  483. {
  484. if (ConsultationInfo == null)
  485. {
  486. Logger.WriteLineWarn($"LiveConsultationMemberChanged Fail: Current is not Consultating");
  487. return new ResultInfoDTO
  488. {
  489. IsSuccess = false,
  490. FailMessage = "LiveConsultationMemberChanged Fail: Current is not Consultating"
  491. };
  492. }
  493. if (ConsultationInfo.ConsultationId != consultationMemberChangeDTO.ConsultationCode)
  494. {
  495. Logger.WriteLineWarn($"LiveConsultationMemberChanged Fail: Current ConsultationCode is {ConsultationInfo.ConsultationId},not {consultationMemberChangeDTO.ConsultationCode}");
  496. return new ResultInfoDTO
  497. {
  498. IsSuccess = false,
  499. FailMessage = $"LiveConsultationMemberChanged Fail: Current ConsultationCode is {ConsultationInfo.ConsultationId},not {consultationMemberChangeDTO.ConsultationCode}"
  500. };
  501. }
  502. ConsultationMemberChange(consultationMemberChangeDTO);
  503. var memberInfo = ConsultationInfo?.ConsultationMemberInfos.FirstOrDefault(f => f.Id == consultationMemberChangeDTO.MemberInfo.Id);
  504. if (consultationMemberChangeDTO.MemberInfo.OperationType == ClientMessageOperationType.Add)
  505. {
  506. if (memberInfo == null)
  507. {
  508. ConsultationInfo.ConsultationMemberInfos.Add(consultationMemberChangeDTO.MemberInfo);
  509. }
  510. memberInfo = consultationMemberChangeDTO.MemberInfo;
  511. }
  512. else if (consultationMemberChangeDTO.MemberInfo.OperationType == ClientMessageOperationType.Delete)
  513. {
  514. if (memberInfo != null)
  515. {
  516. ConsultationInfo?.ConsultationMemberInfos.Remove(memberInfo);
  517. }
  518. }
  519. if (memberInfo != null)
  520. {
  521. consultationMemberChangeDTO.MemberInfo.RoleType = memberInfo.RoleType;
  522. }
  523. var meetingChangeMember = DTOConverter.ConvertConsultationMemberChangeDTOToConsultationMemberNotificaiton(consultationMemberChangeDTO);
  524. HandleConsultationMemberNotificationArrived(meetingChangeMember);
  525. return new ResultInfoDTO
  526. {
  527. IsSuccess = true,
  528. };
  529. }
  530. }
  531. }