Explorar o código

更新钉钉花名册API

johnechoo hai 1 ano
pai
achega
7b09653a7b

+ 4 - 3
Admin.NET/Plugins/Admin.NET.Plugin.DingTalk/Configuration/DingTalk.json

@@ -9,9 +9,10 @@
     "Order": 90
   },
   "DingTalk": {
-    "AppId": "",
-    "AgentId": "",
+    "AppId": "xxxx",
+    "AgentId": 123,
     "ClientId": "xxxx", // 原 AppKey 和 SuiteKey
-    "ClientSecret": "xxxx" // 原 AppSecret 和 SuiteSecret
+    "ClientSecret": "xxxx", // 原 AppSecret 和 SuiteSecret
+    "CorpId": "xxxx"
   }
 }

+ 8 - 3
Admin.NET/Plugins/Admin.NET.Plugin.DingTalk/Const/DingTalkConst.cs

@@ -40,15 +40,20 @@ public class DingTalkConst
     /// <summary>
     /// 主部门Id
     /// </summary>
-    public const string DeptId = "sys00-mainDeptId";
+    public const string DeptIdField = "sys00-mainDeptId";
 
     /// <summary>
     /// 主部门
     /// </summary>
-    public const string Dept = "sys00-mainDept";
+    public const string DeptField = "sys00-mainDept";
 
     /// <summary>
     /// 职位
     /// </summary>
-    public const string Position = "sys00-position";
+    public const string PositionField = "sys00-position";
+
+    /// <summary>
+    /// 邮箱
+    /// </summary>
+    public const string EmailField = "sys00-email";
 }

+ 22 - 25
Admin.NET/Plugins/Admin.NET.Plugin.DingTalk/Job/SyncDingTalkUserJob.cs

@@ -5,7 +5,12 @@
 // 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
 
 using Admin.NET.Plugin.DingTalk;
+using Admin.NET.Plugin.DingTalk.RequestProxy.HRM;
+using Admin.NET.Plugin.DingTalk.RequestProxy.HRM.DTO;
+using Admin.NET.Plugin.DingTalk.Service;
+
 using Furion.Schedule;
+
 using Microsoft.Extensions.DependencyInjection;
 using Microsoft.Extensions.Logging;
 
