1
+ // 大名科技(天津)有限公司 版权所有
2
+ //
3
+ // 此源代码遵循位于源代码树根目录中的 LICENSE 文件的许可证
4
+ //
5
+ // 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动
6
+ //
7
+ // 任何基于本项目二次开发而产生的一切法律纠纷和责任,均与作者无关
8
+
9
+ using Admin . NET . Plugin . DingTalk ;
10
+ using Furion . Schedule ;
11
+ using Microsoft . Extensions . DependencyInjection ;
12
+ using Microsoft . Extensions . Logging ;
13
+
14
+ namespace Admin . NET . Plugin . Job ;
15
+
16
+
17
+ /// <summary>
18
+ /// 同步钉钉用户job
19
+ /// </summary>
20
+ [ JobDetail ( "SyncDingTalkUserJob" , Description = "同步钉钉用户" , GroupName = "default" , Concurrent = false ) ]
21
+ [ Daily ( TriggerId = "SyncDingTalkUserTrigger" , Description = "同步钉钉用户" ) ]
22
+ public class SyncDingTalkUserJob : IJob
23
+ {
24
+ private readonly IServiceScopeFactory _scopeFactory ;
25
+ private readonly IDingTalkApi _dingTalkApi ;
26
+ private readonly ILogger _logger ;
27
+ public SyncDingTalkUserJob ( IServiceScopeFactory scopeFactory , IDingTalkApi dingTalkApi , ILoggerFactory loggerFactory )
28
+ {
29
+ _scopeFactory = scopeFactory ;
30
+ _dingTalkApi = dingTalkApi ;
31
+ _logger = loggerFactory . CreateLogger ( "System.Logging.LoggingMonitor" ) ;
32
+ }
33
+
34
+ public async Task ExecuteAsync ( JobExecutingContext context , CancellationToken stoppingToken )
35
+ {
36
+ using var serviceScope = _scopeFactory . CreateScope ( ) ;
37
+ var _sysUserRep = serviceScope . ServiceProvider . GetRequiredService < SqlSugarRepository < SysUser > > ( ) ;
38
+ var _dingTalkUserRepo = serviceScope . ServiceProvider . GetRequiredService < SqlSugarRepository < DingTalkUser > > ( ) ;
39
+ var _dingTalkOptions = serviceScope . ServiceProvider . GetRequiredService < IOptions < DingTalkOptions > > ( ) ;
40
+ // 获取token
41
+ var param = new GetDingTalkTokenInput ( )
42
+ {
43
+ AppKey = _dingTalkOptions . Value . ClientId ,
44
+ AppSecret = _dingTalkOptions . Value . ClientSecret
45
+ } ;
46
+ var tokenRes = await _dingTalkApi . GetDingTalkToken ( param ) ;
47
+ if ( tokenRes . ErrCode != 0 )
48
+ {
49
+ throw Oops . Oh ( tokenRes . ErrMsg ) ;
50
+ }
51
+ var dingTalkUserList = new List < DingTalkEmpRosterFieldVo > ( ) ;
52
+ var offset = 0 ;
53
+ while ( offset >= 0 )
54
+ {
55
+ // 获取用户id列表
56
+ var userIdsRes = await _dingTalkApi . GetDingTalkCurrentEmployeesList ( tokenRes . AccessToken , new GetDingTalkCurrentEmployeesListInput
57
+ {
58
+ StatusList = "2,3,5,-1" ,
59
+ Size = 50 ,
60
+ Offset = offset
61
+ } ) ;
62
+ if ( ! userIdsRes . Success )
63
+ {
64
+ _logger . LogError ( userIdsRes . ErrMsg ) ;
65
+ break ;
66
+ }
67
+ // 根据用户id获取花名册
68
+ var rosterRes = await _dingTalkApi . GetDingTalkCurrentEmployeesRosterList ( tokenRes . AccessToken , new GetDingTalkCurrentEmployeesRosterListInput ( )
69
+ {
70
+ UserIdList = string . Join ( "," , userIdsRes . Result . DataList ) ,
71
+ FieldFilterList = $ "{ DingTalkConst . NameField } ,{ DingTalkConst . JobNumberField } ,{ DingTalkConst . MobileField } ",
72
+ AgentId = _dingTalkOptions . Value . AgentId
73
+ } ) ;
74
+ if ( ! rosterRes . Success )
75
+ {
76
+ _logger . LogError ( rosterRes . ErrMsg ) ;
77
+ break ;
78
+ }
79
+ dingTalkUserList . AddRange ( rosterRes . Result ) ;
80
+ if ( userIdsRes . Result . NextCursor == null )
81
+ {
82
+ break ;
83
+ }
84
+ // 保存分页游标
85
+ offset = ( int ) userIdsRes . Result . NextCursor ;
86
+ }
87
+
88
+ // 判断新增还是更新
89
+ var sysDingTalkUserIdList = await _dingTalkUserRepo . AsQueryable ( )
90
+ . Select ( x => new
91
+ {
92
+ x . Id ,
93
+ x . DingTalkUserId
94
+ } )
95
+ . ToListAsync ( ) ;
96
+ // 需要更新的用户id
97
+ var uDingTalkUser = dingTalkUserList . Where ( x => sysDingTalkUserIdList . Any ( d => d . DingTalkUserId == x . UserId ) ) ;
98
+ // 需要新增的用户id
99
+ var iDingTalkUser = dingTalkUserList . Where ( u => ! sysDingTalkUserIdList . Any ( d => d . DingTalkUserId == u . UserId ) ) ;
100
+ #region 新增钉钉用户
101
+ var iUser = iDingTalkUser
102
+ . Select ( res => new SysDingTalkUser
103
+ {
104
+ DingTalkUserId = res . UserId ,
105
+ Name = res . FieldDataList
106
+ . Where ( f => f . FieldCode == DingTalkFieldConst . NameField )
107
+ . Select ( f => f . FieldValueList . Select ( v => v . Value ) . FirstOrDefault ( ) )
108
+ . FirstOrDefault ( ) ,
109
+ Mobile = res . FieldDataList
110
+ . Where ( f => f . FieldCode == DingTalkFieldConst . MobileField )
111
+ . Select ( f => f . FieldValueList . Select ( v => v . Value ) . FirstOrDefault ( ) )
112
+ . FirstOrDefault ( ) ,
113
+ JobNumber = res . FieldDataList
114
+ . Where ( f => f . FieldCode == DingTalkFieldConst . JobNumberField )
115
+ . Select ( f => f . FieldValueList . Select ( v => v . Value ) . FirstOrDefault ( ) )
116
+ . FirstOrDefault ( ) ,
117
+ } ) . ToList ( ) ;
118
+ if ( iUser . Count > 0 )
119
+ {
120
+ var iUserRes = await _dingTalkUserRepo . CopyNew ( ) . AsInsertable ( iUser ) . ExecuteCommandAsync ( ) ;
121
+ if ( iUserRes <= 0 )
122
+ {
123
+ throw Oops . Oh ( "保存钉钉用户错误" ) ;
124
+ }
125
+ }
126
+ #endregion
127
+
128
+ #region 更新钉钉用户
129
+ var uUser = uDingTalkUser
130
+ . Select ( res => new SysDingTalkUser
131
+ {
132
+ Id = sysDingTalkUserIdList . Where ( d => d . DingTalkUserId == res . UserId ) . Select ( d => d . Id ) . FirstOrDefault ( ) ,
133
+ DingTalkUserId = res . UserId ,
134
+ Name = res . FieldDataList
135
+ . Where ( f => f . FieldCode == DingTalkFieldConst . NameField )
136
+ . Select ( f => f . FieldValueList . Select ( v => v . Value ) . FirstOrDefault ( ) )
137
+ . FirstOrDefault ( ) ,
138
+ Mobile = res . FieldDataList
139
+ . Where ( f => f . FieldCode == DingTalkFieldConst . MobileField )
140
+ . Select ( f => f . FieldValueList . Select ( v => v . Value ) . FirstOrDefault ( ) )
141
+ . FirstOrDefault ( ) ,
142
+ JobNumber = res . FieldDataList
143
+ . Where ( f => f . FieldCode == DingTalkFieldConst . JobNumberField )
144
+ . Select ( f => f . FieldValueList . Select ( v => v . Value ) . FirstOrDefault ( ) )
145
+ . FirstOrDefault ( ) ,
146
+ } ) . ToList ( ) ;
147
+ if ( uUser . Count > 0 )
148
+ {
149
+ var uUserRes = await _dingTalkUserRepo . CopyNew ( ) . AsUpdateable ( uUser )
150
+ . UpdateColumns ( d => new
151
+ {
152
+ d . DingTalkUserId ,
153
+ d . Name ,
154
+ d . Mobile ,
155
+ d . JobNumber ,
156
+ d . UpdateTime ,
157
+ d . UpdateUserName ,
158
+ d . UpdateUserId ,
159
+ } ) . ExecuteCommandAsync ( ) ;
160
+ if ( uUserRes <= 0 )
161
+ {
162
+ throw Oops . Oh ( "更新钉钉用户错误" ) ;
163
+ }
164
+ }
165
+ #endregion
166
+ // 通过系统用户账号(工号),更新钉钉用户表里面的系统用户id
167
+ var sysUser = await _sysUserRep . AsQueryable ( ) . Select ( x => new
168
+ {
169
+ x . Id ,
170
+ x . Account
171
+ } ) . ToListAsync ( ) ;
172
+ var sysDingTalkUser = await _dingTalkUserRepo . AsQueryable ( )
173
+ . Where ( d => sysUser . Any ( u => u . Account == d . JobNumber ) )
174
+ . Select ( x => new
175
+ {
176
+ x . Id ,
177
+ x . JobNumber ,
178
+ x . Mobile
179
+ } ) . ToListAsync ( ) ;
180
+ var uSysDingTalkUser = sysDingTalkUser . Select ( d => new DingTalkUser
181
+ {
182
+ Id = d . Id ,
183
+ SysUserId = sysUser . Where ( u => u . Account == d . JobNumber ) . Select ( u => u . Id ) . FirstOrDefault ( ) ,
184
+ } ) . ToList ( ) ;
185
+ var uSysDingTalkUserRes = await _dingTalkUserRepo . CopyNew ( ) . AsUpdateable ( uSysDingTalkUser )
186
+ . UpdateColumns ( d => new
187
+ {
188
+ d . SysUserId ,
189
+ d . UpdateTime ,
190
+ d . UpdateUserName ,
191
+ d . UpdateUserId ,
192
+ } ) . ExecuteCommandAsync ( ) ;
193
+ if ( uSysDingTalkUserRes <= 0 )
194
+ {
195
+ _logger . LogError ( "同步钉钉用户错误" ) ;
196
+ return ;
197
+ }
198
+ var originColor = Console . ForegroundColor ;
199
+ Console . ForegroundColor = ConsoleColor . Yellow ;
200
+ Console . WriteLine ( "【" + DateTime . Now + "】同步钉钉用户" ) ;
201
+ Console . ForegroundColor = originColor ;
202
+ }
203
+
204
+ }
0 commit comments