using Azure.Cosmos; using System; using System.Collections.Generic; using System.Threading.Tasks; using TEAMModelOS.SDK.DI; using TEAMModelOS.SDK.Extension; using TEAMModelOS.SDK.Models.Cosmos.Common; using HTEXLib.COMM.Helpers; using System.Linq; using System.Text; using System.Text.Json; using TEAMModelOS.Models; using Azure.Messaging.ServiceBus; using Microsoft.Extensions.Configuration; using TEAMModelOS.SDK.Models.Service; using System.Text.RegularExpressions; using TEAMModelOS.SDK.Models; using System.Net.Http; using DocumentFormat.OpenXml.Wordprocessing; using static TEAMModelOS.SDK.GroupListService; namespace TEAMModelOS.SDK { public class GroupListService { public static async Task DeleteGrouplistEvent(string id , string code,string tbname ,CosmosClient client, IConfiguration _configuration, AzureServiceBusFactory _serviceBus) { GroupChange change = new GroupChange(); GroupList groupList = await client.GetContainer(Constant.TEAMModelOS, tbname).ReadItemAsync(id.ToString(), new PartitionKey(code)); var tleave = groupList.members.FindAll(x => x.type == 1); if (tleave.IsNotEmpty()) { if (groupList.type.Equals("research") || groupList.type.Equals("yxtrain")) { change.tchleave.AddRange(tleave); } else { change.tmdleave.AddRange(tleave); } } var sleave = groupList.members.FindAll(x => x.type == 2); if (sleave.IsNotEmpty()) { change.stuleave.AddRange(sleave); } change.listid = groupList.id; change.scope = groupList.scope; change.originCode = $"{code}"; change.school = groupList.school; change.creatorId = groupList.creatorId; change.type = groupList.type; change.status = "delete"; if (change.tmdleave.IsNotEmpty() || change.tchleave.IsNotEmpty() || change.stuleave.IsNotEmpty()) { var messageChange = new ServiceBusMessage(change.ToJsonString()); messageChange.ApplicationProperties.Add("name", "GroupChange"); var ActiveTask = _configuration.GetValue("Azure:ServiceBus:ActiveTask"); await _serviceBus.GetServiceBusClient().SendMessageAsync(ActiveTask, messageChange); } await client.GetContainer(Constant.TEAMModelOS, tbname).DeleteItemStreamAsync(id.ToString(), new PartitionKey(code)); } /// /// 查询名单成员所在的名单列表, /// /// /// /// /// 成员id /// 成员类型 /// 成员所在的学校 ,可为空 /// 过滤名单的类型集合,不传则是全部 /// 毕业类型0在校,1毕业 , -1查全部。 /// public static async Task> GetMemberInGroupList(CoreAPIHttpService _coreAPIHttpService, CosmosClient client, DingDing _dingDing, string memberId, int memberType, string school,List groupTypes,int graduate =-1) { List groupLists = new List(); if (groupTypes.IsEmpty() || groupTypes.Contains("class")) { if (!string.IsNullOrWhiteSpace(school) && memberType == 2) { Student student = null; try { student = await client.GetContainer(Constant.TEAMModelOS, Constant.Student).ReadItemAsync(memberId, new PartitionKey($"Base-{school}")); } catch (CosmosException ex) when (ex.Status == 404) { return null; } if (!string.IsNullOrWhiteSpace(student.classId)) { try { Class clazz = await client.GetContainer(Constant.TEAMModelOS, Constant.School).ReadItemAsync(student.classId, new PartitionKey($"Class-{school}")); GroupListGrp groupList = new GroupListGrp { id = clazz.id, code = $"GroupList-{clazz.school}", name = clazz.name, periodId = clazz.periodId, pk = "GroupList", expire=0, year = clazz.year, school = clazz.school, scope = "school", type = "class", no = clazz.no, leader = clazz.teacher?.id, graduate=clazz.graduate, grades= new HashSet() { clazz.year} }; //graduate传入的状态>=0 表示指定状态查询,且传入的状态与数据库的状态一致。 if (graduate >= 0 ) { if (groupList.graduate == graduate) { groupLists.Add(groupList); } } //全部。 else if(graduate == -1) { groupLists.Add(groupList); } } catch (CosmosException ex) when (ex.Status == 404) { } } } } string SummarySql = " c.id,c.code,c.name,c.no,c.periodId,c.scope,c.school,c.creatorId,c.type,c.year,c.tcount,c.scount,c.leader ,c.froms ,c.joinLock ,c.review,c.limitCount ,c.expire,c.qrcodeExpire ,c.qrcodeDays ,c.grades "; if (groupTypes.IsEmpty() || groupTypes.Contains("teach")) { //教学班 string teachsql=""; if (!string.IsNullOrWhiteSpace(school) && memberType == 2) { teachsql= $"SELECT distinct {SummarySql} FROM c join m in c.members where c.type='teach' and m.id='{memberId}' and m.code='{school}' and m.type=2 "; } if (memberType == 1) { teachsql=$"SELECT distinct {SummarySql} FROM c join m in c.members where c.type='teach' and m.id='{memberId}' and m.type=1 "; } await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "School"). GetItemQueryIterator(queryText: teachsql, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"GroupList-{school}") })) { HashSet groupName = item.members.Where(x => !string.IsNullOrEmpty(x.groupName)).Select(y => y.groupName).ToHashSet(); groupLists.Add(new GroupListGrp(item, groupName)); } //个人名单 await foreach (var item in client.GetContainer(Constant.TEAMModelOS, Constant.Teacher). GetItemQueryIterator(queryText: teachsql, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"GroupList") })) { HashSet groupName = item.members.Where(x => !string.IsNullOrEmpty(x.groupName)).Select(y => y.groupName).ToHashSet(); groupLists.Add(new GroupListGrp(item, groupName)); } } if (!string.IsNullOrWhiteSpace(school) && (groupTypes.IsEmpty() || groupTypes.Contains("research"))) { //教研组 string teachsql = $"SELECT distinct {SummarySql} FROM c join m in c.members where c.type='research' and m.id='{memberId}' and m.type=1 "; await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "School"). GetItemQueryIterator(queryText: teachsql, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"GroupList-{school}") })) { HashSet groupName = item.members.Where(x => !string.IsNullOrEmpty(x.groupName)).Select(y => y.groupName).ToHashSet(); groupLists.Add(new GroupListGrp(item, groupName)); } } if (!string.IsNullOrWhiteSpace(school) && (groupTypes.IsEmpty() || groupTypes.Contains("yxtrain"))) { //研修名单 string teachsql = $"SELECT distinct {SummarySql} FROM c join m in c.members where c.type='yxtrain' and m.id='{memberId}' and m.type=1 "; await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "School"). GetItemQueryIterator(queryText: teachsql, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"GroupList-{school}") })) { HashSet groupName = item.members.Where(x => !string.IsNullOrEmpty(x.groupName)).Select(y => y.groupName).ToHashSet(); groupLists.Add(new GroupListGrp(item, groupName)); } } return groupLists; } /// ///-1状态异常,0加入成功, 1加入学生或醍摩豆ID为空,2重复加入 ,3不允许跨校加入名单, 4表示个人名单未开放加入,状态=5 ,人数已满。状态=6 ,需要审核通过再加入。状态7 二维码设置已经过期 /// /// /// /// /// /// /// public static async Task<(int status, GroupList stuList,Member member)> CodeJoinList(CosmosClient client,AzureRedisFactory _azureRedis, string _stuListNo, string userid, int type, string school,int year,string name ,string picture,string lang,string courseId= null) { var queryNo = $"SELECT value(c) FROM c where c.no ='{_stuListNo}'"; (int status, GroupList stuList,Member member) data = (-1, null,null); if (!string.IsNullOrEmpty(school)) { await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "School").GetItemQueryIterator(queryText: queryNo, requestOptions: new QueryRequestOptions() { PartitionKey = new Azure.Cosmos.PartitionKey($"GroupList-{school}") })) { data = JoinList(item, userid, type, school,year); break; } } await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "Teacher").GetItemQueryIterator(queryText: queryNo, requestOptions: new QueryRequestOptions() { PartitionKey = new Azure.Cosmos.PartitionKey($"GroupList") })) { if (item.joinLock == 0) { //状态=4 表示未开放加入。 return (4, item, null) ; } if (item.review ==1) { //状态=6 ,人数已满,需要审核通过再加入。 long now = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(); if (now>item.qrcodeExpire) { //二维码设置已经过期,只有需要审核的时候才检查二维码过期问题,目的是为了未正式加入人员的缓存 return (7, item, null); } else { GroupWaitingList waitingList = new GroupWaitingList { stuListNo=_stuListNo, userid=userid, type=type, school= school, year = year, groupId = item.id, groupScope=item.scope, name = name, picture = picture, lang = lang, qrcodeExpire=item.qrcodeExpire, groupName= item.name, applyTime=now }; string sql = "select value c from c join b in c.schedules where b.groupId='60f92012-72cf-4d5c-a66a-552678303fad'"; string key = $"GroupList:GroupWaitingList:{item.scope}:{item.id}"; string filed = !string.IsNullOrWhiteSpace(school) ? $"{school}_{userid}" : userid; await _azureRedis.GetRedisClient(8).HashSetAsync(key, filed, waitingList.ToJsonString()); await _azureRedis.GetRedisClient(8).KeyExpireAsync(key, expiry: DateTimeOffset.FromUnixTimeMilliseconds(item.qrcodeExpire).UtcDateTime); string stuKey = !string.IsNullOrWhiteSpace(school) ? $"GroupList:StudentWaitinglist:{school}_{userid}" :$"GroupList:StudentWaitinglist:{userid}" ; string sutFiled = $"{item.scope}:{item.id}"; await _azureRedis.GetRedisClient(8).HashSetAsync(stuKey, sutFiled, waitingList.ToJsonString()); //三十天都不登录,则不需要查看申请清单,30*24=720 await _azureRedis.GetRedisClient(8).KeyExpireAsync(stuKey, new TimeSpan(720 , 0, 0)); return (6, item, null); } } if (item.members!=null &&item.limitCount>0 && item.members.Count>=item.limitCount) { //状态=5 ,人数已满 return (5, item, null); } data = JoinList(item, userid, type, school,year); //TODO 需要考虑已经通过别的途径加入名单,但是缓存数据仍记录数据的问题。 还要考虑手动加入过的。或者在获取名未加入名单成员的临时缓存数据的时候过滤已经加入的。 break; } return data; } /// /// 加入名单等候列表 /// public class GroupWaitingList { /// /// /// public string stuListNo { get; set; } public string userid { get; set; } //学生类型,1醍摩豆id,2 校内账号 public int type { get; set; } public string school { get; set; } public int year { get; set; } public string groupId { get; set; } public string groupScope { get; set; } public string name { get; set; } public string picture { get; set; } public string lang { get; set; } public long qrcodeExpire { get; set; } public string groupName { get; set; } public long applyTime{ get; set; } /// /// 申请状态,-1 申请中,0 通过,1 拒绝,2 已过期。 /// public int status { get; set; } = -1; public List courses { get; set; }= new List(); } public static (int status, GroupList stuList, Member member) JoinList(GroupList stuList, string userid, int type, string school,int year) { int status = -1; if (!string.IsNullOrWhiteSpace(stuList.school) && !string.IsNullOrWhiteSpace(school)) { if (!stuList.school.Equals(school)) { status = 3;//不允许跨校加入名单 return (status, stuList,null); } } string irs = string.Empty; List irsOrder = stuList.members.Select(x => x.irs)?.Where(y => !string.IsNullOrEmpty(y) && Regex.IsMatch(y, @"^\d*$")).OrderBy(x => int.Parse(x)).ToList(); if (!irsOrder.Contains("0")) { irsOrder.Insert(0, "0"); } if (irsOrder != null) { if (!irsOrder.Contains("0")) { irsOrder.Insert(0, "0"); } } else { irsOrder = new List() { "0" }; } for (int i = 0; i < irsOrder.Count; i++) { irs = $"{int.Parse(irsOrder[i]) + 1}"; int index = i + 1; if (index <= irsOrder.Count - 1) { if (!irs.Equals(irsOrder[index])) { break; } } } Member member = null; if (string.IsNullOrEmpty($"{userid}")) { //加入学生或醍摩豆ID为空 status = 1; } else { if (type == 1) { member = stuList.members.Find(x => x.type == 1 && x.id.Equals(userid)); if (member != null) { //重复加入 status = 2; } else { //加入成功 status = 0; member = new Member { id = userid, type = type, irs = irs, no = irs,year=year }; stuList.members.Add(member); } } else if (type == 2) { member = stuList.members.Find(x => x.type == 2 && x.id.Equals(userid) && x.code.Equals(school)); if (member != null) { //重复加入 status = 2; } else { status = 0; member = new Member { id = userid, code = school, type = type, irs = irs, no = irs, year = year }; stuList.members.Add(member); } } } return (status, stuList, member); } public static async Task UpsertList(GroupList list, AzureCosmosFactory _azureCosmos, IConfiguration _configuration, AzureServiceBusFactory _serviceBus) { bool isnew = false; var client = _azureCosmos.GetCosmosClient(); if (string.IsNullOrEmpty(list.id)) { list.id = Guid.NewGuid().ToString(); isnew = true; } string tbname = list.scope.Equals("private") ? "Teacher" : "School"; var tmembers = list.members.Where(x => x.type == 1); var smembers = list.members.Where(x => x.type == 2); //处理年级 HashSet grades = new HashSet(); if (smembers.Any()) { grades = smembers.Where(z => z.year > 2000).Select(z=>z.year).ToHashSet(); } list.grades = grades; list.scount = smembers.Count(); list.tcount = tmembers.Count(); //if (smembers.Count() > 0 && smembers.Select(x => x.code).ToHashSet().Count()>=2) { // //处理移除多个学校的名单,只保留一个学校的。 // if (string.IsNullOrWhiteSpace(list.school)) // { // HashSet codes = smembers.Select(x => x.code).ToHashSet(); // list.school = codes.First(); // codes.Remove(codes.First()); // list.members.RemoveAll(x => codes.Contains(x.code)); // } // else { // list.members.RemoveAll(x => !x.code.Equals(list.school)); // } //} if (string.IsNullOrWhiteSpace(list.school) && smembers.Count() >= 1) { list.school = smembers.First().code; } if (!string.IsNullOrWhiteSpace(list.school) && smembers.Count() == 0 && list.scope.Equals("private")) { list.school = null; } //学生名单,教研组会触发活动中间表刷新 if (list.type.Equals("teach") || list.type.Equals("research") || list.type.Equals("yxtrain") || list.type.Equals("activity")) { GroupChange change = new GroupChange() { type = list.type, listid = list.id, scope = list.scope, originCode = list.school, school = list.school, creatorId = list.creatorId }; GroupList oldList = null; if (!isnew) { try { oldList = await client.GetContainer(Constant.TEAMModelOS, tbname).ReadItemAsync(list.id, new PartitionKey(list.code)); } catch (CosmosException) { oldList = null; } } if (list.members.IsNotEmpty() && (oldList == null || !oldList.members.IsNotEmpty())) { //加入的 var tmdids = list.members.FindAll(x => x.type == 1); if (tmdids.IsNotEmpty()) { if (list.type.Equals("research") || list.type.Equals("yxtrain")) { change.tchjoin.AddRange(tmdids); } else { change.tmdjoin.AddRange(tmdids); } } var stuids = list.members.FindAll(x => x.type == 2); if (stuids.IsNotEmpty()) { change.stujoin.AddRange(stuids); } } else { if (list.members.IsNotEmpty()) { var tmdids = list.members.FindAll(x => x.type == 1); var oldtmdids = oldList.members.FindAll(x => x.type == 1); //取各自的差集 //新=》旧差集,表示新增 var jointmdid = tmdids.Select(x => x.id).Except(oldtmdids.Select(y => y.id)).ToList(); //旧=》新差集,表示离开 var leavetmdid = oldtmdids.Select(x => x.id).Except(tmdids.Select(y => y.id)).ToList(); if (list.type.Equals("research") || list.type.Equals("yxtrain")) { if (tmdids!=null && jointmdid!=null) { change.tchjoin.AddRange(tmdids.Where(x => jointmdid.Exists(y => y.Equals(x.id)))); } if (oldtmdids!= null &&leavetmdid != null) { change.tchleave.AddRange(oldtmdids.Where(x => leavetmdid.Exists(y => y.Equals(x.id)))); } } else { if (tmdids!=null && jointmdid!=null) { change.tmdjoin.AddRange(tmdids.Where(x => jointmdid.Exists(y => y.Equals(x.id)))); } if (oldtmdids!= null &&leavetmdid != null) { change.tmdleave.AddRange(oldtmdids.Where(x => leavetmdid.Exists(y => y.Equals(x.id)))); } } var stuids = list.members.FindAll(x => x.type == 2); var oldstuids = oldList.members.FindAll(x => x.type == 2); var joinstudent = stuids.Select(x => (x.id, x.code)).Except(oldstuids.Select(y => (y.id, y.code)), new CompareIdCode()).ToList(); var leavestudent = oldstuids.Select(x => (x.id, x.code)).Except(stuids.Select(y => (y.id, y.code)), new CompareIdCode()).ToList(); change.stujoin.AddRange(stuids.Where(x => joinstudent.Exists(y => y.id.Equals(x.id) && y.code.Equals(x.code)))); change.stuleave.AddRange(oldstuids.Where(x => leavestudent.Exists(y => y.id.Equals(x.id) && y.code.Equals(x.code)))); } else { //离开的 if (oldList != null) { var tmdids = oldList.members.FindAll(x => x.type == 1); if (tmdids.IsNotEmpty()) { if (list.type.Equals("research") || list.type.Equals("yxtrain")) { change.tchleave.AddRange(tmdids); } else { change.tmdleave.AddRange(tmdids); } } var stuids = oldList.members.FindAll(x => x.type == 2); if (stuids.IsNotEmpty()) { change.stuleave.AddRange(stuids); } } } } if (change.tmdjoin.Count != 0 || change.tmdleave.Count != 0 || change.stujoin.Count != 0 || change.stuleave.Count != 0 || change.tchjoin.Count != 0 || change.tchleave.Count != 0) { var messageChange = new ServiceBusMessage(change.ToJsonString()); messageChange.ApplicationProperties.Add("name", "GroupChange"); var ActiveTask = _configuration.GetValue("Azure:ServiceBus:ActiveTask"); await _serviceBus.GetServiceBusClient().SendMessageAsync(ActiveTask, messageChange); } } await client.GetContainer(Constant.TEAMModelOS, tbname).UpsertItemAsync(list, new PartitionKey(list.code)); return list; } public static async Task CheckListNo(GroupList list, AzureCosmosFactory _azureCosmos, DingDing _dingDing, Option _option) { try { var client = _azureCosmos.GetCosmosClient(); if (string.IsNullOrEmpty(list.no)) { list.no = $"{Utils.CreatSaltString(6, "123456789")}"; for (int i = 0; i < 10; i++) { List noStus = new List(); var queryNo = $"SELECT c.no FROM c where c.no ='{list.no}'"; if (list.scope.Equals("school")) { await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "School").GetItemQueryStreamIterator(queryText: queryNo, requestOptions: new QueryRequestOptions() { PartitionKey = new Azure.Cosmos.PartitionKey($"{list.code}") })) { using var jsonNo = await JsonDocument.ParseAsync(item.ContentStream); if (jsonNo.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0) { var accounts = jsonNo.RootElement.GetProperty("Documents").EnumerateArray(); while (accounts.MoveNext()) { JsonElement account = accounts.Current; noStus.Add(account.GetProperty("no").GetString()); } } } } await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "Teacher").GetItemQueryStreamIterator(queryText: queryNo, requestOptions: new QueryRequestOptions() { PartitionKey = new Azure.Cosmos.PartitionKey("GroupList") })) { using var jsonNo = await JsonDocument.ParseAsync(item.ContentStream); if (jsonNo.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0) { var accounts = jsonNo.RootElement.GetProperty("Documents").EnumerateArray(); while (accounts.MoveNext()) { JsonElement account = accounts.Current; noStus.Add(account.GetProperty("no").GetString()); } } } if (noStus.Count == 0) { break; } else { if (i == 9) { string msg = $"OS,{_option.Location},school/course/upsert-list()\n 编号生成异常,重复生成次数超过10次"; await _dingDing.SendBotMsg(msg, GroupNames.醍摩豆服務運維群組); throw new Exception(msg); } else { list.no = $"{Utils.CreatSaltString(6, "123456789")}"; } } } } } catch (Exception ex) { } return list; } /// ///根据任意名单id获取名单摘要信息。 /// /// /// /// /// /// /// 毕业类型0在校,1毕业 , -1查全部。 /// public static async Task> GetGroupListByListids(CosmosClient client, DingDing _dingDing, List classes, string school, string SummarySql = " c.id,c.code,c.name,c.no,c.periodId,c.scope,c.school,c.creatorId,c.type,c.year,c.tcount,c.scount,c.leader ,c.froms ,c.joinLock ,c.review,c.limitCount ,c.expire ,c.qrcodeExpire,c.qrcodeDays ,c.grades ", int graduate = -1) { List groupLists = null; try { classes.RemoveAll(x => x == null); if (!classes.IsNotEmpty()) { return null; } if (classes.Count == 1 && classes.First().Equals("TeacherAll") && !string.IsNullOrEmpty(school)) { //默认的教研组 GroupListDto groupList = new GroupListDto { id = "TeacherAll", name = "TeacherAll", code = $"GroupList-{school}", school = school, scope = "school", type = "yxtrain", }; groupLists = new List { groupList }; } else { Dictionary> groups = new Dictionary>(); //List students = new List(); string sql = string.Join(",", classes.Select(x => $"'{x}'")); if (!string.IsNullOrEmpty(school)) { List schoolList = new List(); await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "School").GetItemQueryIterator(queryText: $"select {SummarySql} from c where c.id in ({sql})", requestOptions: new QueryRequestOptions() { PartitionKey = new Azure.Cosmos.PartitionKey($"GroupList-{school}") })) { schoolList.Add(item); } if (schoolList.IsNotEmpty()) { groups.Add("School", schoolList); } //取差集,减少二次搜寻 classes = classes.Except(schoolList.Select(y => y.id)).ToList(); if (classes.IsNotEmpty()) { if (!groupLists.IsNotEmpty()) { groupLists = new List(); } string insql = string.Join(",", classes.Select(x => $"'{x}'")); //搜寻没有关联学生的行政班 await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "School").GetItemQueryIterator(queryText: $"select c.id,c.code,c.name,c.no,c.periodId,c.scope,c.school,c.creatorId,c.type,c.year,c.tcount,c.scount,c.teacher.id as leader ,c.graduate from c where c.id in ({insql})", requestOptions: new QueryRequestOptions() { PartitionKey = new Azure.Cosmos.PartitionKey($"Class-{school}") })) { ///行政班(学生搜寻classId动态返回)class GroupListDto group = new GroupListDto { id = item.id, code = $"GroupList-{school}", name = item.name, periodId = item.periodId, scope = "school", school = school, type = "class", year = item.year, expire = item.expire, leader = item.leader, no = item.no, pk = "GroupList", graduate = item.graduate, grades= new HashSet { item.year } }; //graduate传入的状态>=0 表示指定状态查询,且传入的状态与数据库的状态一致。 if (graduate >= 0) { if (group.graduate == graduate) { groupLists.Add(group); } } //全部。 else { groupLists.Add(group); } // groupLists.Add(group); } //取差集,减少二次搜寻 classes = classes.Except(groupLists.Select(y => y.id)).ToList(); } } if (classes.IsNotEmpty()) { List privateList = new List(); sql = string.Join(",", classes.Select(x => $"'{x}'")); await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "Teacher").GetItemQueryIterator(queryText: $"select {SummarySql} from c where c.id in ({sql})", requestOptions: new QueryRequestOptions() { PartitionKey = new Azure.Cosmos.PartitionKey($"GroupList") })) { privateList.Add(item); //if (string.IsNullOrWhiteSpace(school)) //{ // privateList.Add(item); //} //else //{ // if (!string.IsNullOrWhiteSpace(item.school)) // { // if (item.school.Equals(school)) // { // privateList.Add(item); // } // } // else // { // privateList.Add(item); // } //} } if (privateList.IsNotEmpty()) { groups.Add("Teacher", privateList); } } if (groups.Count != 0) { if (groupLists.IsNotEmpty()) { groupLists.AddRange(groups.SelectMany(x => x.Value).ToList()); } else { groupLists = groups.SelectMany(x => x.Value).ToList(); } } } } catch (Exception ex ) { await _dingDing.SendBotMsg($"{ex.Message}\n{ex.StackTrace}", GroupNames.成都开发測試群組); } return groupLists; } /// /// 根据任意名单id获取成员信息。rmembers是去重的信息,groups是名单及人员信息,同一个人可能在不同的名单内。 /// /// /// /// /// /// /// /// 毕业类型0在校,1毕业 , -1查全部。 /// public static async Task<(Listrmembers, List groups)> GetMemberByListids(CoreAPIHttpService _coreAPIHttpService, CosmosClient client, DingDing _dingDing, List classes, string school, List<(string, List)> groupids = null, int graduate = -1) { List members = new List(); List groupLists = new List(); if (classes != null) { classes.RemoveAll(x => x == null); } if (classes == null || classes.Count <= 0) { return (members, groupLists); } string periodId = string.Empty; if (classes.Count == 1 && classes.First().Equals("TeacherAll") && !string.IsNullOrEmpty(school)) { //默认的教研组 members = new List(); await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "School"). GetItemQueryIterator(queryText: $"SELECT c.id,c.name,c.picture FROM c ", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Teacher-{school}") })) { RMember member = new RMember { id = item.id, name = item.name, picture = item.picture, type = 1, // nickname=item.name, }; members.Add(member); } RGroupList groupList = new RGroupList { id = "TeacherAll", name = "TeacherAll", code = $"GroupList-{school}", school = school, scope = "school", type = "TeacherAll", members = members }; groupLists = new List { groupList }; } else { Dictionary> groups = new Dictionary>(); List students = new List(); string sql = string.Join(",", classes.Select(x => $"'{x}'")); if (!string.IsNullOrEmpty(school)) { List schoolList = new List(); string queryText = $"select value(c) from c where c.id in ({sql})"; await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "School").GetItemQueryIterator(queryText: queryText, requestOptions: new QueryRequestOptions() { PartitionKey = new Azure.Cosmos.PartitionKey($"GroupList-{school}") })) { schoolList.Add(item); } if (schoolList.IsNotEmpty()) { groups.Add("School", schoolList); } //取差集,减少二次搜寻 classes = classes.Except(schoolList.Select(y => y.id)).ToList(); if (classes.IsNotEmpty()) { sql = string.Join(",", classes.Select(x => $"'{x}'")); await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "Student").GetItemQueryIterator(queryText: $"select value(c) from c where c.classId in ({sql})", requestOptions: new QueryRequestOptions() { PartitionKey = new Azure.Cosmos.PartitionKey($"Base-{school}") })) { //graduate传入的状态>=0 表示指定状态查询,且传入的状态与数据库的状态一致。 if (graduate >= 0) { if (item.graduate == graduate) { students.Add(item); } } //全部。 else { students.Add(item); } // students.Add(item); } //取差集,减少二次搜寻 classes = classes.Except(students.Select(y => y.classId)).ToList(); } if (classes.IsNotEmpty()) { string insql = string.Join(",", classes.Select(x => $"'{x}'")); //搜寻没有关联学生的行政班 await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "School") .GetItemQueryIterator(queryText: $"select c.id,c.code,c.name,c.no,c.periodId,c.scope,c.school,c.creatorId,c.type,c.year,c.tcount,c.scount,c.teacher.id as leader ,c.graduate from c where c.id in ({insql})", requestOptions: new QueryRequestOptions() { PartitionKey = new Azure.Cosmos.PartitionKey($"Class-{school}") })) { ///行政班(学生搜寻classId动态返回)class List smembers = new List(); RGroupList group = new RGroupList { id = item.id, code = $"GroupList-{school}", name = item.name, periodId = item.periodId, scope = "school", school = school, type = "class", year = item.year, expire = item.expire, members = smembers, scount = smembers.Count, pk = "GroupList", leader = item.leader, no = item.no, graduate = item.graduate, grades= new HashSet() { item.year } }; //graduate传入的状态>=0 表示指定状态查询,且传入的状态与数据库的状态一致。 if (graduate >= 0) { if (group.graduate == graduate) { groupLists.Add(group); } } //全部。 else { groupLists.Add(group); } //groupLists.Add(group); } //取差集,减少二次搜寻 classes = classes.Except(groupLists.Select(y => y.id)).ToList(); } } if (classes.IsNotEmpty()) { List privateList = new List(); sql = string.Join(",", classes.Select(x => $"'{x}'")); await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "Teacher").GetItemQueryIterator(queryText: $"select value(c) from c where c.id in ({sql})", requestOptions: new QueryRequestOptions() { PartitionKey = new Azure.Cosmos.PartitionKey($"GroupList") })) { privateList.Add(item); //if (string.IsNullOrWhiteSpace(school)) //{ // privateList.Add(item); //} //else //{ // if (!string.IsNullOrWhiteSpace(item.school)) // { // if (item.school.Equals(school)) // { // privateList.Add(item); // } // } // else // { // privateList.Add(item); // } //} } if (privateList.IsNotEmpty()) { groups.Add("Teacher", privateList); } } foreach (var item in groups) { var list = item.Value.GroupBy(x => x.type).Select(y => new { key = y.Key, list = y.ToList() }); foreach (var group in list) { (List rgroups, List rmembers) = await GetGroupListMemberInfo(_coreAPIHttpService, client, group.key, group.list, item.Key, _dingDing, school,graduate); members.AddRange(rmembers); } } groupLists.AddRange(groups.SelectMany(x => x.Value).ToList()); if (students.IsNotEmpty()) { List sqlList = students.Select(x => x.classId).ToList(); string insql = string.Join(",", sqlList.Select(x => $"'{x}'")); await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "School"). GetItemQueryIterator(queryText: $"select c.id,c.code,c.name,c.no,c.periodId,c.scope,c.school,c.creatorId,c.type,c.year,c.tcount,c.scount,c.teacher.id as leader ,c.graduate from c where c.id in ({insql})", requestOptions: new QueryRequestOptions() { PartitionKey = new Azure.Cosmos.PartitionKey($"Class-{school}") })) { ///行政班(学生搜寻classId动态返回)class List smembers = students.Where(x => x.classId.Equals(item.id)) .Select(y => new RMember { id = y.id, code = school, name = y.name, //nickname = y.name, type = 2, picture = y.picture, no = y.no, classId = y.classId, groupId = y.groupId, groupName = y.groupName, irs = y.irs, year= y.year, graduate = y.graduate, gender= y.gender, periodId=y.periodId, }).ToList(); members.AddRange(smembers); RGroupList group = new RGroupList { id = item.id, code = $"GroupList-{school}", name = item.name, periodId = item.periodId, scope = "school", school = school, type = "class", expire= item.expire, year = item.year, members = smembers, scount = smembers.Count, no = item.no, leader = item.leader, pk = "GroupList", graduate = item.graduate, grades= new HashSet { item.year} }; //graduate传入的状态>=0 表示指定状态查询,且传入的状态与数据库的状态一致。 if (graduate >= 0) { if (group.graduate == graduate) { groupLists.Add(group); } } //全部。 else { groupLists.Add(group); } // groupLists.Add(group); } //去重。 members = members.FindAll(x => x.type == 2).Where((x, i) => members.FindAll(x => x.type == 2).FindIndex(n => n.id.Equals(x.id) && n.code.Equals(x.code)) == i).ToList(); } } if (groupids.IsNotEmpty()) { List rmembers = new List(); groupLists.ForEach(y => { (string id, List grpids) = groupids.Find(x => x.Item1.Equals(y.id)); var gpmember = y.members.FindAll(x => !string.IsNullOrEmpty(x.groupName) && grpids.Contains(x.groupName)); if (grpids.Contains("default")) { var gpmemberdft = y.members.FindAll(x => string.IsNullOrWhiteSpace(x.groupName)); if (gpmember.IsNotEmpty()) { gpmember.AddRange(gpmemberdft); } else { gpmember = gpmemberdft; } } y.members = gpmember; }); var gpgpmembers = groupLists.SelectMany(x => x.members).ToList(); List tmdids = gpgpmembers.FindAll(x => x.type == 1).Where((x, i) => gpgpmembers.FindAll(x => x.type == 1).FindIndex(n => n.id.Equals(x.id)) == i).ToList(); List students = gpgpmembers.FindAll(x => x.type == 2).Where((x, i) => gpgpmembers.FindAll(x => x.type == 2).FindIndex(n => n.id.Equals(x.id) && n.code.Equals(x.code)) == i).ToList(); if (tmdids.IsNotEmpty()) { rmembers.AddRange(tmdids); } if (students.IsNotEmpty()) { rmembers.AddRange(students); } groupLists.ForEach(x => { if (string.IsNullOrWhiteSpace(x.periodId)) { var meb = x.members.Where(z => !string.IsNullOrWhiteSpace(z.periodId)).FirstOrDefault(); if (meb!= null) { x.periodId=meb?.periodId; } } }); return (rmembers, groupLists); } else { groupLists.ForEach(x => { if (string.IsNullOrWhiteSpace(x.periodId)) { var meb = x.members.Where(z => !string.IsNullOrWhiteSpace(z.periodId)).FirstOrDefault(); if (meb!= null) { x.periodId=meb?.periodId; } } }); return (members, groupLists); } } /// /// 根据名单类型获取名单及成员信息。 /// /// /// /// /// /// /// /// 毕业类型0在校,1毕业 , -1查全部。 /// public static async Task> GetGroupListMemberByType(CoreAPIHttpService _coreAPIHttpService, CosmosClient client, string type, List scopes, string school, DingDing _dingDing, int graduate = -1) { StringBuilder sql = new StringBuilder($"SELECT distinct value(c) FROM c where c.type='{type}'"); Dictionary> groups = new Dictionary>(); if (scopes.Contains("school")) { if (!string.IsNullOrEmpty(school)) { List groupLists = new List(); await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "School").GetItemQueryIterator(queryText: sql.ToString(), requestOptions: new QueryRequestOptions() { PartitionKey = new Azure.Cosmos.PartitionKey($"GroupList-{school}") })) { groupLists.Add(item); } groups.Add("School", groupLists); } } else if (scopes.Contains("private")) { List groupLists = new List(); await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "Teacher").GetItemQueryIterator(queryText: sql.ToString(), requestOptions: new QueryRequestOptions() { PartitionKey = new Azure.Cosmos.PartitionKey($"GroupList") })) { groupLists.Add(item); //if (string.IsNullOrWhiteSpace(school)) //{ // groupLists.Add(item); //} //else //{ // if (!string.IsNullOrWhiteSpace(item.school)) // { // if (item.school.Equals(school)) // { // groupLists.Add(item); // } // } // else { // groupLists.Add(item); // } //} } groups.Add("Teacher", groupLists); } foreach (var item in groups) { var list = item.Value.GroupBy(x => x.type).Select(y => new { key = y.Key, list = y.ToList() }); foreach (var group in list) { (List rgroups, List rmembers) = await GetGroupListMemberInfo(_coreAPIHttpService, client, group.key, group.list, item.Key, _dingDing, school,graduate); } } var lists = groups.SelectMany(x => x.Value).ToList(); return lists; } /// /// 根据名单类型,名单分组信息获取成员信息, rmembers是去重的信息,groups是名单及人员信息,同一个人可能在不同的名单内。 /// /// /// /// /// /// /// /// /// 毕业类型0在校,1毕业 , -1查全部。 /// public static async Task<(List groups, List members)> GetGroupListMemberInfo(CoreAPIHttpService _coreAPIHttpService, CosmosClient client, string type, List groups, string groupTbname, DingDing _dingDing, string school, int graduate = -1) { try { HashSet changes = new HashSet(); var members = groups.SelectMany(y => y.members).ToList(); //去重 List tmdids = members.FindAll(x => x.type == 1).Where((x, i) => members.FindAll(x => x.type == 1).FindIndex(n => n.id.Equals(x.id)) == i).ToList(); List students = members.FindAll(x => x.type == 2).Where((x, i) => members.FindAll(x => x.type == 2).FindIndex(n => n.id.Equals(x.id) && n.code.Equals(x.code)) == i).ToList(); var stu = students.GroupBy(x => x.code).Select(y => new { key = y.Key, list = y.ToList() }); List studentsData = new List(); string periodId = ""; if (stu != null) { foreach (var item in stu) { var ids = item.list.Select(x => x.id).ToList(); if (ids.IsNotEmpty()) { StringBuilder stuSql = new StringBuilder($"SELECT distinct c.name,c.id,c.code,c.picture,c.no,c.irs,c.classId ,c.graduate,c.year ,c.periodId FROM c "); string insql = string.Join(",", ids.Select(x => $"'{x}'")); stuSql.Append($"where c.id in ({insql})"); await foreach (var student in client.GetContainer(Constant.TEAMModelOS, "Student").GetItemQueryIterator(queryText: stuSql.ToString(), requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Base-{item.key}") })) { periodId=student.periodId; student.schoolId = item.key; studentsData.Add(student); } } } var unexist_student = students.Select(x => (x.id, x.code)).Except(studentsData.Select(y => (y.id, y.schoolId)), new CompareIdCode()).ToList(); groups.ForEach(x => { int item = x.members.RemoveAll(y => y.type == 2 && unexist_student.Exists(x => x.id.Equals(y.id) && x.Item2.Equals(y.code))); if (item > 0) { changes.Add(x); } }); } List tmdsData = new List(); if (tmdids.IsNotEmpty()) { string memberTbname = ""; if ($"{type}".Equals("activity")) { var mbers = groups.SelectMany(x => x.members).Where(z => !string.IsNullOrEmpty(z.code)); var schoolTeachers = mbers.GroupBy(y => y.code).Select(m => new { key = m.Key, list = m.ToList() }); foreach (var schoolTeacher in schoolTeachers) { StringBuilder tmdidSql = new StringBuilder($"SELECT distinct c.name,c.id,c.picture FROM c "); string insql = string.Join(",", schoolTeacher.list.Select(x => $"'{x.id}'")); tmdidSql.Append($" where c.id in ({insql})"); await foreach (var tmd in client.GetContainer(Constant.TEAMModelOS, "School").GetItemQueryIterator(queryText: tmdidSql.ToString(), requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Teacher-{schoolTeacher.key}") })) { tmdsData.Add(tmd); } } var unexist_teachers = mbers.Select(x => (x.id, x.code)).Except(tmdsData.Select(y => (y.id, y.code)), new CompareIdCode()).ToList(); groups.ForEach(x => { int item = x.members.RemoveAll(y => y.type == 2 && unexist_teachers.Exists(x => x.id.Equals(y.id) && x.Item2.Equals(y.code))); if (item > 0) { changes.Add(x); } }); } else { //处理研修名单,如果是学校老师的,则需要检查SchoolTeacher //处理 学校教研组,学校管理人员,学校任课教师,学校研修名单。 if (!string.IsNullOrEmpty(school) && ($"{type}".Equals("yxtrain") || $"{type}".Equals("research") || $"{type}".Equals("manage") || $"{type}".Equals("subject"))) { StringBuilder tmdidSql = new StringBuilder($"SELECT distinct c.name,c.id,c.picture FROM c "); string insql = string.Join(",", tmdids.Select(x => $"'{x.id}'")); tmdidSql.Append($" where c.id in ({insql})"); await foreach (var tmd in client.GetContainer(Constant.TEAMModelOS, "School").GetItemQueryIterator(queryText: tmdidSql.ToString(), requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Teacher-{school}") })) { tmdsData.Add(tmd); } } else { { StringBuilder tmdidSql = new StringBuilder($"SELECT distinct c.name,c.id,c.picture FROM c "); string insql = string.Join(",", tmdids.Select(x => $"'{x.id}'")); tmdidSql.Append($" where c.id in ({insql})"); memberTbname = "Teacher"; await foreach (var tmd in client.GetContainer(Constant.TEAMModelOS, memberTbname).GetItemQueryIterator(queryText: tmdidSql.ToString(), requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Base") })) { tmdsData.Add(tmd); } } { //取差集,减少二次搜寻 var tmdidexp = tmdids.Select(x => x.id).Except(tmdsData.Select(y => y.id)).ToList(); if (tmdidexp.IsNotEmpty()) { StringBuilder tmdidSql = new StringBuilder($"SELECT distinct c.name,c.id,c.picture FROM c "); string insql = string.Join(",", tmdidexp.Select(x => $"'{x}'")); tmdidSql.Append($" where c.id in ({insql})"); memberTbname = "Student"; await foreach (var tmd in client.GetContainer(Constant.TEAMModelOS, memberTbname).GetItemQueryIterator(queryText: tmdidSql.ToString(), requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Base") })) { tmdsData.Add(tmd); } } } } tmdsData = tmdsData.Where((x, i) => tmdsData.FindIndex(n => n.id.Equals(x.id)) == i).ToList(); var unexist_tmdid = tmdids.Select(x => x.id).Except(tmdsData.Select(y => y.id)).ToList(); groups.ForEach(x => { int item = x.members.RemoveAll(y => unexist_tmdid.Contains(y.id) && y.type == 1); if (item > 0) { changes.Add(x); } }); } } if (tmdids.IsNotEmpty() && _coreAPIHttpService.check) { ///获取真实的名称 ,大于50则不处理 if (tmdids.Count < 60) { var content = new StringContent(tmdids.Select(x => x.id).ToHashSet().ToJsonString(), Encoding.UTF8, "application/json"); string json = null; try { json = await _coreAPIHttpService.GetUserInfos(content); if (!string.IsNullOrWhiteSpace(json)) { List tmdInfos = json.ToObject>(); if (tmdInfos.IsNotEmpty()) { tmdsData.ForEach(y => { var tmd = tmdInfos.Find(x => x.id.Equals(y.id)); if (tmd != null) { y.name = tmd?.name; y.picture = tmd?.picture; } else { groups.ForEach(x => { int item = x.members.RemoveAll(z => z.id.Equals(y.id) && z.type == 1); if (item > 0) { changes.Add(x); } }); } }); } } } catch (Exception ex) { await _dingDing.SendBotMsg($"{_coreAPIHttpService.options.location}用户转换失败:{_coreAPIHttpService.options.coreUrl}{json}\n {ex.Message}\n{ex.StackTrace}{tmdids.Select(x => x.id).ToJsonString()}", GroupNames.醍摩豆服務運維群組); } } } tmdids.ForEach(x => { var user = tmdsData.Find(y => y.id.Equals(x.id)); x.name = user?.name; // x.nickname = string.IsNullOrWhiteSpace(x.nickname) ? user?.name : x.nickname; x.picture = user?.picture; }); students.ForEach(x => { var student = studentsData.Find(y => y.id.Equals(x.id) && y.schoolId.Equals(x.code)); if (student != null) { x.name = student?.name; // x.nickname = string.IsNullOrWhiteSpace(x.nickname) ? student?.name:x.nickname; x.picture = student?.picture; x.classId = student?.classId; x.graduate = student.graduate; x.year = student.year; x.gender= student.gender; x.periodId = student.periodId; } }); var mbs = tmdids; mbs.AddRange(students); if (changes.Count > 0 && !string.IsNullOrEmpty(groupTbname)) { foreach (var change in changes) { change.tcount = change.members.Where(x => x.type == 1).Count(); change.scount = change.members.Where(x => x.type == 2).Count(); GroupList group = change.ToJsonString().ToObject(); await client.GetContainer(Constant.TEAMModelOS, groupTbname).ReplaceItemAsync(group, group.id, new PartitionKey(group.code)); } } groups.ForEach(x => { x.members.ForEach(y => { if (y.type == 1) { var tmd = tmdids.Find(t => t.id.Equals(y.id)); y.name = tmd?.name; //y.nickname = string.IsNullOrWhiteSpace(y.nickname) ? tmd?.nickname : y.nickname; y.picture = tmd?.picture; } if (y.type == 2) { var student = students.Find(t => t.id.Equals(y.id) && t.code.Equals(y.code)); if (student != null) { y.name = student?.name; // y.nickname = string.IsNullOrWhiteSpace(y.nickname) ? student?.nickname : y.nickname; y.picture = student?.picture; y.classId = student?.classId; y.graduate = student.graduate; y.gender = student.gender; y.year = student.year; x.periodId = student.periodId; x.grades.Add(student.year); } } }); if (!x.type.Equals("class")) { var yearc = x.members.Where(z => z.type == 2).GroupBy(g => g.year).Select(k => new { key = k.Key, count = k.Count() }).OrderByDescending(z => z.count); if (yearc.Any()) { //有一半的人是同一个班的,则以 if (yearc.First().count * 1.0 / x.members.Count > 0.51) { x.year = yearc.First().key; } } } x.periodId=periodId; }); HashSet schoolCodes = groups.SelectMany(x => x.members).Where(y => !string.IsNullOrEmpty(y.code)).Select(z => z.code).ToHashSet(); if (schoolCodes != null && schoolCodes.Count > 0) { List schools = new List(); string insql = $"select c.name,c.id from c where c.id in ({string.Join(",", schoolCodes.Select(x => $"'{x}'"))})"; await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "School").GetItemQueryIterator(queryText: insql, requestOptions: new QueryRequestOptions { PartitionKey = new PartitionKey("Base") })) { schools.Add(item); } if (schools.IsNotEmpty()) { groups.SelectMany(x => x.members).Where(y => !string.IsNullOrEmpty(y.code)).ToList().ForEach(z => { var school = schools.Find(j => j.id.Equals(z.code)); z.schoolName = school?.name; }); } } if (graduate >= 0) { groups= groups.FindAll(x => x.graduate == graduate); if (groups != null) { groups.ForEach(x => { x.members.RemoveAll(y => y.graduate != graduate); }); } mbs.RemoveAll(z => z.graduate != graduate); return (groups, mbs); } //直接返回 else { return (groups, mbs); } } catch (Exception ex) { await _dingDing.SendBotMsg($"{_coreAPIHttpService.options.location},GetGroupListMemberInfo()\n{ex.Message}\n{ex.StackTrace}\n", GroupNames.醍摩豆服務運維群組); } return (null, null); } /// /// 处理活动结束的 /// /// /// 数据库 /// 钉钉消息 /// 学校编码 /// 行政班 /// 学生 /// 教师 /// 分组 /// 毕业类型0在校,1毕业 , -1查全部。 /// public static async Task> GetFinishMemberInfo(CoreAPIHttpService _coreAPIHttpService, CosmosClient cosmosClient, DingDing _dingDing, string school, List classes, List stuLists, List tchLists, List<(string, List)> _groupLists = null, int graduate = -1) { List fMembers = new(); if (classes != null && classes.Count > 0) { (List staffList, List classInfos) = await GetMemberByListids(_coreAPIHttpService, cosmosClient, _dingDing, classes, school); staffList.ForEach(x => fMembers.Add(new FMember() { id = x.id, code = school, type = 1, })); } if (stuLists != null && stuLists.Count > 0) { (List staffList, List classInfos) = await GetMemberByListids(_coreAPIHttpService, cosmosClient, _dingDing, stuLists, school); staffList.ForEach(x => fMembers.Add(new FMember() { id = x.id, code = school, type = 2 })); } /* if (tchLists != null && tchLists.Count > 0) { (List staffList, List classInfos) = await GetMemberByListids(_coreAPIHttpService, cosmosClient, _dingDing, tchLists, school); staffList.ForEach(x => fMembers.Add(new FMember() { id = x.id, code = school, type = 2 })); }*/ if (tchLists != null && tchLists.Count > 0) { (List staffList, List groupLists1) = await GetMemberByListids(_coreAPIHttpService, cosmosClient, _dingDing, tchLists, school, _groupLists); staffList.ForEach(x => fMembers.Add(new FMember() { id = x.id, code = school, type = 2 })); } return fMembers; } } public class CompareIdCode : IEqualityComparer<(string id, string code)> { public bool Equals((string id, string code) x, (string id, string code) y) { return x.id.Equals(y.id) && x.code.Equals(y.code); } public int GetHashCode((string id, string code) obj) { if (obj.id != null && obj.code != null) { return 1; } else { return 0; } } } }