@@ -19,13 +24,11 @@ namespace Admin.NET.Plugin.Job;
 public class SyncDingTalkUserJob : IJob
 {
     private readonly IServiceScopeFactory _scopeFactory;
-    private readonly IDingTalkApi _dingTalkApi;
     private readonly ILogger _logger;
 
-    public SyncDingTalkUserJob(IServiceScopeFactory scopeFactory, IDingTalkApi dingTalkApi, ILoggerFactory loggerFactory)
+    public SyncDingTalkUserJob(IServiceScopeFactory scopeFactory, ILoggerFactory loggerFactory)
     {
         _scopeFactory = scopeFactory;
-        _dingTalkApi = dingTalkApi;
         _logger = loggerFactory.CreateLogger(CommonConst.SysLogCategoryName);
     }
 
@@ -35,35 +38,29 @@ public class SyncDingTalkUserJob : IJob
         var sysUserRep = serviceScope.ServiceProvider.GetRequiredService<SqlSugarRepository<SysUser>>();
         var dingTalkUserRepo = serviceScope.ServiceProvider.GetRequiredService<SqlSugarRepository<DingTalkUser>>();
         var dingTalkOptions = serviceScope.ServiceProvider.GetRequiredService<IOptions<DingTalkOptions>>();
+        var dingTalkService = serviceScope.ServiceProvider.GetRequiredService<DingTalkService>();
+        var hrmRequest = serviceScope.ServiceProvider.GetRequiredService<HrmRequest>();
 
         // 获取Token
-        var tokenRes = await _dingTalkApi.GetDingTalkToken(dingTalkOptions.Value.ClientId, dingTalkOptions.Value.ClientSecret);
-        if (tokenRes.ErrCode != 0)
-            throw Oops.Oh(tokenRes.ErrMsg);
+        var token = await dingTalkService.GetDingTalkToken();
 
-        var dingTalkUserList = new List<DingTalkEmpRosterFieldVo>();
+        var dingTalkUserList = new List<RosterListResultDomain>();
         var offset = 0;
         while (offset >= 0)
         {
             // 获取用户Id列表
-            var userIdsRes = await _dingTalkApi.GetDingTalkCurrentEmployeesList(tokenRes.AccessToken, new GetDingTalkCurrentEmployeesListInput
-            {
-                StatusList = "2,3,5,-1",
-                Size = 50,
-                Offset = offset
-            });
+            var userIdsRes = await hrmRequest.EmployeeQueryOnJob(token,
+                new List<string> { "2", "3", "5", "-1" }, 50, offset);
             if (!userIdsRes.Success)
             {
                 _logger.LogError(userIdsRes.ErrMsg);
                 break;
             }
             // 根据用户Id获取花名册
-            var rosterRes = await _dingTalkApi.GetDingTalkCurrentEmployeesRosterList(tokenRes.AccessToken, new GetDingTalkCurrentEmployeesRosterListInput()
-            {
-                UserIdList = string.Join(",", userIdsRes.Result.DataList),
-                FieldFilterList = $"{DingTalkConst.NameField},{DingTalkConst.JobNumberField},{DingTalkConst.MobileField}",
-                AgentId = dingTalkOptions.Value.AgentId
-            });
+            var rosterRes = await hrmRequest.RosterListsQuery(token,
+                userIdsRes.Result.DataList,
+                new List<string> { DingTalkConst.NameField, DingTalkConst.JobNumberField, DingTalkConst.MobileField, DingTalkConst.DeptField, DingTalkConst.DeptIdField, DingTalkConst.PositionField },
+                dingTalkOptions.Value.AgentId);
             if (!rosterRes.Success)
             {
                 _logger.LogError(rosterRes.ErrMsg);
@@ -95,9 +92,9 @@ public class SyncDingTalkUserJob : IJob
             Name = res.FieldDataList.Where(u => u.FieldCode == DingTalkConst.NameField).Select(u => u.FieldValueList.Select(m => m.Value).FirstOrDefault()).FirstOrDefault(),
             Mobile = res.FieldDataList.Where(u => u.FieldCode == DingTalkConst.MobileField).Select(u => u.FieldValueList.Select(m => m.Value).FirstOrDefault()).FirstOrDefault(),
             JobNumber = res.FieldDataList.Where(u => u.FieldCode == DingTalkConst.JobNumberField).Select(u => u.FieldValueList.Select(m => m.Value).FirstOrDefault()).FirstOrDefault(),
-            DeptId = res.FieldDataList.Where(u => u.FieldCode == DingTalkConst.DeptId).Select(u => u.FieldValueList.Select(m => m.Value).FirstOrDefault()).FirstOrDefault(),
-            Dept = res.FieldDataList.Where(u => u.FieldCode == DingTalkConst.Dept).Select(u => u.FieldValueList.Select(m => m.Value).FirstOrDefault()).FirstOrDefault(),
-            Position = res.FieldDataList.Where(u => u.FieldCode == DingTalkConst.Position).Select(u => u.FieldValueList.Select(m => m.Value).FirstOrDefault()).FirstOrDefault(),
+            DeptId = res.FieldDataList.Where(u => u.FieldCode == DingTalkConst.DeptIdField).Select(u => u.FieldValueList.Select(m => m.Value).FirstOrDefault()).FirstOrDefault(),
+            Dept = res.FieldDataList.Where(u => u.FieldCode == DingTalkConst.DeptField).Select(u => u.FieldValueList.Select(m => m.Value).FirstOrDefault()).FirstOrDefault(),
+            Position = res.FieldDataList.Where(u => u.FieldCode == DingTalkConst.PositionField).Select(u => u.FieldValueList.Select(m => m.Value).FirstOrDefault()).FirstOrDefault(),
         }).ToList();
         if (iUser.Count > 0)
         {
@@ -112,9 +109,9 @@ public class SyncDingTalkUserJob : IJob
             Name = res.FieldDataList.Where(u => u.FieldCode == DingTalkConst.NameField).Select(u => u.FieldValueList.Select(m => m.Value).FirstOrDefault()).FirstOrDefault(),
             Mobile = res.FieldDataList.Where(u => u.FieldCode == DingTalkConst.MobileField).Select(u => u.FieldValueList.Select(m => m.Value).FirstOrDefault()).FirstOrDefault(),
             JobNumber = res.FieldDataList.Where(u => u.FieldCode == DingTalkConst.JobNumberField).Select(u => u.FieldValueList.Select(m => m.Value).FirstOrDefault()).FirstOrDefault(),
-            DeptId = res.FieldDataList.Where(u => u.FieldCode == DingTalkConst.DeptId).Select(u => u.FieldValueList.Select(m => m.Value).FirstOrDefault()).FirstOrDefault(),
-            Dept = res.FieldDataList.Where(u => u.FieldCode == DingTalkConst.Dept).Select(u => u.FieldValueList.Select(m => m.Value).FirstOrDefault()).FirstOrDefault(),
-            Position = res.FieldDataList.Where(u => u.FieldCode == DingTalkConst.Position).Select(u => u.FieldValueList.Select(m => m.Value).FirstOrDefault()).FirstOrDefault(),
+            DeptId = res.FieldDataList.Where(u => u.FieldCode == DingTalkConst.DeptIdField).Select(u => u.FieldValueList.Select(m => m.Value).FirstOrDefault()).FirstOrDefault(),
+            Dept = res.FieldDataList.Where(u => u.FieldCode == DingTalkConst.DeptField).Select(u => u.FieldValueList.Select(m => m.Value).FirstOrDefault()).FirstOrDefault(),
+            Position = res.FieldDataList.Where(u => u.FieldCode == DingTalkConst.PositionField).Select(u => u.FieldValueList.Select(m => m.Value).FirstOrDefault()).FirstOrDefault(),
         }).ToList();
         if (uUser.Count > 0)
         {

+ 6 - 1
Admin.NET/Plugins/Admin.NET.Plugin.DingTalk/Option/DingTalkOptions.cs

@@ -16,7 +16,7 @@ public sealed class DingTalkOptions : IConfigurableOptions
     /// <summary>
     /// AgentId
     /// </summary>
-    public string AgentId { get; set; }
+    public long AgentId { get; set; }
 
     /// <summary>
     /// 原 AppKey 和 SuiteKey
@@ -27,4 +27,9 @@ public sealed class DingTalkOptions : IConfigurableOptions
     /// 原 AppSecret 和 SuiteSecret
     /// </summary>
     public string ClientSecret { get; set; }
+
+    /// <summary>
+    /// 所属企业的CorpId
+    /// </summary>
+    public string CorpId { get; set; }
 }

