PbxController.cs 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569
  1. using Hotline.Caches;
  2. using Hotline.CallCenter.Calls;
  3. using Hotline.CallCenter.Devices;
  4. using Hotline.CallCenter.Ivrs;
  5. using Hotline.CallCenter.Manage;
  6. using Hotline.CallCenter.Tels;
  7. using Hotline.Permissions;
  8. using Hotline.Repository.SqlSugar.CallCenter;
  9. using Hotline.Share.Dtos.CallCenter;
  10. using Hotline.Share.Enums.CallCenter;
  11. using Hotline.Share.Requests;
  12. using Hotline.Users;
  13. using MapsterMapper;
  14. using Microsoft.AspNetCore.Mvc;
  15. using XF.Domain.Authentications;
  16. using XF.Domain.Cache;
  17. using XF.Domain.Exceptions;
  18. using XF.Utility.EnumExtensions;
  19. namespace Hotline.Api.Controllers
  20. {
  21. /// <summary>
  22. /// 话机设备管理
  23. /// </summary>
  24. public class PbxController : BaseController
  25. {
  26. private readonly ITelRepository _telRepository;
  27. private readonly ITelDomainService _telDomainService;
  28. private readonly ITypedCache<Tel> _cacheTel;
  29. private readonly ITypedCache<TelGroup> _cacheTelGroup;
  30. private readonly ITelGroupRepository _telGroupRepository;
  31. private readonly IMapper _mapper;
  32. private readonly IWorkRepository _workRepository;
  33. private readonly IDeviceManager _deviceManager;
  34. private readonly IUserCacheManager _userCacheManager;
  35. private readonly ISessionContext _sessionContext;
  36. private readonly ICallRepository _callRepository;
  37. public PbxController(
  38. ITelRepository telRepository,
  39. ITelDomainService telDomainService,
  40. ITypedCache<Tel> cacheTel,
  41. ITypedCache<TelGroup> cacheTelGroup,
  42. ITelGroupRepository telGroupRepository,
  43. IMapper mapper,
  44. IWorkRepository workRepository,
  45. IDeviceManager deviceManager,
  46. IUserCacheManager userCacheManager,
  47. ISessionContext sessionContext,
  48. ICallRepository callRepository)
  49. {
  50. _telRepository = telRepository;
  51. _telDomainService = telDomainService;
  52. _cacheTel = cacheTel;
  53. _cacheTelGroup = cacheTelGroup;
  54. _telGroupRepository = telGroupRepository;
  55. _mapper = mapper;
  56. _workRepository = workRepository;
  57. _deviceManager = deviceManager;
  58. _userCacheManager = userCacheManager;
  59. _sessionContext = sessionContext;
  60. _callRepository = callRepository;
  61. }
  62. #region 话机
  63. /// <summary>
  64. /// 根据设备自动同步分机数据到数据库
  65. /// </summary>
  66. /// <returns></returns>
  67. [Permission(EPermission.SyncTelsAsync)]
  68. [HttpPut("sync-tels")]
  69. public async Task SyncTelsAsync()
  70. {
  71. var dbTels = await _telRepository.QueryAsync();
  72. foreach (var dbTel in dbTels)
  73. {
  74. _cacheTel.Remove(dbTel.No);
  75. }
  76. //await _telRepository.RemoveRangeAsync(dbTels);
  77. var tels = await _telDomainService.QueryTelsAsync(HttpContext.RequestAborted);
  78. var list = tels.ExceptBy(dbTels.Select(e => e.No), x => x.No).ToList();
  79. var delList = dbTels.ExceptBy(tels.Select(e => e.No), x => x.No).ToList();
  80. for (int i = 0; i < delList.Count; i++)
  81. {
  82. delList[i].SoftDelete();
  83. }
  84. await _telRepository.UpdateRangeAsync(delList);
  85. await _telRepository.AddRangeAsync(list);
  86. }
  87. /// <summary>
  88. /// 查询所有分机
  89. /// </summary>
  90. /// <returns></returns>
  91. [Permission(EPermission.QueryTels)]
  92. [HttpGet("query-tels")]
  93. public async Task<IReadOnlyList<TelDto>> QueryTels()
  94. {
  95. var tels = await _telRepository.QueryExtAsync(d => true, d => d.Includes(x => x.Groups));
  96. return _mapper.Map<IReadOnlyList<TelDto>>(tels);
  97. }
  98. #endregion
  99. #region 分机组
  100. /// <summary>
  101. /// 页面基础信息
  102. /// </summary>
  103. /// <returns></returns>
  104. [Permission(EPermission.GetBaseInfoGroup)]
  105. [HttpGet("base-info-group")]
  106. public async Task<dynamic> GetBaseInfoGroup()
  107. {
  108. return new
  109. {
  110. Distributions = EnumExts.GetDescriptions<EDistribution>()
  111. };
  112. }
  113. /// <summary>
  114. /// 查询所有分机组
  115. /// </summary>
  116. /// <returns></returns>
  117. [Permission(EPermission.QueryTelGroups)]
  118. [HttpGet("query-telgroups")]
  119. public async Task<IReadOnlyList<TelGroupDto>> QueryTelGroups()
  120. {
  121. var groups = await _telGroupRepository.QueryExtAsync(d => true, d => d.Includes(x => x.Tels));
  122. return _mapper.Map<IReadOnlyList<TelGroupDto>>(groups);
  123. }
  124. /// <summary>
  125. /// 新增分机组
  126. /// </summary>
  127. /// <param name="dto"></param>
  128. /// <returns></returns>
  129. [Permission(EPermission.AddTelGroup)]
  130. [HttpPost("add-telgroup")]
  131. public async Task AddTelGroup([FromBody] AddTelGroupDto dto)
  132. {
  133. var works = await _workRepository.QueryAsync(d => dto.TelNos.Contains(d.TelNo) && !d.EndTime.HasValue);
  134. await _deviceManager.AssginConfigGroupAsync(
  135. dto.No,
  136. dto.Distribution.ToString().ToLower(),
  137. ext: works.Select(d => d.TelNo).ToList(),
  138. voiceFile: dto.Voice ?? null,
  139. cancellationToken: HttpContext.RequestAborted);
  140. var group = _mapper.Map<TelGroup>(dto);
  141. var tels = await _telRepository.QueryAsync(d => dto.TelNos.Contains(d.No));
  142. group.Tels = tels;
  143. await _telGroupRepository.AddNavTelsAsync(group, HttpContext.RequestAborted);
  144. _cacheTelGroup.Remove(dto.No);
  145. }
  146. /// <summary>
  147. /// 更新分机组
  148. /// </summary>
  149. /// <param name="dto"></param>
  150. /// <returns></returns>
  151. [Permission(EPermission.UpdateTelGroup)]
  152. [HttpPut("update-telgroup")]
  153. public async Task UpdateTelGroup([FromBody] UpdateTelGroupDto dto)
  154. {
  155. var works = await _workRepository.QueryAsync(d => dto.TelNos.Contains(d.TelNo) && !d.EndTime.HasValue);
  156. await _deviceManager.AssginConfigGroupAsync(
  157. dto.No,
  158. dto.Distribution.ToString().ToLower(),
  159. ext: works.Select(d => d.TelNo).ToList(),
  160. voiceFile: dto.Voice ?? null,
  161. cancellationToken: HttpContext.RequestAborted);
  162. var group = _mapper.Map<TelGroup>(dto);
  163. var tels = await _telRepository.QueryAsync(d => dto.TelNos.Contains(d.No));
  164. group.Tels = tels;
  165. await _telGroupRepository.UpdateNavTelsAsync(group, HttpContext.RequestAborted);
  166. _cacheTelGroup.Remove(dto.No);
  167. }
  168. #endregion
  169. #region 话机设备操作
  170. /// <summary>
  171. /// 分机休息
  172. /// </summary>
  173. /// <returns></returns>
  174. [Permission(EPermission.Rest)]
  175. [HttpPut("rest")]
  176. public async Task Rest()
  177. {
  178. var work = _userCacheManager.GetWorkByUser(_sessionContext.RequiredUserId);
  179. if (work is null)
  180. throw UserFriendlyException.SameMessage("当前坐席暂未进行工作");
  181. await _telDomainService.RestAsync(work, HttpContext.RequestAborted);
  182. }
  183. /// <summary>
  184. /// 分机结束休息
  185. /// </summary>
  186. [Permission(EPermission.UnRest)]
  187. [HttpPut("un-rest")]
  188. public async Task<TelRestDto> UnRest()
  189. {
  190. var work = _userCacheManager.GetWorkByUser(_sessionContext.RequiredUserId);
  191. if (work is null)
  192. throw UserFriendlyException.SameMessage("当前坐席暂未进行工作");
  193. var telRest = await _telDomainService.UnRestAsync(work.TelId, HttpContext.RequestAborted);
  194. return _mapper.Map<TelRestDto>(telRest);
  195. }
  196. /// <summary>
  197. /// 保持通话
  198. /// </summary>
  199. [Permission(EPermission.Hold)]
  200. [HttpPut("hold")]
  201. public async Task Hold(string callId)
  202. {
  203. var work = _userCacheManager.GetWorkByUser(_sessionContext.RequiredUserId);
  204. if (work is null)
  205. throw UserFriendlyException.SameMessage("当前坐席暂未进行工作");
  206. await _telDomainService.HoldAsync(work.TelId,_sessionContext.RequiredUserId,_sessionContext.UserName,callId, HttpContext.RequestAborted);
  207. }
  208. /// <summary>
  209. /// 恢复通话(解除hold状态)
  210. /// </summary>
  211. [Permission(EPermission.UnHold)]
  212. [HttpPut("un-hold")]
  213. public async Task UnHold(string callId)
  214. {
  215. var work = _userCacheManager.GetWorkByUser(_sessionContext.RequiredUserId);
  216. if (work is null)
  217. throw UserFriendlyException.SameMessage("当前坐席暂未进行工作");
  218. await _telDomainService.UnHoldAsync(work.TelId,_sessionContext.RequiredUserId,callId, HttpContext.RequestAborted);
  219. }
  220. /// <summary>
  221. /// 分机呼分机
  222. /// </summary>
  223. /// <returns></returns>
  224. [Permission(EPermission.TelToTel)]
  225. [HttpPost("tel-to-tel")]
  226. public async Task TelToTel([FromBody] TelToTelDto dto)
  227. {
  228. var work = _userCacheManager.GetWorkByUser(_sessionContext.RequiredUserId);
  229. if (work is null)
  230. throw UserFriendlyException.SameMessage("当前坐席暂未进行工作");
  231. await _deviceManager.ExtToExtAsync(work.TelNo, dto.TelNo, HttpContext.RequestAborted);
  232. }
  233. /// <summary>
  234. /// 分机拨打外部电话
  235. /// </summary>
  236. /// <param name="dto"></param>
  237. /// <returns></returns>
  238. [Permission(EPermission.TelToOuter)]
  239. [HttpPost("tel-to-outer")]
  240. public async Task TelToOuter([FromBody] TelToOuterDto dto)
  241. {
  242. var work = _userCacheManager.GetWorkByUser(_sessionContext.RequiredUserId);
  243. if (work is null)
  244. throw UserFriendlyException.SameMessage("当前坐席暂未进行工作");
  245. await _deviceManager.ExtToOuterAsync(work.TelNo, dto.OuterNo, HttpContext.RequestAborted);
  246. }
  247. /// <summary>
  248. /// 指定模拟外线外呼(分机拨打外部电话)
  249. /// OM设备多个外线时调用此接口
  250. /// </summary>
  251. /// <param name="dto"></param>
  252. /// <returns></returns>
  253. [Permission(EPermission.TelToOuterByLine)]
  254. [HttpPost("tel-to-outer-line")]
  255. public async Task TelToOuterByLine([FromBody] TelToOuterByLineDto dto)
  256. {
  257. var work = _userCacheManager.GetWorkByUser(_sessionContext.RequiredUserId);
  258. if (work is null)
  259. throw UserFriendlyException.SameMessage("当前坐席暂未进行工作");
  260. string newOuter = dto.LineId + "," + dto.OuterNo;
  261. await _deviceManager.ExtToOuterAsync(work.TelNo, newOuter, HttpContext.RequestAborted);
  262. }
  263. /// <summary>
  264. /// 来电转分机
  265. /// </summary>
  266. /// <param name="dto"></param>
  267. /// <returns></returns>
  268. [Permission(EPermission.VisitorToTel)]
  269. [HttpPost("visitor-to-tel")]
  270. public async Task VisitorToTel([FromBody] VisitorToTelDto dto)
  271. {
  272. var work = _userCacheManager.GetWorkByUser(_sessionContext.RequiredUserId);
  273. if (work is null)
  274. throw UserFriendlyException.SameMessage("当前坐席暂未进行工作");
  275. var tel = await _deviceManager.QueryTelAsync(work.TelNo, HttpContext.RequestAborted);
  276. if (!string.IsNullOrEmpty(tel.ConversationId))
  277. await _deviceManager.VisitorToExtAsync(tel.ConversationId, dto.TelNo, HttpContext.RequestAborted);
  278. else
  279. throw UserFriendlyException.SameMessage("当前分机没有通话");
  280. }
  281. /// <summary>
  282. /// 来电转外部电话
  283. /// </summary>
  284. /// <param name="dto"></param>
  285. /// <returns></returns>
  286. [Permission(EPermission.VisitorToOuter)]
  287. [HttpPost("visitor-to-outer")]
  288. public async Task VisitorToOuter([FromBody] VisitorToOuterDto dto)
  289. {
  290. var work = _userCacheManager.GetWorkByUser(_sessionContext.RequiredUserId);
  291. if (work is null)
  292. throw UserFriendlyException.SameMessage("当前坐席暂未进行工作");
  293. var tel = await _deviceManager.QueryTelAsync(work.TelNo, HttpContext.RequestAborted);
  294. if (!string.IsNullOrEmpty(tel.ConversationId))
  295. await _deviceManager.VisitorToOuterAsync(tel.ConversationId, dto.OuterNo, HttpContext.RequestAborted);
  296. else
  297. throw UserFriendlyException.SameMessage("当前分机没有通话");
  298. }
  299. /// <summary>
  300. /// 来电转分机组队列
  301. /// </summary>
  302. /// <param name="dto"></param>
  303. /// <returns></returns>
  304. [Permission(EPermission.VisitorToGroup)]
  305. [HttpPost("visitor-to-group")]
  306. public async Task VisitorToGroup([FromBody] VisitorToGroupDto dto)
  307. {
  308. var work = _userCacheManager.GetWorkByUser(_sessionContext.RequiredUserId);
  309. if (work is null)
  310. throw UserFriendlyException.SameMessage("当前坐席暂未进行工作");
  311. var tel = await _deviceManager.QueryTelAsync(work.TelNo, HttpContext.RequestAborted);
  312. if (!string.IsNullOrEmpty(tel.ConversationId))
  313. await _deviceManager.VisitorToGroupAsync(tel.ConversationId, dto.groupid, HttpContext.RequestAborted);
  314. else
  315. throw UserFriendlyException.SameMessage("当前分机没有通话");
  316. }
  317. /// <summary>
  318. /// 去电转外部电话
  319. /// </summary>
  320. /// <param name="dto"></param>
  321. /// <returns></returns>
  322. /// <exception cref="UserFriendlyException"></exception>
  323. [Permission(EPermission.OuterToOuter)]
  324. [HttpPost("outer-to-outer")]
  325. public async Task OuterToOuter([FromBody] OuterToOuterDto dto)
  326. {
  327. var work = _userCacheManager.GetWorkByUser(_sessionContext.RequiredUserId);
  328. if (work is null)
  329. throw UserFriendlyException.SameMessage("当前坐席暂未进行工作");
  330. var tel = await _deviceManager.QueryTelAsync(work.TelNo, HttpContext.RequestAborted);
  331. if (!string.IsNullOrEmpty(tel.ConversationId))
  332. await _deviceManager.OuterToOuterAsync(tel.ConversationId, dto.OuterNo, HttpContext.RequestAborted);
  333. else
  334. throw UserFriendlyException.SameMessage("当前分机没有通话");
  335. }
  336. /// <summary>
  337. /// 去电转分机
  338. /// </summary>
  339. /// <param name="dto"></param>
  340. /// <returns></returns>
  341. /// <exception cref="UserFriendlyException"></exception>
  342. [Permission(EPermission.OuterToTel)]
  343. [HttpPost("outer-to-tel")]
  344. public async Task OuterToTel([FromBody] OuterToTelDto dto)
  345. {
  346. var work = _userCacheManager.GetWorkByUser(_sessionContext.RequiredUserId);
  347. if (work is null)
  348. throw UserFriendlyException.SameMessage("当前坐席暂未进行工作");
  349. var tel = await _deviceManager.QueryTelAsync(work.TelNo, HttpContext.RequestAborted);
  350. if (!string.IsNullOrEmpty(tel.ConversationId))
  351. await _deviceManager.OuterToExtAsync(tel.ConversationId, dto.TelNo, HttpContext.RequestAborted);
  352. else
  353. throw UserFriendlyException.SameMessage("当前分机没有通话");
  354. }
  355. /// <summary>
  356. /// 三方会议
  357. /// 先建立两方通话,然后调用保持通话接口,拨通第三方分机,然后再调用三方会议接口
  358. /// 1. 分机 A 正在和 B 通话;
  359. /// 2. 分机 A 把原通话呼叫保持;
  360. /// 3. 分机 A 向 C 发起新的呼叫,并建立通话;
  361. /// 4. 此时,使用该 API 能够实现以分机 A 为主持方建立 A、B、C 的三方会议。
  362. /// </summary>
  363. /// <param name="dto">TelNo:会议发起方分机号</param>
  364. /// <returns></returns>
  365. /// <exception cref="UserFriendlyException"></exception>
  366. [Permission(EPermission.Conference)]
  367. [HttpPost("meeting")]
  368. public async Task Conference([FromBody] ConferenceDto dto)
  369. {
  370. var work = _userCacheManager.GetWorkByUser(_sessionContext.RequiredUserId);
  371. if (work is null)
  372. throw UserFriendlyException.SameMessage("当前坐席暂未进行工作");
  373. var tel = await _deviceManager.QueryTelAsync(work.TelNo, HttpContext.RequestAborted);
  374. if (!string.IsNullOrEmpty(tel.ConversationId))
  375. await _deviceManager.ConferenceMeetingAsync(dto.TelNo, HttpContext.RequestAborted);
  376. else
  377. throw UserFriendlyException.SameMessage("当前分机没有通话");
  378. }
  379. #region 监听和强插
  380. /// <summary>
  381. /// 监听分机
  382. /// </summary>
  383. /// <param name="request"></param>
  384. /// <returns></returns>
  385. [Permission(EPermission.MonitorExt)]
  386. [HttpPost("monitor-ext")]
  387. public async Task MonitorExt([FromBody] MonitorExtRequest request)
  388. {
  389. await _deviceManager.MonitorExtAsync(request.firstTelNo, request.secondTelNo, HttpContext.RequestAborted);
  390. }
  391. /// <summary>
  392. /// 从监听到插播状态变换
  393. /// 1. 已知:分机 A 在监听分机 B 与其通话方的通话;
  394. /// 2. 执行分机 A 的从监听到插播状态变换的 API;
  395. /// 3. 执行成功时,分机 A 与分机 B 建立通话,分机 B 的原通话方听保持音。
  396. /// </summary>
  397. /// <param name="request"></param>
  398. /// <returns></returns>
  399. [Permission(EPermission.MonitorExtToTalk)]
  400. [HttpPost("monitor-ext-to-talk")]
  401. public async Task MonitorExtToTalk([FromBody] MonitorExtToTalkRequest request)
  402. {
  403. await _deviceManager.MonitorExtToTalkAsync(request.telNo, HttpContext.RequestAborted);
  404. }
  405. /// <summary>
  406. /// 从插播到监听状态变换
  407. /// 1. 已知:分机 A 在插播分机 B 的通话;
  408. /// 2. 执行分机 A 的从插播到监听状态变换的 API;
  409. /// 3. 执行成功时,分机 A 监听分机 B 及其原通话方的通话。
  410. /// </summary>
  411. /// <param name="request"></param>
  412. /// <returns></returns>
  413. [Permission(EPermission.MonitorExtToListen)]
  414. [HttpPost("monitor-ext-to-listen")]
  415. public async Task MonitorExtToListen([FromBody] MonitorExtToListenRequest request)
  416. {
  417. await _deviceManager.MonitorExtToListenAsync(request.telNo, HttpContext.RequestAborted);
  418. }
  419. #endregion
  420. #region 强插
  421. /// <summary>
  422. /// 强插
  423. /// 1. 已知:分机 A 当前空闲,分机 B 正在通话中;
  424. /// 2. 执行分机 A 强插分机 B 的 API;
  425. /// 3. 执行成功时,分机 A 振铃,摘机后即可形成三方通话。
  426. /// </summary>
  427. /// <param name="request"></param>
  428. /// <returns></returns>
  429. [Permission(EPermission.BargeinExt)]
  430. [HttpPost("bargein-ext")]
  431. public async Task BargeinExt([FromBody] BargeinExtRequest request)
  432. {
  433. await _deviceManager.BargeinExtAsync(request.firstTelNo, request.secondTelNo, HttpContext.RequestAborted);
  434. }
  435. #endregion
  436. #region 强拆
  437. /// <summary>
  438. /// 强拆分机
  439. /// </summary>
  440. /// <param name="request"></param>
  441. /// <returns></returns>
  442. [Permission(EPermission.ClearExt)]
  443. [HttpPost("clear-ext")]
  444. public async Task ClearExt([FromBody] ClearExtRequest request)
  445. {
  446. await _deviceManager.ClearExtAsync(request.ExtId, HttpContext.RequestAborted);
  447. }
  448. /// <summary>
  449. /// 强拆来电
  450. /// </summary>
  451. /// <param name="request"></param>
  452. /// <returns></returns>
  453. [Permission(EPermission.ClearVisitor)]
  454. [HttpPost("clear-visitor")]
  455. public async Task ClearVisitor([FromBody] ClearVisitorRequest request)
  456. {
  457. //查询当前通话记录
  458. var call = await _callRepository.GetAsync(request.CallId, HttpContext.RequestAborted);
  459. if (call is null)
  460. throw UserFriendlyException.SameMessage("无效通话,无法挂断");
  461. if (call.CallStatus == ECallStatus.Bye)
  462. throw UserFriendlyException.SameMessage("通话已结束");
  463. await _deviceManager.ClearVisitorAsync(call.ConversationId, HttpContext.RequestAborted);
  464. }
  465. /// <summary>
  466. /// 强拆去电
  467. /// </summary>
  468. /// <param name="request"></param>
  469. /// <returns></returns>
  470. [Permission(EPermission.ClearOuter)]
  471. [HttpPost("clear-outer")]
  472. public async Task ClearOuter([FromBody] ClearOuterRequest request)
  473. {
  474. //查询当前通话记录
  475. var call = await _callRepository.GetAsync(request.CallId, HttpContext.RequestAborted);
  476. if (call is null)
  477. throw UserFriendlyException.SameMessage("无效通话,无法挂断");
  478. if (call.CallStatus == ECallStatus.Bye)
  479. throw UserFriendlyException.SameMessage("通话已结束");
  480. await _deviceManager.ClearOuterAsync(call.ConversationId, HttpContext.RequestAborted);
  481. }
  482. #endregion
  483. #region 静音和取消静音
  484. /// <summary>
  485. /// 静音
  486. /// </summary>
  487. /// <returns></returns>
  488. [Permission(EPermission.Mute)]
  489. [HttpGet("mute")]
  490. public async Task Mute()
  491. {
  492. var work = _userCacheManager.GetWorkByUser(_sessionContext.RequiredUserId);
  493. if (work is null)
  494. throw UserFriendlyException.SameMessage("当前坐席暂未进行工作");
  495. await _deviceManager.MuteAsync(work.TelNo, HttpContext.RequestAborted);
  496. }
  497. /// <summary>
  498. /// 取消静音
  499. /// </summary>
  500. /// <returns></returns>
  501. [Permission(EPermission.UnMute)]
  502. [HttpGet("unmute")]
  503. public async Task UnMute()
  504. {
  505. var work = _userCacheManager.GetWorkByUser(_sessionContext.RequiredUserId);
  506. if (work is null)
  507. throw UserFriendlyException.SameMessage("当前坐席暂未进行工作");
  508. await _deviceManager.UnMuteAsync(work.TelNo, HttpContext.RequestAborted);
  509. }
  510. #endregion
  511. #endregion
  512. }
  513. }