using Microsoft.Azure.Cosmos; using System; using System.Collections.Generic; using System.Threading.Tasks; using TEAMModelOS.SDK.DI; using TEAMModelOS.SDK.Extension; using System.Linq; using System.Text; using System.Text.Json; using TEAMModelOS.Models; using Azure.Messaging.ServiceBus; using Microsoft.Extensions.Configuration; using System.Text.RegularExpressions; using TEAMModelOS.SDK.Models; using System.Net.Http; namespace TEAMModelOS.SDK { public class GroupListService { /// /// 根据教师id获取执教的名单及协同身份的名单 /// /// /// /// /// /// 可选,不填则只获取个人课程的名单 /// school,传递,则 periodId必传 /// 时间,以便于获取某一学期的数据 /// public static async Task> GetTeacherTeachGroupList(CoreAPIHttpService _coreAPIHttpService, CosmosClient client, DingDing _dingDing, string tmdid, string school, string periodId, long time = -1) { string sql = $"SELECT distinct value c FROM c join b in c.schedules where c.pk='CourseTask' and (ARRAY_CONTAINS(b.assistants,'{tmdid}')or b.teacherId ='{tmdid}' )"; List> schoolTeacherTask = new List>(); List> schoolAssistantTask = new List>(); List> privateTeacherTask = new List>(); List> privateAssistantTask = new List>(); List schoolCourses = new List(); List teahcerCourses = new List(); List groupIds = new List(); if (!string.IsNullOrWhiteSpace(school) && !school.Equals("SYSTEM_NO_SCHOOL") && !string.IsNullOrWhiteSpace(periodId)) { School schoolBase = await client.GetContainer(Constant.TEAMModelOS, Constant.School).ReadItemAsync(school, new PartitionKey("Base")); var data = SchoolService.GetSemester(schoolBase.period.Find(x => x.id.Equals(periodId)), time); sql = $"{sql} and c.year={data.studyYear} and c.semesterId='{data.currSemester.id}'"; HashSet courseIds = new HashSet(); var resultSchool = await client.GetContainer(Constant.TEAMModelOS, Constant.School).GetList(sql, $"CourseTask-{school}"); if (resultSchool.list.IsNotEmpty()) { resultSchool.list.ForEach(x => { var schedulesTeacher = x.schedules.Where(z => !string.IsNullOrWhiteSpace(z.teacherId) && z.teacherId.Equals(tmdid)); if (schedulesTeacher.Any()) { courseIds.Add(x.courseId); CourseTask courseTask = x.ToJsonString().ToObject(); courseTask.schedules=schedulesTeacher.ToList(); schoolTeacherTask.Add(new KeyValuePair(x.courseId, courseTask)); groupIds.AddRange(schedulesTeacher.Where(z => !string.IsNullOrWhiteSpace(z.groupId)).Select(x => x.groupId)); } var schedulesAssistant = x.schedules.Where(z => z.assistants.Contains(tmdid)); if (schedulesAssistant.Any()) { courseIds.Add(x.courseId); CourseTask courseTask = x.ToJsonString().ToObject(); courseTask.schedules=schedulesAssistant.ToList(); schoolAssistantTask.Add(new KeyValuePair(x.courseId, courseTask)); groupIds.AddRange(schedulesAssistant.Where(z => !string.IsNullOrWhiteSpace(z.groupId)).Select(x => x.groupId)); } }); } if (courseIds.Any()) { string sqlCourse = $"select value c from c where c.id in ({string.Join(",", courseIds.Select(b => $"'{b}'"))})"; var result = await client.GetContainer(Constant.TEAMModelOS, Constant.School).GetList(sqlCourse, $"CourseBase-{school}"); if (result.list.IsNotEmpty()) { foreach (var item in result.list) { List courseTaskDtos = new List(); var teacher = schoolTeacherTask.Where(x => x.Key.Equals(item.id)).Select(z => new CourseTaskDto { courseTask=z.Value, type="teacher" }); if (teacher.Any()) { courseTaskDtos.AddRange(teacher.ToList()); } var assistant = schoolAssistantTask.Where(x => x.Key.Equals(item.id)).Select(z => new CourseTaskDto { courseTask=z.Value, type="assistant" }); if (assistant.Any()) { courseTaskDtos.AddRange(assistant.ToList()); } schoolCourses.Add(new CourseDto { courseBase=item, courseTasks=courseTaskDtos }); } } } } { HashSet courseIds = new HashSet(); string sqlCoursePrivate = $"select value c.id from c where c.creatorId='{tmdid}'"; var resultCourseBasePrivate = await client.GetContainer(Constant.TEAMModelOS, Constant.Teacher).GetList(sqlCoursePrivate, $"CourseBase"); if (resultCourseBasePrivate.list.IsNotEmpty()) { courseIds=new HashSet(resultCourseBasePrivate.list); } string sqlprivate = $"SELECT distinct value c FROM c join b in c.schedules where c.pk='CourseTask' and (ARRAY_CONTAINS(b.assistants,'{tmdid}')or b.teacherId ='{tmdid}' )"; var resultTeacher = await client.GetContainer(Constant.TEAMModelOS, Constant.Teacher).GetList(sqlprivate, $"CourseTask"); if (resultTeacher.list.IsNotEmpty()) { resultTeacher.list.ForEach(x => { var schedulesTeacher = x.schedules.Where(z => !string.IsNullOrWhiteSpace(z.teacherId) && z.teacherId.Equals(tmdid)); if (schedulesTeacher.Any()) { courseIds.Add(x.courseId); CourseTask courseTask = x.ToJsonString().ToObject(); courseTask.schedules=schedulesTeacher.ToList(); privateTeacherTask.Add(new KeyValuePair(x.courseId, courseTask)); groupIds.AddRange(schedulesTeacher.Where(z => !string.IsNullOrWhiteSpace(z.groupId)).Select(x => x.groupId)); } var schedulesAssistant = x.schedules.Where(z => z.assistants.Contains(tmdid)); if (schedulesAssistant.Any()) { courseIds.Add(x.courseId); CourseTask courseTask = x.ToJsonString().ToObject(); courseTask.schedules=schedulesAssistant.ToList(); privateAssistantTask.Add(new KeyValuePair(x.courseId, courseTask)); groupIds.AddRange(schedulesAssistant.Where(z => !string.IsNullOrWhiteSpace(z.groupId)).Select(x => x.groupId)); } }); } if (courseIds.Any()) { string sqlCourse = $"select value c from c where c.id in ({string.Join(",", courseIds.Select(b => $"'{b}'"))})"; var result = await client.GetContainer(Constant.TEAMModelOS, Constant.Teacher).GetList(sqlCourse, $"CourseBase"); if (result.list.IsNotEmpty()) { foreach (var item in result.list) { List courseTaskDtos = new List(); var teacher = privateTeacherTask.Where(x => x.Key.Equals(item.id)).Select(z => new CourseTaskDto { courseTask=z.Value, type="teacher" }); if (teacher.Any()) { courseTaskDtos.AddRange(teacher.ToList()); } var assistant = privateAssistantTask.Where(x => x.Key.Equals(item.id)).Select(z => new CourseTaskDto { courseTask=z.Value, type="assistant" }); if (assistant.Any()) { courseTaskDtos.AddRange(assistant.ToList()); } teahcerCourses.Add(new CourseDto { courseBase=item, courseTasks=courseTaskDtos }); } } } List courseGroupLists = new List(); _coreAPIHttpService.check=false; groupIds= groupIds.ToHashSet().ToList(); var groupListDatas = await GroupListService.GetMemberByListids(_coreAPIHttpService, client, _dingDing, groupIds.ToHashSet().ToList(), school); string privateGrouplistSQL = $"select value c from c where c.creatorId={tmdid} "; if (groupIds.IsNotEmpty()) { privateGrouplistSQL = $"select value c from c where c.creatorId={tmdid} and c.id not in ({string.Join(",", groupIds.Select(x=>$"'{x}'"))})"; } var resultRGroupList = await client.GetContainer(Constant.TEAMModelOS, Constant.Teacher).GetList(privateGrouplistSQL, "GroupList"); if (resultRGroupList.list.IsNotEmpty()) { CourseGroupList courseGroupList = new CourseGroupList { scope="private", id="default", name="default" }; foreach (var data in resultRGroupList.list) { HashSet groupName = data.members.Where(x => !string.IsNullOrEmpty(x.groupName)).Select(y => y.groupName).ToHashSet(); GroupListGrp groupListGrp = new GroupListGrp(data, groupName); groupListGrp.teachType="teacher"; courseGroupList.groups.Add(groupListGrp); } } foreach (var z in teahcerCourses) { CourseGroupList courseGroupList = new CourseGroupList { scope="private", id=z.courseBase.id, name=z.courseBase.name, periodId=z.courseBase.period?.id, period=z.courseBase.period?.name, subject=z.courseBase.subject?.name, subjectId= z.courseBase.subject?.id }; foreach (var x in z.courseTasks) { foreach (var y in x.courseTask.schedules) { var data = groupListDatas.groups.Find(m => m.id.Equals(y.groupId)); if (data!= null) { HashSet groupName = data.members.Where(x => !string.IsNullOrEmpty(x.groupName)).Select(y => y.groupName).ToHashSet(); GroupListGrp groupListGrp = new GroupListGrp(data, groupName); groupListGrp.teachType=x.type; courseGroupList.groups.Add(groupListGrp); } } } courseGroupLists.Add(courseGroupList); } foreach (var z in schoolCourses) { CourseGroupList courseGroupList = new CourseGroupList { scope="school", id=z.courseBase.id, name=z.courseBase.name, periodId=z.courseBase.period?.id, period=z.courseBase.period?.name, subject=z.courseBase.subject?.name, subjectId= z.courseBase.subject?.id }; foreach (var x in z.courseTasks) { foreach (var y in x.courseTask.schedules) { var data = groupListDatas.groups.Find(m => m.id.Equals(y.groupId)); if (data!= null) { HashSet groupName = data.members.Where(x => !string.IsNullOrEmpty(x.groupName)).Select(y => y.groupName).ToHashSet(); GroupListGrp groupListGrp = new GroupListGrp(data, groupName); groupListGrp.teachType=x.type; courseGroupList.groups.Add(groupListGrp); } } } courseGroupLists.Add(courseGroupList); } long now = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(); foreach (var groups in courseGroupLists) { groups.groups.RemoveAll(z => z.expire>0 && z.expire(id.ToString(), new PartitionKey(code)); GroupChange change = new GroupChange() { client=_client,name=groupList.name}; 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,long time =-1) { List groupLists = new List(); if (groupTypes.IsEmpty() || groupTypes.Contains("class")) { if (!string.IsNullOrWhiteSpace(school) && !school.Equals("SYSTEM_NO_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.StatusCode == System.Net.HttpStatusCode.NotFound) { 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.StatusCode == System.Net.HttpStatusCode.NotFound) { } } } } 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.optNo ,c.expire,c.qrcodeExpire ,c.qrcodeDays ,c.grades "; if (groupTypes.IsEmpty() || groupTypes.Contains("teach")) { //教学班 string teachsql=""; if (!string.IsNullOrWhiteSpace(school) && !school.Equals("SYSTEM_NO_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"). GetItemQueryIteratorSql(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). GetItemQueryIteratorSql(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) && !school.Equals("SYSTEM_NO_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"). GetItemQueryIteratorSql(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) && !school.Equals("SYSTEM_NO_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"). GetItemQueryIteratorSql(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)); } } List groupListSemesters = new List(); List rmembers = new List(); List rgroupList = new List(); List groupListDtos = new List(); if (!string.IsNullOrWhiteSpace(school) && !school.Equals("SYSTEM_NO_SCHOOL") && time>0 && groupLists.IsNotEmpty()) { School schoolBase = await client.GetContainer(Constant.TEAMModelOS, Constant.School).ReadItemAsync(school, new PartitionKey("Base")); foreach (var period in schoolBase.period) { var dataSemester = SchoolService.GetSemester(period,time); //string id = $"{dataSemester.studyYear}-{dataSemester.currSemester.id}-{student.classId}"; string code = $"GroupListSemester-{school}"; string sql = $"select value c from c join m in c.members where m.id='{memberId}' and m.type={memberType} and c.studyYear={dataSemester.studyYear} and c.semesterId='{dataSemester.currSemester.id}' and c.groupListId not in({string.Join(",", groupLists.Select(c => $"'{c.id}'"))}) "; var result = await client.GetContainer(Constant.TEAMModelOS, Constant.School).GetList(sql, code); if (result.list.IsNotEmpty()) { foreach (var x in result.list) { HashSet groupName = x.members.Where(x => !string.IsNullOrEmpty(x.groupName)).Select(y => y.groupName).ToHashSet(); groupLists.Add(new GroupListGrp { id = x.id, code = x.code, periodId = x.periodId, pk = x.pk, name = x.name, school = x.school, creatorId = x.creatorId, no = x.no, scope = x.scope, type = x.type, scount = x.scount, tcount = x.tcount, leader = x.leader, year = x.year, expire = x.expire, groupName = groupName, froms = x.froms, joinLock = x.joinLock, qrcodeExpire = x.qrcodeExpire, qrcodeDays = x.qrcodeDays, review=x.review, limitCount = x.limitCount, optNo = x.optNo, grades = x.grades, }); } } } } 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,int seatNo, string courseId= null,string _client="web") { 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").GetItemQueryIteratorSql(queryText: queryNo, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"GroupList-{school}") })) { data = await JoinList(_azureRedis, item, userid, type, school,year,seatNo,_client:_client); break; } } await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "Teacher").GetItemQueryIteratorSql(queryText: queryNo, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"GroupList") })) { if (item.joinLock == 0) { //状态=4 表示未开放加入。 return (4, item, null) ; } if (item.review ==1) { var mb = item.members.FindAll(x => x.id.Equals(userid) && x.type==type); if (mb.IsNotEmpty()) { return (2, item, null); } //状态=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, seatNo=seatNo }; 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 =await JoinList(_azureRedis, item, userid, type, school,year,seatNo, _client: _client); //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 已过期,3已经加入。 /// public int status { get; set; } = -1; public int seatNo { get; set; } public List courses { get; set; }= new List(); } public static async Task<(int status, GroupList stuList, Member member)> JoinList(AzureRedisFactory azureRedis, GroupList stuList, string userid, int type, string school, int year, int seatNo = 0,string _client="web") { Member member = null; int status = -1; if (!string.IsNullOrWhiteSpace(stuList.school) && !string.IsNullOrWhiteSpace(school)) { if (!stuList.school.Equals(school)) { status = 3;//不允许跨校加入名单 return (status, stuList,null); } } if (seatNo>0) { var mb= stuList.members.Find(x => x.irs.Equals($"{seatNo}")); if (mb==null) { 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 = $"{seatNo}", no = $"{seatNo}", year=year,manual=1 }; 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 = $"{seatNo}", no = $"{seatNo}", year = year, manual=1 }; stuList.members.Add(member); } } return (status, stuList, member); } } 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; } } } 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,string _client ) { 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() { name=list.name, client=_client, type = list.type, listid = list.id, scope = list.scope, originCode = list.school, school = list.school, creatorId = list.creatorId, periodId = list.periodId, }; 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); } } // list.periodId=list.members.FindAll(x=>!string.IsNullOrEmpty(x.periodId)) 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").GetItemQueryStreamIteratorSql(queryText: queryNo, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"{list.code}") })) { using var jsonNo = await JsonDocument.ParseAsync(item.Content); 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").GetItemQueryStreamIteratorSql(queryText: queryNo, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey("GroupList") })) { using var jsonNo = await JsonDocument.ParseAsync(item.Content); 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.optNo,c.expire ,c.qrcodeExpire,c.qrcodeDays ,c.grades ", int graduate = -1,long time=-1) { List groupLists = new List(); 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>(); var semesterGroupList = await GetGroupListSemester(client, classes, school, type: null, periodId: null, no: null, time); groupLists.AddRange(semesterGroupList.groupListDtos); classes = classes.Except(semesterGroupList.rgroupList.Select(y => y.id)).ToList(); if (classes.IsNotEmpty()) { //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").GetItemQueryIteratorSql(queryText: $"select {SummarySql} from c where c.id in ({sql})", requestOptions: new QueryRequestOptions() { PartitionKey = new 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()) { string insql = string.Join(",", classes.Select(x => $"'{x}'")); //搜寻没有关联学生的行政班 await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "School").GetItemQueryIteratorSql(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 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()) { string sql = string.Join(",", classes.Select(x => $"'{x}'")); List privateList = new List(); sql = string.Join(",", classes.Select(x => $"'{x}'")); await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "Teacher").GetItemQueryIteratorSql(queryText: $"select {SummarySql} from c where c.id in ({sql})", requestOptions: new QueryRequestOptions() { PartitionKey = new 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; } public static async Task<(List groupListSemesters, List rmembers, List rgroupList, List groupListDtos)> GetGroupListSemester(CosmosClient client, List classes, string school,string type,string periodId,string no , long time =-1) { List groupListSemesters = new List(); List rmembers = new List(); List rgroupList = new List(); List groupListDtos = new List(); if (!string.IsNullOrWhiteSpace(school) && !school.Equals("SYSTEM_NO_SCHOOL") && time>0) { School schoolBase = await client.GetContainer(Constant.TEAMModelOS, Constant.School).ReadItemAsync(school, new PartitionKey("Base")); foreach (var period in schoolBase.period) { var dataSemester = SchoolService.GetSemester(period, time); //string id = $"{dataSemester.studyYear}-{dataSemester.currSemester.id}-{student.classId}"; string code = $"GroupListSemester-{school}"; StringBuilder sql =new StringBuilder($"select value c from c where c.studyYear={dataSemester.studyYear} and c.semesterId='{dataSemester.currSemester.id}' "); if (classes.IsNotEmpty()) { sql.Append($" and c.groupListId in({string.Join(",", classes.Select(c => $"'{c}'"))})"); } if (!string.IsNullOrWhiteSpace(type)) { sql.Append($" and c.type ='{type}'"); } if (!string.IsNullOrWhiteSpace(periodId)) { sql.Append($" and c.periodId ='{periodId}'"); } if (!string.IsNullOrWhiteSpace(no)) { sql.Append($" and c.no ='{no}'"); } var result = await client.GetContainer(Constant.TEAMModelOS, Constant.School).GetList(sql.ToString(), code); if (result.list.IsNotEmpty()) { groupListSemesters.AddRange(result.list); } } if (groupListSemesters.IsNotEmpty()) { rmembers.AddRange(groupListSemesters.SelectMany(x => x.members)); rmembers= rmembers.FindAll(x => x.type == 2).Where((x, i) => rmembers.FindAll(x => x.type == 2).FindIndex(n => n.id.Equals(x.id) && n.code.Equals(x.code)) == i).ToList(); rgroupList.AddRange(groupListSemesters.Select(z => new RGroupList { id = z.groupListId, code= $"GroupList-{school}", pk="GroupList", name=z.name, no=z.no, periodId=z.periodId, school=z.school, scope=z.scope, creatorId=z.creatorId, type=z.type, year=z.year, expire=z.expire, tcount=z.tcount, scount=z.scount, members=z.members, leader=z.leader, froms=z.froms, joinLock=z.joinLock, graduate=z.graduate, review=z.review, optNo=z.optNo, limitCount=z.limitCount, qrcodeDays=z.qrcodeDays, qrcodeExpire=z.qrcodeExpire, grades =z.grades, })); groupListDtos.AddRange(groupListSemesters.Select(z => new GroupListDto { id = z.groupListId, code= $"GroupList-{school}", pk="GroupList", name=z.name, no=z.no, periodId=z.periodId, school=z.school, scope=z.scope, creatorId=z.creatorId, type=z.type, year=z.year, expire=z.expire, tcount=z.tcount, scount=z.scount, leader=z.leader, froms=z.froms, joinLock=z.joinLock, graduate=z.graduate, review=z.review, optNo=z.optNo, limitCount=z.limitCount, qrcodeDays=z.qrcodeDays, qrcodeExpire=z.qrcodeExpire, grades =z.grades, })); } } return (groupListSemesters,rmembers, rgroupList,groupListDtos); } /// /// 根据任意名单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,long time =-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"). GetItemQueryIteratorSql(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 { var semesterGroupList = await GetGroupListSemester(client, classes, school,type:null,periodId:null ,no:null, time); if (semesterGroupList.rgroupList.IsNotEmpty()) { groupLists.AddRange(semesterGroupList.rgroupList); members.AddRange(semesterGroupList.rmembers); } classes = classes.Except(semesterGroupList.rgroupList.Select(y => y.id)).ToList(); if (classes.IsNotEmpty()) { 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").GetItemQueryIteratorSql(queryText: queryText, requestOptions: new QueryRequestOptions() { PartitionKey = new 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").GetItemQueryIteratorSql(queryText: $"select value(c) from c where c.classId in ({sql})", requestOptions: new QueryRequestOptions() { PartitionKey = new 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") .GetItemQueryIteratorSql(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 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").GetItemQueryIteratorSql(queryText: $"select value(c) from c where c.id in ({sql})", requestOptions: new QueryRequestOptions() { PartitionKey = new 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"). GetItemQueryIteratorSql(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 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; } } //簡易課程名單處理 List mebList = x.members.Where(z => z.type.Equals(3)).ToList(); if(mebList.Count > 0) { foreach(RMember mb in mebList) { if(string.IsNullOrWhiteSpace(mb.name) && !string.IsNullOrWhiteSpace(mb.nickname)) { mb.name = mb.nickname; } } members.AddRange(mebList); } }); return (members, groupLists); } } /// /// 根据名单类型获取名单及成员信息。 /// /// /// /// /// /// /// /// 毕业类型0在校,1毕业 , -1查全部。 /// public static async Task> GetGroupListByType(CosmosClient client, string type, School school, Models.Period period, int graduate = -1) { List classes = new List(); List grd = new List (); int index = 0; period.grades.ForEach(z => { grd.Add(index); index+=1; }); var yearsdata = SchoolService.GetYears(school, period.id, grd); List years = yearsdata.years.ToList(); if (years.IsNotEmpty()) { StringBuilder sql = new StringBuilder($"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.year in ({string.Join(",", years)}) and c.periodId='{period.id}' "); if (graduate!=-1) { sql.Append($" and c.graduate={graduate} "); } var result = await client.GetContainer(Constant.TEAMModelOS, Constant.School).GetList(sql.ToString(), $"Class-{school.id}"); foreach (var item in result.list) { GroupListDto group = new GroupListDto { id = item.id, code = $"GroupList-{school.id}", name = item.name, periodId = item.periodId, scope = "school", school = school.id, type = "class", expire= item.expire, year = item.year, no = item.no, leader = item.leader, pk = "GroupList", graduate = item.graduate, grades= new HashSet { item.year } }; classes.Add(group); } } return classes; } /// /// 根据名单类型获取名单及成员信息。 /// /// /// /// /// /// /// /// 毕业类型0在校,1毕业 , -1查全部。 /// public static async Task> GetGroupListMemberByType(CoreAPIHttpService _coreAPIHttpService, CosmosClient client, string type, List scopes, string school, DingDing _dingDing, int graduate = -1,long time =-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").GetItemQueryIteratorSql(queryText: sql.ToString(), requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"GroupList-{school}") })) { groupLists.Add(item); } groups.Add("School", groupLists); if (!string.IsNullOrWhiteSpace(school) && !school.Equals("SYSTEM_NO_SCHOOL") && time>0 && groupLists.IsNotEmpty()) { School schoolBase = await client.GetContainer(Constant.TEAMModelOS, Constant.School).ReadItemAsync(school, new PartitionKey("Base")); foreach (var period in schoolBase.period) { var dataSemester = SchoolService.GetSemester(period, time); //string id = $"{dataSemester.studyYear}-{dataSemester.currSemester.id}-{student.classId}"; string code = $"GroupListSemester-{school}"; string sqlSem = $"select value c from c where c.type='{type}' and c.studyYear={dataSemester.studyYear} and c.semesterId='{dataSemester.currSemester.id}' and c.groupListId not in({string.Join(",", groupLists.Select(c => $"'{c.id}'"))}) "; var result = await client.GetContainer(Constant.TEAMModelOS, Constant.School).GetList(sqlSem, code); if (result.list.IsNotEmpty()) { foreach (var x in result.list) { HashSet groupName = x.members.Where(x => !string.IsNullOrEmpty(x.groupName)).Select(y => y.groupName).ToHashSet(); groupLists.Add(new RGroupList { id = x.groupListId, code = $"GroupList-{school}", periodId = x.periodId, pk = x.pk, name = x.name, school = x.school, creatorId = x.creatorId, no = x.no, scope = x.scope, type = x.type, scount = x.scount, tcount = x.tcount, leader = x.leader, year = x.year, expire = x.expire, graduate = x.graduate, members = x.members, froms = x.froms, joinLock = x.joinLock, qrcodeExpire = x.qrcodeExpire, optNo = x.optNo, qrcodeDays = x.qrcodeDays, review=x.review, limitCount = x.limitCount, grades = x.grades, }); } } } } } } else if (scopes.Contains("private")) { List groupLists = new List(); await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "Teacher").GetItemQueryIteratorSql(queryText: sql.ToString(), requestOptions: new QueryRequestOptions() { PartitionKey = new 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(); List simples = members.FindAll(x => x.type == 3).Where((x, i) => members.FindAll(x => x.type == 3).FindIndex(n => n.id.Equals(x.id)) == 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").GetItemQueryIteratorSql(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").GetItemQueryIteratorSql(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) && !school.Equals("SYSTEM_NO_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").GetItemQueryIteratorSql(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).GetItemQueryIteratorSql(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).GetItemQueryIteratorSql(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)); } } //簡易課程成員處理邏輯 if(simples.IsNotEmpty()) { } 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; } } } if (!x.scope.Equals("private")) { 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").GetItemQueryIteratorSql(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; } } } }