+ 4 - 11
Admin.NET/Plugins/Admin.NET.Plugin.DingTalk/RequestProxy/Attendance/DTO/GetLeaveStatusResponse.cs

@@ -13,14 +13,8 @@ namespace Admin.NET.Plugin.DingTalk.RequestProxy.Attendance.DTO;
 /// <summary>
 /// 查询请假状态
 /// </summary>
-public class GetLeaveStatusResponse:DingtalkResponseErrorResultRequestId<GetLeaveStatusResult>
+public class GetLeaveStatusResponse : DingTalkResponseAll<GetLeaveStatusResult>
 {
-    /// <summary>
-    /// 请求是否成功。
-    /// </summary>
-    [JsonProperty("success")]
-    [JsonPropertyName("success")]
-    public bool Success { get; set; }
 }
 
 public class GetLeaveStatusResult
@@ -47,7 +41,7 @@ public class LeaveStatusDomain
     /// </summary>
     [JsonProperty("duration_unit")]
     [JsonPropertyName("duration_unit")]
-    public string DurationUnit {  get; set; }
+    public string DurationUnit { get; set; }
 
     /// <summary>
     /// 假期时长*100,例如用户请假时长为1天,该值就等于100。
@@ -68,13 +62,12 @@ public class LeaveStatusDomain
     /// </summary>
     [JsonProperty("start_time")]
     [JsonPropertyName("start_time")]
-    public long StartTime {  get; set; }
+    public long StartTime { get; set; }
 
     /// <summary>
     /// 用户ID。
     /// </summary>
     [JsonProperty("userid")]
     [JsonPropertyName("userid")]
-    public string UserId {  get; set; }
-
+    public string UserId { get; set; }
 }

+ 19 - 0
Admin.NET/Plugins/Admin.NET.Plugin.DingTalk/RequestProxy/BaseTypes/DingTalkResponseAll.cs

@@ -0,0 +1,19 @@
+// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
+//
+// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
+//
+// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
+
+using System.Text.Json.Serialization;
+
+namespace Admin.NET.Plugin.DingTalk.RequestProxy.BaseTypes;
+
+public class DingTalkResponseAll<T> : DingtalkResponseErrorResultRequestId<T>
+{
+    /// <summary>
+    /// 接口调用是否成功
+    /// </summary>
+    [JsonProperty("success")]
+    [JsonPropertyName("success")]
+    public virtual bool Success { get; set; }
+}

