DingTalkService.cs 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  1. // 大名科技(天津)有限公司 版权所有
  2. //
  3. // 此源代码遵循位于源代码树根目录中的 LICENSE 文件的许可证
  4. //
  5. // 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动
  6. //
  7. // 任何基于本项目二次开发而产生的一切法律纠纷和责任,均与作者无关
  8. namespace Admin.NET.Plugin.DingTalk.Service;
  9. /// <summary>
  10. /// 钉钉服务
  11. /// </summary>
  12. [ApiDescriptionSettings(DingTalkConst.GroupName, Module = "DingTalk", Order = 100)]
  13. public class DingTalkService : IDynamicApiController, IScoped
  14. {
  15. private readonly IDingTalkApi _dingTalkApi;
  16. private readonly DingTalkOptions _dingTalkOptions;
  17. private readonly SqlSugarRepository<DingTalkUser> _dingTalkUserRepo;
  18. private readonly SqlSugarRepository<SysUser> _sysUserRep;
  19. public DingTalkService(IDingTalkApi dingTalkApi,
  20. IOptions<DingTalkOptions> dingTalkOptions,
  21. SqlSugarRepository<DingTalkUser> dingTalkUserRepo,
  22. SqlSugarRepository<SysUser> sysUserRep)
  23. {
  24. _dingTalkApi = dingTalkApi;
  25. _dingTalkOptions = dingTalkOptions.Value;
  26. _dingTalkUserRepo = dingTalkUserRepo;
  27. _sysUserRep = sysUserRep;
  28. }
  29. /// <summary>
  30. /// 同步钉钉用户
  31. /// </summary>
  32. /// <returns></returns>
  33. [DisplayName("同步钉钉用户")]
  34. public async Task SyncDingTalkUser()
  35. {
  36. var param = new GetDingTalkTokenInput()
  37. {
  38. AppKey = _dingTalkOptions.ClientId,
  39. AppSecret = _dingTalkOptions.ClientSecret
  40. };
  41. var tokenRes = await _dingTalkApi.GetDingTalkToken(param);
  42. if (tokenRes.ErrCode != 0)
  43. throw Oops.Oh(tokenRes.ErrMsg);
  44. var offset = 0;
  45. while (offset >= 0)
  46. {
  47. // 获取用户Id列表
  48. var userIdsRes = await _dingTalkApi.GetDingTalkCurrentEmployeesList(tokenRes.AccessToken, new GetDingTalkCurrentEmployeesListInput
  49. {
  50. StatusList = "2,3,5,-1",
  51. Size = 50,
  52. Offset = offset
  53. });
  54. if (!userIdsRes.Success)
  55. throw Oops.Oh(userIdsRes.ErrMsg);
  56. // 根据用户Id获取花名册
  57. var rosterRes = await _dingTalkApi.GetDingTalkCurrentEmployeesRosterList(tokenRes.AccessToken, new GetDingTalkCurrentEmployeesRosterListInput()
  58. {
  59. UserIdList = string.Join(",", userIdsRes.Result.DataList),
  60. FieldFilterList = $"{DingTalkConst.NameField},{DingTalkConst.JobNumberField},{DingTalkConst.MobileField}",
  61. AgentId = _dingTalkOptions.AgentId
  62. });
  63. if (!rosterRes.Success)
  64. throw Oops.Oh(rosterRes.ErrMsg);
  65. // 判断新增还是更新
  66. var userIds = rosterRes.Result.Select(u => u.UserId).ToList();
  67. var uDingTalkUser = await _dingTalkUserRepo.AsQueryable()
  68. .Where(u => userIds.Contains(u.DingTalkUserId))
  69. .ToListAsync();
  70. var uUserIds = uDingTalkUser.Select(u => u.DingTalkUserId); // 需要更新的用户Id
  71. var iUserIds = userIds.Where(u => !uUserIds.Contains(u)); // 需要新增的用户Id
  72. // 保存钉钉用户
  73. var iUsers = rosterRes.Result
  74. .Where(u => iUserIds.Contains(u.UserId))
  75. .Select(u => new DingTalkUser
  76. {
  77. DingTalkUserId = u.UserId,
  78. Name = u.FieldDataList.Where(m => m.FieldCode == DingTalkConst.NameField).Select(m => m.FieldValueList.Select(n => n.Value).FirstOrDefault()).FirstOrDefault(),
  79. Mobile = u.FieldDataList.Where(m => m.FieldCode == DingTalkConst.MobileField).Select(m => m.FieldValueList.Select(n => n.Value).FirstOrDefault()).FirstOrDefault(),
  80. JobNumber = u.FieldDataList.Where(m => m.FieldCode == DingTalkConst.JobNumberField).Select(m => m.FieldValueList.Select(n => n.Value).FirstOrDefault()).FirstOrDefault(),
  81. }).ToList();
  82. if (iUsers.Count > 0)
  83. {
  84. await _dingTalkUserRepo.AsInsertable(iUsers).ExecuteCommandAsync();
  85. }
  86. // 更新钉钉用户
  87. var uUsers = rosterRes.Result
  88. .Where(u => uUserIds.Contains(u.UserId))
  89. .Select(u => new DingTalkUser
  90. {
  91. Id = uDingTalkUser.Where(m => m.DingTalkUserId == u.UserId).Select(m => m.Id).FirstOrDefault(),
  92. DingTalkUserId = u.UserId,
  93. Name = u.FieldDataList.Where(m => m.FieldCode == DingTalkConst.NameField).Select(m => m.FieldValueList.Select(n => n.Value).FirstOrDefault()).FirstOrDefault(),
  94. Mobile = u.FieldDataList.Where(m => m.FieldCode == DingTalkConst.MobileField).Select(m => m.FieldValueList.Select(n => n.Value).FirstOrDefault()).FirstOrDefault(),
  95. JobNumber = u.FieldDataList.Where(m => m.FieldCode == DingTalkConst.JobNumberField).Select(m => m.FieldValueList.Select(n => n.Value).FirstOrDefault()).FirstOrDefault(),
  96. }).ToList();
  97. if (uUsers.Count > 0)
  98. {
  99. await _dingTalkUserRepo.AsUpdateable(uUsers).UpdateColumns(u => new
  100. {
  101. u.DingTalkUserId,
  102. u.Name,
  103. u.Mobile,
  104. u.JobNumber,
  105. u.UpdateTime,
  106. u.UpdateUserName,
  107. u.UpdateUserId,
  108. }).ExecuteCommandAsync();
  109. }
  110. // 保存分页游标
  111. if (userIdsRes.Result.NextCursor == null)
  112. break;
  113. offset = (int)userIdsRes.Result.NextCursor;
  114. }
  115. var sysUser = await _sysUserRep.AsQueryable()
  116. .Select(u => new
  117. {
  118. u.Id,
  119. u.Account,
  120. u.Phone
  121. }).ToListAsync();
  122. var dingTalkUser = await _dingTalkUserRepo.AsQueryable()
  123. .Where(u => sysUser.Any(m => m.Account == u.JobNumber))
  124. .Select(u => new
  125. {
  126. u.Id,
  127. u.JobNumber,
  128. u.Mobile
  129. }).ToListAsync();
  130. // 更新钉钉用户中系统用户Id
  131. var uDingTalkUsers = dingTalkUser.Select(u => new DingTalkUser
  132. {
  133. Id = u.Id,
  134. SysUserId = sysUser.Where(m => m.Account == u.JobNumber).Select(m => m.Id).FirstOrDefault(),
  135. }).ToList();
  136. if (uDingTalkUsers.Count > 0)
  137. {
  138. await _dingTalkUserRepo.AsUpdateable(uDingTalkUsers).UpdateColumns(u => new
  139. {
  140. u.SysUserId,
  141. u.UpdateTime,
  142. u.UpdateUserName,
  143. u.UpdateUserId,
  144. }).ExecuteCommandAsync();
  145. }
  146. return;
  147. }
  148. /// <summary>
  149. /// 获取企业内部应用的access_token
  150. /// </summary>
  151. /// <param name="input"></param>
  152. /// <returns></returns>
  153. [DisplayName("获取企业内部应用的access_token")]
  154. public async Task<GetDingTalkTokenOutput> GetDingTalkToken([FromQuery] GetDingTalkTokenInput input)
  155. {
  156. return await _dingTalkApi.GetDingTalkToken(input);
  157. }
  158. /// <summary>
  159. /// 获取在职员工列表
  160. /// </summary>
  161. /// <param name="access_token"></param>
  162. /// <param name="input"></param>
  163. /// <returns></returns>
  164. [DisplayName("获取在职员工列表")]
  165. public async Task<DingTalkBaseResponse<GetDingTalkCurrentEmployeesListOutput>> GetDingTalkCurrentEmployeesList(string access_token, [Required] GetDingTalkCurrentEmployeesListInput input)
  166. {
  167. return await _dingTalkApi.GetDingTalkCurrentEmployeesList(access_token, input);
  168. }
  169. /// <summary>
  170. /// 获取员工花名册字段信息
  171. /// </summary>
  172. /// <param name="access_token"></param>
  173. /// <param name="input"></param>
  174. /// <returns></returns>
  175. [DisplayName("获取员工花名册字段信息")]
  176. public async Task<DingTalkBaseResponse<List<DingTalkEmpRosterFieldVo>>> GetDingTalkCurrentEmployeesRosterList(string access_token, [Required] GetDingTalkCurrentEmployeesRosterListInput input)
  177. {
  178. return await _dingTalkApi.GetDingTalkCurrentEmployeesRosterList(access_token, input);
  179. }
  180. /// <summary>
  181. /// 发送钉钉互动卡片
  182. /// </summary>
  183. /// <param name="token"></param>
  184. /// <param name="input"></param>
  185. /// <returns></returns>
  186. [DisplayName("给指定用户发送钉钉互动卡片")]
  187. public async Task<DingTalkSendInteractiveCardsOutput> DingTalkSendInteractiveCards(string token, DingTalkSendInteractiveCardsInput input)
  188. {
  189. return await _dingTalkApi.DingTalkSendInteractiveCards(token, input);
  190. }
  191. }