var lstOverdue = table.AsEnumerable().Select(row => new GJSXItem
            {
                DateDiffDays = Convert.ToInt32(row["DateDiffDays"]),
                GJSXID = row["GJSXID"].ToString(),
                ProjectId = row["ProjectId"].ToString(),
                ProjectName = row["ProjectName"].ToString(),
                UnitName = row["UnitName"].ToString(),
                Detail = row["Detail"].ToString(),
                CNProfessionalName = row["CNProfessionalName"].ToString(),
                QuestionTypeName = row["QuestionTypeName"].ToString(),
                GJSXTypeName = row["GJSXTypeName"].ToString(),
                UserID = row["UserID"].ToString(),
                UserName = row["UserName"].ToString(),
                //UserEmail = row["UserEmail"].ToString(),
                User_ReceiveUserId = row["User_ReceiveUserId"].ToString(),
                User_ReceiveUserName = row["User_ReceiveUserName"].ToString(),
                //User_ReceiveUserEmail = row["User_ReceiveUserEmail"].ToString(),
                User_AcceptanceUserId = row["User_AcceptanceUserId"].ToString(),
                User_AcceptanceUserName = row["User_AcceptanceUserName"].ToString(),
                //User_AcceptanceUserEmail = row["User_AcceptanceUserEmail"].ToString(),
                User_CsUserIds = row["User_CsUserIds"].ToString(),
                User_CsUsers = row["User_CsUsers"].ToString(),
                //User_CsUsersUserEmail = row["User_CsUsersUserEmail"].ToString(),
                CompleteDate = Convert.ToDateTime(row["CompleteDate"].ToString())
            }).ToList();
            var gItem = lstOverdue.FirstOrDefault();
            if (gItem != null)
            {
                userIds.Add(gItem.User_AcceptanceUserId);
                if (!string.IsNullOrWhiteSpace(gItem.User_CsUserIds))
                {
                    userIds.AddRange(gItem.User_CsUserIds.Split(','));
                }
                foreach (var userId in userIds)
                {
                    var user = UserService.GetUserByUserId(userId);
                    if (!string.IsNullOrWhiteSpace(user.Email))
                    {
                        MailMessage mail = new MailMessage();
                        //邮件主题
                        if (userId == gItem.User_AcceptanceUserId)
                        {
                            mail.Subject = $"你有新的关键事项了——{gItem.ProjectName}";
                        }
                        else
                        {
                            mail.Subject = $"有新的关键事项抄送你了——{gItem.ProjectName}";
                        }
                        mail.To.Add(user.Email);
                        //mail.To.Add("test@test.com");
                        mail.IsBodyHtml = true;//确保邮件正文被当作HTML解析
                                               //邮件正文
                        string bodyStr = $@"
新的关键事项信息
项目名称:{gItem.ProjectName}
事项编号:{gItem.GJSXID}
责任单位:{gItem.UnitName}
专业:{gItem.CNProfessionalName}
事项类别:{gItem.GJSXTypeName}
紧急程度:{gItem.QuestionTypeName}
事项描述:{gItem.Detail}
提出人:{gItem.UserName}
责任人:{gItem.User_AcceptanceUserName}
跟踪人:{gItem.User_ReceiveUserName}
抄送人:{gItem.User_CsUsers}
约定完成日期:{gItem.CompleteDate.ToShortDateString()}
智慧施工管理信息系统
请点击此处,进入智慧施工管理信息系统,查看事项详情
登录账号:{user.Account}
登录密码:CWCEC.+身份证号后四位(示例:CWCEC.1234)
";
                        //< p > 登录密码:{ user.RawPassword} p >
                        mail.Body = bodyStr;
                        try
                        {
                            bool send = PushEmail(mail);
                        }
                        catch (Exception ex)
                        {
                            //ErrLogInfo.WriteLog($"关键事项通知提醒责任人;项目名称:{gItem.ProjectName},事项编号:{gItem.GJSXID}", ex);
                            ErrLogInfo.WriteLog($"【新增关键事项通知提醒责任人邮箱提醒异常】邮箱:{user.Email};项目名称:{gItem.ProjectName},事项编号:{gItem.GJSXID};时间:{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")};异常信息:{ex.Message}");
                            continue;
                        }
                    }
                }
            }
        }
        /// 
        /// 关键事项申请关闭通知提醒提出人和跟踪人
        /// 
        /// 
        /// 
        public static void GJSXApplyCloseNoticeSendEmail(string gjsxId, string detail)
        {
            List userIds = new List();
            string strSql = $@"select 
                                    DATEDIFF(DAY, CompleteDate, isnull(CloseDate,getdate())) AS DateDiffDays
                                    ,a.GJSXID,a.ProjectId,a.Detail,a.createDate,Base_Project.ProjectName,Base_Unit.UnitName,a.CloseDate,a.IsManypeople,a.CompleteDate,a.AttachUrl
                                    ,case a.state when 2 then '正在进行' when 3 then '待办' when 0 then '已关闭' when 1 then '开放' end as state
                                    ,CNProfessionalName = STUFF((SELECT ',' + Base_CNProfessional.ProfessionalName FROM dbo.Base_CNProfessional where PATINDEX('%,' + RTRIM(Base_CNProfessional.CNProfessionalId) + ',%', ',' + a.CNProfessional_ID + ',') > 0 FOR XML PATH('')), 1, 1,'')
                                    ,QuestionTypeName = STUFF((SELECT ',' + Base_QuestionType.QuestionTypeName FROM dbo.Base_QuestionType where PATINDEX('%,' + RTRIM(Base_QuestionType.QuestionTypeID) + ',%', ',' + a.QuestionTypeID + ',') > 0 FOR XML PATH('')), 1, 1,'')
                                    ,GJSXTypeName = STUFF((SELECT ',' + Base_GJSXType.GJSXTypeName FROM dbo.Base_GJSXType where PATINDEX('%,' + RTRIM(Base_GJSXType.GJSXTypeID) + ',%', ',' + a.GJSXTypeID + ',') > 0 FOR XML PATH('')), 1, 1,'')
                                    ,a.UserID,b.UserName 
                                    --,b.Email as UserEmail
                                    ,a.User_ReceiveID as User_ReceiveUserId
                                    ,User_ReceiveUserName = STUFF((SELECT ',' + p2.UserName FROM dbo.Sys_User as p2 where PATINDEX('%,' + RTRIM(p2.UserId) + ',%', ',' + a.User_ReceiveID + ',') > 0 FOR XML PATH('')), 1, 1,'') 
                                    --,User_ReceiveUserEmail = STUFF((SELECT ',' + p2.Email FROM dbo.Sys_User as p2 where PATINDEX('%,' + RTRIM(p2.UserId) + ',%', ',' + a.User_ReceiveID + ',') > 0 FOR XML PATH('')), 1, 1,'') 
                                    ,a.user_Acceptance as User_AcceptanceUserId
                                    ,User_AcceptanceUserName = STUFF((SELECT ',' + p2.UserName FROM dbo.Sys_User as p2 where PATINDEX('%,' + RTRIM(p2.UserId) + ',%', ',' + a.user_Acceptance + ',') > 0 FOR XML PATH('')), 1, 1,'') 
                                    --,User_AcceptanceUserEmail = STUFF((SELECT ',' + p2.Email FROM dbo.Sys_User as p2 where PATINDEX('%,' + RTRIM(p2.UserId) + ',%', ',' + a.user_Acceptance + ',') > 0 FOR XML PATH('')), 1, 1,'') 
                                    ,a.CsUsers as User_CsUserIds
                                    ,User_CsUsers = STUFF((SELECT ',' + p2.UserName FROM dbo.Sys_User as p2 where PATINDEX('%,' + RTRIM(p2.UserId) + ',%', ',' + a.CsUsers + ',') > 0 FOR XML PATH('')), 1, 1,'') 
                                    --,User_CsUsersUserEmail = STUFF((SELECT ',' + p2.Email FROM dbo.Sys_User as p2 where PATINDEX('%,' + RTRIM(p2.UserId) + ',%', ',' + a.CsUsers + ',') > 0 FOR XML PATH('')), 1, 1,'') 
                                    from GJSX as a 
                                    left join Sys_User as b on a.UserId = b.UserId
                                    left join[dbo].[Base_Project] on a.ProjectId = Base_Project.ProjectId
                                    left join[dbo].[Base_Unit] on a.UnitId = Base_Unit.UnitId
                                where 1=1 and a.GJSXID = '{gjsxId}'  ";
            List listStr = new List();
            SqlParameter[] parameter = listStr.ToArray();
            DataTable table = SQLHelper.GetDataTableRunText(strSql, parameter);
            // 使用LINQ将DataTable转换为List
            var lstOverdue = table.AsEnumerable().Select(row => new GJSXItem
            {
                DateDiffDays = Convert.ToInt32(row["DateDiffDays"]),
                GJSXID = row["GJSXID"].ToString(),
                ProjectId = row["ProjectId"].ToString(),
                ProjectName = row["ProjectName"].ToString(),
                UnitName = row["UnitName"].ToString(),
                Detail = row["Detail"].ToString(),
                CNProfessionalName = row["CNProfessionalName"].ToString(),
                QuestionTypeName = row["QuestionTypeName"].ToString(),
                GJSXTypeName = row["GJSXTypeName"].ToString(),
                UserID = row["UserID"].ToString(),
                UserName = row["UserName"].ToString(),
                //UserEmail = row["UserEmail"].ToString(),
                User_ReceiveUserId = row["User_ReceiveUserId"].ToString(),
                User_ReceiveUserName = row["User_ReceiveUserName"].ToString(),
                //User_ReceiveUserEmail = row["User_ReceiveUserEmail"].ToString(),
                User_AcceptanceUserId = row["User_AcceptanceUserId"].ToString(),
                User_AcceptanceUserName = row["User_AcceptanceUserName"].ToString(),
                //User_AcceptanceUserEmail = row["User_AcceptanceUserEmail"].ToString(),
                User_CsUserIds = row["User_CsUserIds"].ToString(),
                User_CsUsers = row["User_CsUsers"].ToString(),
                //User_CsUsersUserEmail = row["User_CsUsersUserEmail"].ToString(),
                CompleteDate = Convert.ToDateTime(row["CompleteDate"].ToString())
            }).ToList();
            var gItem = lstOverdue.FirstOrDefault();
            if (gItem != null)
            {
                userIds.Add(gItem.UserID);
                userIds.Add(gItem.User_ReceiveUserId);
                foreach (var userId in userIds)
                {
                    var user = UserService.GetUserByUserId(userId);
                    if (!string.IsNullOrWhiteSpace(user.Email))
                    {
                        MailMessage mail = new MailMessage();
                        //邮件主题
                        mail.Subject = $"有新的事项申请关闭——{gItem.ProjectName}";
                        mail.To.Add(user.Email);
                        //mail.To.Add("test@test.com");
                        mail.IsBodyHtml = true;//确保邮件正文被当作HTML解析
                                               //邮件正文
                        string bodyStr = $@"
事项申请关闭
项目名称:{gItem.ProjectName}
事项编号:{gItem.GJSXID}
责任单位:{gItem.UnitName}
专业:{gItem.CNProfessionalName}
事项类别:{gItem.GJSXTypeName}
紧急程度:{gItem.QuestionTypeName}
事项描述:{gItem.Detail}
提出人:{gItem.UserName}
责任人:{gItem.User_AcceptanceUserName}
跟踪人:{gItem.User_ReceiveUserName}
抄送人:{gItem.User_CsUsers}
约定完成日期:{gItem.CompleteDate.ToShortDateString()}
申请关闭说明:{detail}
智慧施工管理信息系统
请点击此处,进入智慧施工管理信息系统,查看事项详情
登录账号:{user.Account}
登录密码:CWCEC.+身份证号后四位(示例:CWCEC.1234)
";
                        //< p > 登录密码:{ user.RawPassword} p >
                        mail.Body = bodyStr;
                        try
                        {
                            bool send = PushEmail(mail);
                        }
                        catch (Exception ex)
                        {
                            //ErrLogInfo.WriteLog($"关键事项申请关闭通知提醒责任人;项目名称:{gItem.ProjectName},事项编号:{gItem.GJSXID}", ex);
                            ErrLogInfo.WriteLog($"【申请关闭通知提醒责任人邮箱提醒异常】邮箱:{user.Email};项目名称:{gItem.ProjectName},事项编号:{gItem.GJSXID};时间:{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")};异常信息:{ex.Message}");
                            continue;
                        }
                    }
                }
            }
        }
        /// 
        /// 关键事项驳回申请关闭通知提醒责任人
        /// 
        /// 
        /// 
        public static void GJSXDisallowApplyCloseNoticeSendEmail(string gjsxId, string detail)
        {
            List userIds = new List();
            string strSql = $@"select 
                                    DATEDIFF(DAY, CompleteDate, isnull(CloseDate,getdate())) AS DateDiffDays
                                    ,a.GJSXID,a.ProjectId,a.Detail,a.createDate,Base_Project.ProjectName,Base_Unit.UnitName,a.CloseDate,a.IsManypeople,a.CompleteDate,a.AttachUrl
                                    ,case a.state when 2 then '正在进行' when 3 then '待办' when 0 then '已关闭' when 1 then '开放' end as state
                                    ,CNProfessionalName = STUFF((SELECT ',' + Base_CNProfessional.ProfessionalName FROM dbo.Base_CNProfessional where PATINDEX('%,' + RTRIM(Base_CNProfessional.CNProfessionalId) + ',%', ',' + a.CNProfessional_ID + ',') > 0 FOR XML PATH('')), 1, 1,'')
                                    ,QuestionTypeName = STUFF((SELECT ',' + Base_QuestionType.QuestionTypeName FROM dbo.Base_QuestionType where PATINDEX('%,' + RTRIM(Base_QuestionType.QuestionTypeID) + ',%', ',' + a.QuestionTypeID + ',') > 0 FOR XML PATH('')), 1, 1,'')
                                    ,GJSXTypeName = STUFF((SELECT ',' + Base_GJSXType.GJSXTypeName FROM dbo.Base_GJSXType where PATINDEX('%,' + RTRIM(Base_GJSXType.GJSXTypeID) + ',%', ',' + a.GJSXTypeID + ',') > 0 FOR XML PATH('')), 1, 1,'')
                                    ,a.UserID,b.UserName 
                                    --,b.Email as UserEmail
                                    ,a.User_ReceiveID as User_ReceiveUserId
                                    ,User_ReceiveUserName = STUFF((SELECT ',' + p2.UserName FROM dbo.Sys_User as p2 where PATINDEX('%,' + RTRIM(p2.UserId) + ',%', ',' + a.User_ReceiveID + ',') > 0 FOR XML PATH('')), 1, 1,'') 
                                    --,User_ReceiveUserEmail = STUFF((SELECT ',' + p2.Email FROM dbo.Sys_User as p2 where PATINDEX('%,' + RTRIM(p2.UserId) + ',%', ',' + a.User_ReceiveID + ',') > 0 FOR XML PATH('')), 1, 1,'') 
                                    ,a.user_Acceptance as User_AcceptanceUserId
                                    ,User_AcceptanceUserName = STUFF((SELECT ',' + p2.UserName FROM dbo.Sys_User as p2 where PATINDEX('%,' + RTRIM(p2.UserId) + ',%', ',' + a.user_Acceptance + ',') > 0 FOR XML PATH('')), 1, 1,'') 
                                    --,User_AcceptanceUserEmail = STUFF((SELECT ',' + p2.Email FROM dbo.Sys_User as p2 where PATINDEX('%,' + RTRIM(p2.UserId) + ',%', ',' + a.user_Acceptance + ',') > 0 FOR XML PATH('')), 1, 1,'') 
                                    ,a.CsUsers as User_CsUserIds
                                    ,User_CsUsers = STUFF((SELECT ',' + p2.UserName FROM dbo.Sys_User as p2 where PATINDEX('%,' + RTRIM(p2.UserId) + ',%', ',' + a.CsUsers + ',') > 0 FOR XML PATH('')), 1, 1,'') 
                                    --,User_CsUsersUserEmail = STUFF((SELECT ',' + p2.Email FROM dbo.Sys_User as p2 where PATINDEX('%,' + RTRIM(p2.UserId) + ',%', ',' + a.CsUsers + ',') > 0 FOR XML PATH('')), 1, 1,'') 
                                    from GJSX as a 
                                    left join Sys_User as b on a.UserId = b.UserId
                                    left join[dbo].[Base_Project] on a.ProjectId = Base_Project.ProjectId
                                    left join[dbo].[Base_Unit] on a.UnitId = Base_Unit.UnitId
                                where 1=1 and a.GJSXID = '{gjsxId}'  ";
            List listStr = new List();
            SqlParameter[] parameter = listStr.ToArray();
            DataTable table = SQLHelper.GetDataTableRunText(strSql, parameter);
            // 使用LINQ将DataTable转换为List
            var lstOverdue = table.AsEnumerable().Select(row => new GJSXItem
            {
                DateDiffDays = Convert.ToInt32(row["DateDiffDays"]),
                GJSXID = row["GJSXID"].ToString(),
                ProjectId = row["ProjectId"].ToString(),
                ProjectName = row["ProjectName"].ToString(),
                UnitName = row["UnitName"].ToString(),
                Detail = row["Detail"].ToString(),
                CNProfessionalName = row["CNProfessionalName"].ToString(),
                QuestionTypeName = row["QuestionTypeName"].ToString(),
                GJSXTypeName = row["GJSXTypeName"].ToString(),
                UserID = row["UserID"].ToString(),
                UserName = row["UserName"].ToString(),
                //UserEmail = row["UserEmail"].ToString(),
                User_ReceiveUserId = row["User_ReceiveUserId"].ToString(),
                User_ReceiveUserName = row["User_ReceiveUserName"].ToString(),
                //User_ReceiveUserEmail = row["User_ReceiveUserEmail"].ToString(),
                User_AcceptanceUserId = row["User_AcceptanceUserId"].ToString(),
                User_AcceptanceUserName = row["User_AcceptanceUserName"].ToString(),
                //User_AcceptanceUserEmail = row["User_AcceptanceUserEmail"].ToString(),
                User_CsUserIds = row["User_CsUserIds"].ToString(),
                User_CsUsers = row["User_CsUsers"].ToString(),
                //User_CsUsersUserEmail = row["User_CsUsersUserEmail"].ToString(),
                CompleteDate = Convert.ToDateTime(row["CompleteDate"].ToString())
            }).ToList();
            var gItem = lstOverdue.FirstOrDefault();
            if (gItem != null)
            {
                userIds.Add(gItem.User_AcceptanceUserId);
                foreach (var userId in userIds)
                {
                    var user = UserService.GetUserByUserId(userId);
                    if (!string.IsNullOrWhiteSpace(user.Email))
                    {
                        MailMessage mail = new MailMessage();
                        //邮件主题
                        mail.Subject = $"有事项申请关闭被驳回了——{gItem.ProjectName}";
                        mail.To.Add(user.Email);
                        //mail.To.Add("test@test.com");
                        mail.IsBodyHtml = true;//确保邮件正文被当作HTML解析
                                               //邮件正文
                        string bodyStr = $@"
事项申请关闭被驳回
项目名称:{gItem.ProjectName}
事项编号:{gItem.GJSXID}
责任单位:{gItem.UnitName}
专业:{gItem.CNProfessionalName}
事项类别:{gItem.GJSXTypeName}
紧急程度:{gItem.QuestionTypeName}
事项描述:{gItem.Detail}
提出人:{gItem.UserName}
责任人:{gItem.User_AcceptanceUserName}
跟踪人:{gItem.User_ReceiveUserName}
抄送人:{gItem.User_CsUsers}
约定完成日期:{gItem.CompleteDate.ToShortDateString()}
驳回申请关闭说明:{detail}
智慧施工管理信息系统
请点击此处,进入智慧施工管理信息系统,查看事项详情
登录账号:{user.Account}
登录密码:CWCEC.+身份证号后四位(示例:CWCEC.1234)
";
                        //< p > 登录密码:{ user.RawPassword} p >
                        mail.Body = bodyStr;
                        try
                        {
                            bool send = PushEmail(mail);
                        }
                        catch (Exception ex)
                        {
                            //ErrLogInfo.WriteLog($"关键事项申请关闭驳回通知提醒责任人;项目名称:{gItem.ProjectName},事项编号:{gItem.GJSXID}", ex);
                            ErrLogInfo.WriteLog($"【驳回申请关闭通知提醒责任人邮箱提醒异常】邮箱:{user.Email};项目名称:{gItem.ProjectName},事项编号:{gItem.GJSXID};时间:{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")};异常信息:{ex.Message}");
                            continue;
                        }
                    }
                }
            }
        }
        /// 
        /// 关键事项超期预警定时提醒发送邮箱
        /// 
        public static void OverdueWarningSendEmail()
        {
            try
            {
                Model.SGGLDB db = Funs.DB;
                //取未关闭且已经超期的数据
                string strSql = @"select 
                                    DATEDIFF(DAY, CompleteDate, isnull(CloseDate,getdate())) AS DateDiffDays
                                    ,a.GJSXID,a.ProjectId,a.Detail,a.createDate,Base_Project.ProjectName,Base_Unit.UnitName,a.CloseDate,a.IsManypeople,a.CompleteDate,a.AttachUrl
                                    ,case a.state when 2 then '正在进行' when 3 then '待办' when 0 then '已关闭' when 1 then '开放' end as state
                                    ,CNProfessionalName = STUFF((SELECT ',' + Base_CNProfessional.ProfessionalName FROM dbo.Base_CNProfessional where PATINDEX('%,' + RTRIM(Base_CNProfessional.CNProfessionalId) + ',%', ',' + a.CNProfessional_ID + ',') > 0 FOR XML PATH('')), 1, 1,'')
                                    ,QuestionTypeName = STUFF((SELECT ',' + Base_QuestionType.QuestionTypeName FROM dbo.Base_QuestionType where PATINDEX('%,' + RTRIM(Base_QuestionType.QuestionTypeID) + ',%', ',' + a.QuestionTypeID + ',') > 0 FOR XML PATH('')), 1, 1,'')
                                    ,GJSXTypeName = STUFF((SELECT ',' + Base_GJSXType.GJSXTypeName FROM dbo.Base_GJSXType where PATINDEX('%,' + RTRIM(Base_GJSXType.GJSXTypeID) + ',%', ',' + a.GJSXTypeID + ',') > 0 FOR XML PATH('')), 1, 1,'')
                                    ,a.UserID,b.UserName 
                                    --,b.Email as UserEmail
                                    ,a.User_ReceiveID as User_ReceiveUserId
                                    ,User_ReceiveUserName = STUFF((SELECT ',' + p2.UserName FROM dbo.Sys_User as p2 where PATINDEX('%,' + RTRIM(p2.UserId) + ',%', ',' + a.User_ReceiveID + ',') > 0 FOR XML PATH('')), 1, 1,'') 
                                    --,User_ReceiveUserEmail = STUFF((SELECT ',' + p2.Email FROM dbo.Sys_User as p2 where PATINDEX('%,' + RTRIM(p2.UserId) + ',%', ',' + a.User_ReceiveID + ',') > 0 FOR XML PATH('')), 1, 1,'') 
                                    ,a.user_Acceptance as User_AcceptanceUserId
                                    ,User_AcceptanceUserName = STUFF((SELECT ',' + p2.UserName FROM dbo.Sys_User as p2 where PATINDEX('%,' + RTRIM(p2.UserId) + ',%', ',' + a.user_Acceptance + ',') > 0 FOR XML PATH('')), 1, 1,'') 
                                    --,User_AcceptanceUserEmail = STUFF((SELECT ',' + p2.Email FROM dbo.Sys_User as p2 where PATINDEX('%,' + RTRIM(p2.UserId) + ',%', ',' + a.user_Acceptance + ',') > 0 FOR XML PATH('')), 1, 1,'') 
                                    ,a.CsUsers as User_CsUserIds
                                    ,User_CsUsers = STUFF((SELECT ',' + p2.UserName FROM dbo.Sys_User as p2 where PATINDEX('%,' + RTRIM(p2.UserId) + ',%', ',' + a.CsUsers + ',') > 0 FOR XML PATH('')), 1, 1,'') 
                                    --,User_CsUsersUserEmail = STUFF((SELECT ',' + p2.Email FROM dbo.Sys_User as p2 where PATINDEX('%,' + RTRIM(p2.UserId) + ',%', ',' + a.CsUsers + ',') > 0 FOR XML PATH('')), 1, 1,'') 
                                from GJSX as a 
                                    left join Sys_User as b on a.UserId = b.UserId
                                    left join[dbo].[Base_Project] on a.ProjectId = Base_Project.ProjectId
                                    left join[dbo].[Base_Unit] on a.UnitId = Base_Unit.UnitId
                                where 1=1 and Base_Project.ProjectState=1 and a.state<>'0' and a.state<>'1' and (GETDATE()>a.CompleteDate or DATEDIFF(DAY, CompleteDate, isnull(CloseDate,getdate()))=-7 or DATEDIFF(DAY, CompleteDate, isnull(CloseDate,getdate()))=-6 or DATEDIFF(DAY, CompleteDate, isnull(CloseDate,getdate()))=-1 )   ";
                List listStr = new List();
                SqlParameter[] parameter = listStr.ToArray();
                DataTable table = SQLHelper.GetDataTableRunText(strSql, parameter);
                // 使用LINQ将DataTable转换为List
                var lstOverdue = table.AsEnumerable().Select(row => new GJSXItem
                {
                    DateDiffDays = Convert.ToInt32(row["DateDiffDays"]),
                    GJSXID = row["GJSXID"].ToString(),
                    ProjectId = row["ProjectId"].ToString(),
                    ProjectName = row["ProjectName"].ToString(),
                    UnitName = row["UnitName"].ToString(),
                    Detail = row["Detail"].ToString(),
                    CNProfessionalName = row["CNProfessionalName"].ToString(),
                    QuestionTypeName = row["QuestionTypeName"].ToString(),
                    GJSXTypeName = row["GJSXTypeName"].ToString(),
                    UserID = row["UserID"].ToString(),
                    UserName = row["UserName"].ToString(),
                    //UserEmail = row["UserEmail"].ToString(),
                    User_ReceiveUserId = row["User_ReceiveUserId"].ToString(),
                    User_ReceiveUserName = row["User_ReceiveUserName"].ToString(),
                    //User_ReceiveUserEmail = row["User_ReceiveUserEmail"].ToString(),
                    User_AcceptanceUserId = row["User_AcceptanceUserId"].ToString(),
                    User_AcceptanceUserName = row["User_AcceptanceUserName"].ToString(),
                    //User_AcceptanceUserEmail = row["User_AcceptanceUserEmail"].ToString(),
                    User_CsUserIds = row["User_CsUserIds"].ToString(),
                    User_CsUsers = row["User_CsUsers"].ToString(),
                    //User_CsUsersUserEmail = row["User_CsUsersUserEmail"].ToString(),
                    CompleteDate = Convert.ToDateTime(row["CompleteDate"].ToString())
                }).ToList();
                #region 根据用户聚合推送,多个事项合并推送
                //获取有邮箱的用户
                var userIds = BLL.UserService.GetUserHaveEmailList();
                //userIds = userIds.Where(x => x.UserName == "张邦兴" || x.UserName == "申银行").ToList();
                //userIds = userIds.Where(x => x.UserName == "白金潮" || x.UserName == "申银行").ToList();
                if (userIds.Any() && lstOverdue.Any())
                {
                    //int allnum = 0;
                    var lstProject = lstOverdue.Select(x => new { x.ProjectId, x.ProjectName }).Distinct().ToList();
                    foreach (var pro in lstProject)
                    {
                        //if (allnum > 50) { break; }
                        var lstProjectOverdue = lstOverdue.Where(x => x.ProjectId == pro.ProjectId).ToList();
                        if (lstProjectOverdue.Any())
                        {
                            string projectName = pro.ProjectName;
                            #region 事项预警提醒相关人员
                            foreach (var user in userIds)
                            {
                                //if (allnum > 100) { break; }
                                MailMessage mail = new MailMessage();
                                //邮件主题
                                mail.Subject = $"关键事项预警提醒——{projectName}";
                                mail.To.Add(user.Email);
                                //mail.To.Add("test@test.com");
                                mail.IsBodyHtml = true;//确保邮件正文被当作HTML解析
                                StringBuilder tbodyStr = new StringBuilder();
                                int index = 1;
                                //责任人为本人
                                var acceptanceItems = lstProjectOverdue.Where(x => x.User_AcceptanceUserId.Contains(user.UserId)).OrderByDescending(x => x.DateDiffDays).ToList();
                                if (acceptanceItems.Any())
                                {
                                    foreach (var item in acceptanceItems)
                                    {
                                        tbodyStr.Append($"| {index} | 本人负责 | {item.UnitName} | {item.GJSXID} | {item.Detail} | {item.GJSXTypeName} | {item.QuestionTypeName} | {item.UserName} | {item.User_AcceptanceUserName} | {item.CompleteDate.ToShortDateString()} | {(item.DateDiffDays > 0 ? item.DateDiffDays.ToString() : item.DateDiffDays < -1 ? "还有一周就逾期了" : "半")} | 
");
                                        index++;
                                    }
                                }
                                //发起人为本人
                                var userItems = lstProjectOverdue.Where(x => x.UserID == user.UserId && x.DateDiffDays > -1).OrderByDescending(x => x.DateDiffDays).ToList();
                                if (userItems.Any())
                                {
                                    foreach (var item in userItems)
                                    {
                                        tbodyStr.Append($"| {index} | 本人发起 | {item.UnitName} | {item.GJSXID} | {item.Detail} | {item.GJSXTypeName} | {item.QuestionTypeName} | {item.UserName} | {item.User_AcceptanceUserName} | {item.CompleteDate.ToShortDateString()} | {(item.DateDiffDays > 0 ? item.DateDiffDays.ToString() : "半")} | 
");
                                        index++;
                                    }
                                }
                                //跟踪人为本人--x.User_ReceiveUserId != null && x.User_ReceiveUserId != "" &&
                                var receiveItems = lstProjectOverdue.Where(x => x.User_ReceiveUserId.Contains(user.UserId) && x.DateDiffDays > -1).OrderByDescending(x => x.DateDiffDays).ToList();
                                if (receiveItems.Any())
                                {
                                    foreach (var item in receiveItems)
                                    {
                                        tbodyStr.Append($"| {index} | 本人跟踪 | {item.UnitName} | {item.GJSXID} | {item.Detail} | {item.GJSXTypeName} | {item.QuestionTypeName} | {item.UserName} | {item.User_AcceptanceUserName} | {item.CompleteDate.ToShortDateString()} | {(item.DateDiffDays > 0 ? item.DateDiffDays.ToString() : "半")} | 
");
                                        index++;
                                    }
                                }
                                //抄送人为本人
                                var csUserItems = lstProjectOverdue.Where(x => x.User_CsUserIds.Contains(user.UserId)).OrderByDescending(x => x.DateDiffDays).ToList();
                                if (csUserItems.Any())
                                {
                                    foreach (var item in csUserItems)
                                    {
                                        tbodyStr.Append($"| {index} | 抄送本人 | {item.UnitName} | {item.GJSXID} | {item.Detail} | {item.GJSXTypeName} | {item.QuestionTypeName} | {item.UserName} | {item.User_AcceptanceUserName} | {item.CompleteDate.ToShortDateString()} | {(item.DateDiffDays > 0 ? item.DateDiffDays.ToString() : item.DateDiffDays < -1 ? "还有一周就逾期了" : "半")} | 
");
                                        index++;
                                    }
                                }
                                //邮件正文
                                string bodyStr = @"
关键事项预警提醒
请点击此处,查看详细信息,并及时处置关闭
    
        | 序号 | 类型 | 责任单位 | 事项编号 | 事项描述 | 事项类别 | 紧急程度 | 发起人 | 责任人 | 约定完成时间 | 超期时间(天) | 
" + tbodyStr.ToString() + "
";
                                mail.Body = bodyStr;
                                if (index > 1)
                                {
                                    try
                                    {
                                        //allnum++;
                                        bool send = PushEmail(mail);
                                        //Thread.Sleep(1000); //暂停1秒
                                    }
                                    catch (Exception ex)
                                    {
                                        ErrLogInfo.WriteLog($"【邮箱提醒异常】邮箱:{user.Email};时间:{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")};异常信息:{ex.Message}");
                                        continue;
                                    }
                                }
                            }
                            #endregion
                            #region 事项逾期提醒项目主管和项目经理
                            var projectSupervisors = ProjectUserService.GetProjectUserByRoleId(pro.ProjectId,Const.ProjectSupervisor);
                            var projectManagers = ProjectUserService.GetProjectUserByRoleId(pro.ProjectId, Const.ProjectManager);
                            List remindUserIds = new List();
                            List projectSupervisorIds = projectSupervisors.Select(x => x.UserId).ToList();
                            List projectManagerIds = projectManagers.Select(x => x.UserId).ToList();
                            if (projectSupervisorIds.Any()) { remindUserIds.AddRange(projectSupervisorIds); }
                            if (projectManagerIds.Any()) { remindUserIds.AddRange(projectManagerIds); }
                            var remindUsers = userIds.Where(x => remindUserIds.Contains(x.UserId));
                            foreach (var user in remindUsers)
                            {
                                MailMessage mail = new MailMessage();
                                //邮件主题
                                mail.Subject = $"关键事项逾期提醒——{projectName}";
                                mail.To.Add(user.Email);
                                //mail.To.Add("test@test.com");
                                mail.IsBodyHtml = true;//确保邮件正文被当作HTML解析
                                StringBuilder tbodyStr = new StringBuilder();
                                int index = 0;
                                if (projectManagerIds.Contains(user.UserId))
                                {
                                    index = 0;
                                    //超期当日提醒项目经理
                                    var lstProjectOverdue1 = lstProjectOverdue.Where(x => x.DateDiffDays == 0 || x.DateDiffDays == -1).ToList();
                                    //超期一周的重要、紧急事项提醒项目经理
                                    var lstProjectOverdue7 = lstProjectOverdue.Where(x => x.DateDiffDays >= 7 && x.QuestionTypeName != "一般").ToList();
                                    lstProjectOverdue1.AddRange(lstProjectOverdue7);
                                    foreach (var item in lstProjectOverdue1)
                                    {
                                        if (!item.User_CsUserIds.Contains(user.UserId))
                                        {
                                            index++;
                                            tbodyStr.Append($"| {index} | 事项逾期 | {item.UnitName} | {item.GJSXID} | {item.Detail} | {item.GJSXTypeName} | {item.QuestionTypeName} | {item.UserName} | {item.User_AcceptanceUserName} | {item.CompleteDate.ToShortDateString()} | {(item.DateDiffDays > 0 ? item.DateDiffDays.ToString() : "半")} | 
");
                                        }
                                    }
                                }
                                if (projectSupervisorIds.Contains(user.UserId) && !projectManagerIds.Contains(user.UserId))
                                {
                                    //超期两周的重要、紧急事项提醒项目主管
                                    var lstProjectOverdue14 = lstProjectOverdue.Where(x => x.DateDiffDays >= 13).ToList();
                                    index = 0;
                                    foreach (var item in lstProjectOverdue14)
                                    {
                                        if (!item.User_CsUserIds.Contains(user.UserId))
                                        {
                                            index++;
                                            tbodyStr.Append($"| {index} | 事项逾期 | {item.UnitName} | {item.GJSXID} | {item.Detail} | {item.GJSXTypeName} | {item.QuestionTypeName} | {item.UserName} | {item.User_AcceptanceUserName} | {item.CompleteDate.ToShortDateString()} | {(item.DateDiffDays > 0 ? item.DateDiffDays.ToString() : "半")} | 
");
                                        }
                                    }
                                }
                                //邮件正文
                                string bodyStr = @"
关键事项超期预警提醒
请点击此处,查看详细信息,并及时处置关闭
    
        | 序号 | 类型 | 责任单位 | 事项编号 | 事项描述 | 事项类别 | 紧急程度 | 发起人 | 责任人 | 约定完成时间 | 超期时间(天) | 
" + tbodyStr.ToString() + "
";
                                mail.Body = bodyStr;
                                if (index > 1)
                                {
                                    try
                                    {
                                        //allnum++;
                                        bool send = PushEmail(mail);
                                        //Thread.Sleep(1000); //暂停1秒
                                    }
                                    catch (Exception ex)
                                    {
                                        ErrLogInfo.WriteLog($"【邮箱提醒异常】邮箱:{user.Email};时间:{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")};异常信息:{ex.Message}");
                                        continue;
                                    }
                                }
                            }
                            #endregion
                        }
                    }
                }
                #endregion
            }
            catch (Exception ex)
            {
                ErrLogInfo.WriteLog("关键事项邮件预警", ex);
            }
        }
        /// 
        /// 发送邮件
        /// 
        /// 
        private static bool PushEmail(MailMessage mail)
        {
            //await Task.Delay(1000); //等待1000毫秒
            // 忽略SSL证书验证
            ServicePointManager.ServerCertificateValidationCallback =
                delegate (object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
                {
                    return true;
                };
            //获取发送邮箱配置
            Email_Pop pops = BLL.Email_PopService.GetEmail_Pop("7EC5E991-B7A0-495A-90ED-2BE15370C959");
            if (pops != null)
            {
                mail.From = new MailAddress(pops.EmailYx);//发件人邮箱地址
                SmtpClient client = new SmtpClient(pops.EmailFwq);//替换为你的SMTP服务器地址
                client.Port = int.Parse(pops.EmailDk);//587或465如果使用SSL
                client.EnableSsl = true;//如果服务器支持SSL,设置为true
                client.DeliveryMethod = SmtpDeliveryMethod.Network;
                client.UseDefaultCredentials = false;
                client.Credentials = new NetworkCredential(pops.EmailYx, pops.EmailPass);//替换为你的邮箱和服务授权码
                client.Timeout = 6000;//6秒超时
                try
                {
                    client.Send(mail);
                    client.Dispose();//释放资源
                    return true;
                    //Console.WriteLine("Email sent successfully.");
                }
                catch (Exception ex)
                {
                    ErrLogInfo.WriteLog(mail.Subject, ex);
                    return false;
                    //Console.WriteLine("Email sending failed: " + ex.Message);
                }
            }
            return false;
        }
    }
}