+ 22 - 0
Admin.NET/Plugins/Admin.NET.Plugin.DingTalk/RequestProxy/HRM/DTO/GetRosterMetaRequest.cs

@@ -0,0 +1,22 @@
+// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
+//
+// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
+//
+// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
+
+using System.Text.Json.Serialization;
+
+namespace Admin.NET.Plugin.DingTalk.RequestProxy.HRM.DTO;
+
+/// <summary>
+/// 获取花名册元数据
+/// </summary>
+public class GetRosterMetaRequest
+{
+    /// <summary>
+    /// 应用的AgentID
+    /// </summary>
+    [JsonProperty("agentid")]
+    [JsonPropertyName("agentid")]
+    public long AgentId { get; set; }
+}

+ 100 - 0
Admin.NET/Plugins/Admin.NET.Plugin.DingTalk/RequestProxy/HRM/DTO/GetRosterMetaResponse.cs

@@ -0,0 +1,100 @@
+// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
+//
+// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
+//
+// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
+
+using Admin.NET.Plugin.DingTalk.RequestProxy.BaseTypes;
+
+using System.Text.Json.Serialization;
+
+namespace Admin.NET.Plugin.DingTalk.RequestProxy.HRM.DTO;
+
+/// <summary>
+/// 获取花名册元数据
+/// </summary>
+public class GetRosterMetaResponse : DingtalkResponseErrorResultRequestId<List<RosterMetaResult>>
+{
+    /// <summary>
+    /// 接口调用是否成功
+    /// </summary>
+    [JsonProperty("success")]
+    [JsonPropertyName("success")]
+    public virtual bool Success { get; set; }
+}
+
+public class RosterMetaResult
+{
+    /// <summary>
+    /// 分组是否支持明细
+    /// </summary>
+    [JsonProperty("detail")]
+    [JsonPropertyName("detail")]
+    public bool Detail { get; set; }
+
+    /// <summary>
+    /// 花名册分组内字段定义
+    /// </summary>
+    [JsonProperty("field_meta_info_list")]
+    [JsonPropertyName("field_meta_info_list")]
+    public List<RosterMetaFieldInfo> FieldMetaInfoList { get; set; }
+
+    /// <summary>
+    /// 分组标识
+    /// </summary>
+    [JsonProperty("group_id")]
+    [JsonPropertyName("group_id")]
+    public string GroupId { get; set; }
+
+    /// <summary>
+    /// 分组名称
+    /// </summary>
+    [JsonProperty("group_name")]
+    [JsonPropertyName("group_name")]
+    public string GroupName { get; set; }
+}
+
+public class RosterMetaFieldInfo
+{
+    /// <summary>
+    /// 是否衍生字段,例如司龄、年龄等系统计算的字段
+    /// </summary>
+    [JsonProperty("derived")]
+    [JsonPropertyName("derived")]
+    public bool Derived { get; set; }
+
+    /// <summary>
+    /// 字段标识
+    /// </summary>
+    [JsonProperty("field_code")]
+    [JsonPropertyName("field_code")]
+    public string FieldCode { get; set; }
+
+    /// <summary>
+    /// 字段名称
+    /// </summary>
+    [JsonProperty("field_name")]
+    [JsonPropertyName("field_name")]
+    public string FieldName { get; set; }
+
+    /// <summary>
+    /// 可用选项的序列化结果
+    /// </summary>
+    [JsonProperty("option_text")]
+    [JsonPropertyName("option_text")]
+    public string? OptionText { get; set; }
+}
+
+/// <summary>
+/// 可用选项的反序列化类型
+/// </summary>
+public class OptionTextDomain
+{
+    [JsonProperty("label")]
+    [JsonPropertyName("label")]
+    public string Label { get; set; }
+
+    [JsonProperty("value")]
+    [JsonPropertyName("value")]
+    public string Value { get; set; }
+}

+ 20 - 31
Admin.NET/Plugins/Admin.NET.Plugin.DingTalk/RequestProxy/HRM/DTO/RosterListsQueryResponse.cs

@@ -4,6 +4,8 @@
 //
 // 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
 
+using Admin.NET.Plugin.DingTalk.RequestProxy.BaseTypes;
+
 using System.Text.Json.Serialization;
 
 namespace Admin.NET.Plugin.DingTalk.RequestProxy.HRM.DTO;
@@ -11,44 +13,31 @@ namespace Admin.NET.Plugin.DingTalk.RequestProxy.HRM.DTO;
 /// <summary>
 /// 获取员工花名册字段信息
 /// </summary>
-public class RosterListsQueryResponse
+public class RosterListsQueryResponse : DingTalkResponseAll<RosterListResultDomain[]>
 {
-    /// <summary>
-    /// 结果列表
-    /// </summary>
-    [JsonProperty("result")]
-    [JsonPropertyName("result")]
-    public List<ResultDomain> Result { get; set; }
 }
 
-public class ResultDomain
+public class RosterListResultDomain
 {
     /// <summary>
     /// 企业的corpId
     /// </summary>
-    [JsonProperty("corpId")]
-    [JsonPropertyName("corpId")]
+    [JsonProperty("corp_id")]
+    [JsonPropertyName("corp_id")]
     public string CorpId { get; set; }
 
     /// <summary>
     /// 员工的userId
     /// </summary>
-    [JsonProperty("userId")]
-    [JsonPropertyName("userId")]
+    [JsonProperty("userid")]
+    [JsonPropertyName("userid")]
     public string UserId { get; set; }
 
-    /// <summary>
-    /// 暂未开放
-    /// </summary>
-    [JsonProperty("unionId")]
-    [JsonPropertyName("unionId")]
-    public string UnionId { get; set; }
-
     /// <summary>
     /// 返回的字段信息列表
     /// </summary>
-    [JsonProperty("fieldDataList")]
-    [JsonPropertyName("fieldDataList")]
+    [JsonProperty("field_data_list")]
+    [JsonPropertyName("field_data_list")]
     public List<FieldDataDomain> FieldDataList { get; set; }
 }
 
@@ -57,29 +46,29 @@ public class FieldDataDomain
     /// <summary>
     /// 字段标识
     /// </summary>
-    [JsonProperty("fieldCode")]
-    [JsonPropertyName("fieldCode")]
+    [JsonProperty("field_code")]
+    [JsonPropertyName("field_code")]
     public string FieldCode { get; set; }
 
     /// <summary>
     /// 字段名称
     /// </summary>
-    [JsonProperty("fieldName")]
-    [JsonPropertyName("fieldName")]
+    [JsonProperty("field_name")]
+    [JsonPropertyName("field_name")]
     public string FieldName { get; set; }
 
     /// <summary>
     /// 分组标识
     /// </summary>
-    [JsonProperty("groupId")]
-    [JsonPropertyName("groupId")]
+    [JsonProperty("group_id")]
+    [JsonPropertyName("group_id")]
     public string GroupId { get; set; }
 
     /// <summary>
     /// 字段值列表
     /// </summary>
-    [JsonProperty("fieldValueList")]
-    [JsonPropertyName("fieldValueList")]
+    [JsonProperty("field_value_list")]
+    [JsonPropertyName("field_value_list")]
     public List<FieldValueDomain> FieldValueList { get; set; }
 }
 
@@ -102,7 +91,7 @@ public class FieldValueDomain
     /// <summary>
     /// 第几条的明细标识,下标从0开始
     /// </summary>
-    [JsonProperty("itemIndex")]
-    [JsonPropertyName("itemIndex")]
+    [JsonProperty("item_index")]
+    [JsonPropertyName("item_index")]
     public int ItemIndex { get; set; }
 }

+ 13 - 1
Admin.NET/Plugins/Admin.NET.Plugin.DingTalk/RequestProxy/HRM/HrmRequest.cs

@@ -23,7 +23,7 @@ public class HrmRequest : IScoped
     /// 获取在职员工列表
     /// </summary>
     /// <param name="accessToken"></param>
-    /// <param name="statusList">在职员工状态筛选,可以查询多个状态。不同状态之间使用英文逗号分隔。2:试用期、3:正式、5:待离职、-1:无状态</param>
+    /// <param name="statusList">在职员工状态筛选,可以查询多个状态。2:试用期、3:正式、5:待离职、-1:无状态</param>
     /// <param name="size">分页大小,最大50</param>
     /// <param name="offset">分页游标,从0开始。根据返回结果里的next_cursor是否为空来判断是否还有下一页,且再次调用时offset设置成next_cursor的值</param>
     /// <returns></returns>
@@ -56,4 +56,16 @@ public class HrmRequest : IScoped
         });
         return resStr.ToObject<RosterListsQueryResponse>();
     }
+
+    /// <summary>
+    /// 获取花名册元数据
+    /// </summary>
+    /// <param name="accessToken"></param>
+    /// <param name="agentId"></param>
+    /// <returns></returns>
+    public async Task<GetRosterMetaResponse> GetRosterMeta(string accessToken, long agentId)
+    {
+        var resStr = await _request.GetRosterMeta(accessToken, new GetRosterMetaRequest { AgentId = agentId });
+        return resStr.ToObject<GetRosterMetaResponse>();
+    }
 }

+ 4 - 1
Admin.NET/Plugins/Admin.NET.Plugin.DingTalk/RequestProxy/HRM/IHrmRequestProxy.cs

@@ -14,6 +14,9 @@ public interface IHrmRequestProxy : IHttpDispatchProxy
     Task<string> EmployeeQueryonjob([QueryString("access_token")] string accessToken, [Body] DTO.EmployeeQueryOnJobRequest request);
 
     [Post("https://oapi.dingtalk.com/topapi/smartwork/hrm/employee/v2/list")]
-    Task<string> RosterListsQuery([Headers("x-acs-dingtalk-access-token")] string accessToken,
+    Task<string> RosterListsQuery([QueryString("access_token")] string accessToken,
     [Body] RosterListsQueryRequest request);
+
+    [Post("https://oapi.dingtalk.com/topapi/smartwork/hrm/roster/meta/get")]
+    Task<string> GetRosterMeta([QueryString("access_token")] string accessToken, [Body] GetRosterMetaRequest request);
 }

+ 9 - 1
Admin.NET/Plugins/Admin.NET.Plugin.DingTalk/Service/DingTalkService.cs

@@ -38,11 +38,19 @@ public class DingTalkService : IDynamicApiController, IScoped
         _accessTokenKey = DingTalkConst.AccessTokenKeyPrefix + _dingTalkOptions.ClientId;
     }
 
+    [HttpGet, DisplayName("获取花名册元数据")]
+    public async Task<GetRosterMetaResponse> GetRosterMeta()
+    {
+        var token = await GetDingTalkToken();
+        var res = await _hrmRequest.GetRosterMeta(token, _dingTalkOptions.AgentId);
+        return res;
+    }
+
     /// <summary>
     /// 获取企业内部应用的access_token
     /// </summary>
     /// <returns></returns>
-    [HttpGet,DisplayName("获取企业内部应用的access_token")]
+    [HttpGet, DisplayName("获取企业内部应用的access_token")]
     public async Task<string> GetDingTalkToken()
     {
         var token = _sysCacheService.Get<string>(_accessTokenKey);

+ 1 - 1
Admin.NET/Plugins/Admin.NET.Plugin.DingTalk/Service/Dto/GetDingTalkCurrentEmployeesRosterListInput.cs

@@ -29,5 +29,5 @@ public class GetDingTalkCurrentEmployeesRosterListInput
     /// </summary>
     [JsonProperty("agentid")]
     [JsonPropertyName("agentid")]
-    public string AgentId { get; set; }
+    public long AgentId { get; set; }
 }

+ 2 - 2
Admin.NET/Plugins/Admin.NET.Plugin.DingTalk/Service/IDingTalkApi.cs

@@ -24,7 +24,7 @@ public interface IDingTalkApi : IHttpDispatchProxy
     /// <param name="input"></param>
     /// <returns></returns>
     [Post("https://oapi.dingtalk.com/topapi/smartwork/hrm/employee/queryonjob")]
-    Task<DingTalkBaseResponse<GetDingTalkCurrentEmployeesListOutput>> GetDingTalkCurrentEmployeesList([QueryString] string accessToken,
+    Task<DingTalkBaseResponse<GetDingTalkCurrentEmployeesListOutput>> GetDingTalkCurrentEmployeesList([QueryString("access_token")] string accessToken,
         [Body, Required] GetDingTalkCurrentEmployeesListInput input);
 
     /// <summary>
@@ -34,7 +34,7 @@ public interface IDingTalkApi : IHttpDispatchProxy
     /// <param name="input"></param>
     /// <returns></returns>
     [Post("https://oapi.dingtalk.com/topapi/smartwork/hrm/employee/v2/list")]
-    Task<DingTalkBaseResponse<List<DingTalkEmpRosterFieldVo>>> GetDingTalkCurrentEmployeesRosterList([QueryString] string accessToken,
+    Task<DingTalkBaseResponse<List<DingTalkEmpRosterFieldVo>>> GetDingTalkCurrentEmployeesRosterList([QueryString("access_token")] string accessToken,
         [Body, Required] GetDingTalkCurrentEmployeesRosterListInput input);
 
     /// <summary>