| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207 |
- using OASystem.API.OAMethodLib.DeepSeekAPI;
- using OASystem.API.OAMethodLib.Hotmail;
- using OASystem.API.OAMethodLib.QiYeWeChatAPI;
- using OASystem.Domain.ViewModels.QiYeWeChat;
- using System.Text.Json;
- using System.Text.Json.Serialization;
- using System.Web;
- using static OASystem.API.OAMethodLib.Hotmail.HotmailService;
- namespace OASystem.API.OAMethodLib.Quartz.Business
- {
- /// <summary>
- /// 获取hotmail邮件,自动总结邮件内容发送至企业微信邮件
- /// </summary>
- public static class ProcessAndNotifySummary
- {
- private static readonly SqlSugarClient _sqlSugar = AutofacIocManager.Instance.GetService<SqlSugarClient>();
- private static readonly IQiYeWeChatApiService _qiYeWeChatApiService = AutofacIocManager.Instance.GetService<IQiYeWeChatApiService>();
- private static readonly HotmailService _hotmailService = AutofacIocManager.Instance.GetService<HotmailService>();
- private static readonly IDeepSeekService _deepSeekService = AutofacIocManager.Instance.GetService<IDeepSeekService>();
- /// <summary>
- /// hotmail 邮件 汇总 发送企微邮件
- /// 时间范围 昨天
- /// </summary>
- public static async void ProcessAndNotifySummaryAsync()
- {
- var hotmailConfigs = await _hotmailService.GetUserMailConfigListAsync();
- if (hotmailConfigs == null || !hotmailConfigs.Any()) return;
- var hotmails = hotmailConfigs.Select(x => x.UserName).ToList();
- var userIds = hotmailConfigs.Select(x => x.UserId).ToList();
- var cstZone = CommonFun.GetCstZone();
- var nowInCst = TimeZoneInfo.ConvertTimeFromUtc(DateTime.UtcNow, cstZone);
- var yesterdayStart = nowInCst.Date.AddDays(-1);
- var yesterdayEnd = yesterdayStart.AddDays(1).AddTicks(-1);
- // 获取邮件信息
- var emailInfos = await _hotmailService.GetMergedMessagesAsync(hotmails, yesterdayStart, yesterdayEnd);
- // 处理无邮件情况
- if (emailInfos == null || !emailInfos.Any())
- {
- await NotifyEmptyEmails(userIds);
- return;
- }
- //// 预处理:限制每封邮件正文长度,防止 Token 溢出
- //foreach (var mail in emailInfos)
- //{
- // mail.Content = CleanHtmlToPlainText(mail.Content);
- //}
- // 调用 AI
- var question = BuildMailSummaryPrompt(emailInfos);
- var res = await _deepSeekService.ChatAsync(question);
- if (res.Success)
- {
- // 清洗 AI 可能带出的 Markdown 格式符
- string cleanJson = res.Answer.Trim();
- if (cleanJson.StartsWith("```json")) cleanJson = cleanJson.Replace("```json", "").Replace("```", "").Trim();
- try
- {
- var aiSummaryResults = JsonConvert.DeserializeObject<List<AiSummaryResult>>(cleanJson);
- var users = await _sqlSugar.Queryable<Sys_Users>().Where(x => x.IsDel == 0 && userIds.Contains(x.Id)).Select(x => new { x.Id, x.Email }).ToListAsync();
- foreach (var hotmailConfig in hotmailConfigs)
- {
- var qwEmail = users.FirstOrDefault(x => x.Id == hotmailConfig.UserId)?.Email;
- if (string.IsNullOrEmpty(qwEmail)) continue;
- if (hotmailConfig.UserName.Equals("925554512@qq.com") || hotmailConfig.UserName.Equals("Roy.Lei.Atom@hotmail.com"))
- {
- if (aiSummaryResults.Any(x => x.Recipient.Equals("925554512@qq.com")))
- {
- hotmailConfig.UserName = "925554512@qq.com";
- }
- if (aiSummaryResults.Any(x => x.Recipient.Equals("Roy.Lei.Atom@hotmail.com")))
- {
- hotmailConfig.UserName = "Roy.Lei.Atom@hotmail.com";
- }
- }
- // 获取 AI 为该账号生成的摘要
- var summary = aiSummaryResults?.FirstOrDefault(x => x.Recipient.Equals(hotmailConfig.UserName, StringComparison.OrdinalIgnoreCase));
- string finalSubject = $"{DateTime.Now:yyyy-MM-dd} - 邮件汇总";
- string finalBody = "未能获取到hotmail邮件。";
- if (summary != null)
- {
- finalSubject = $"[AI摘要] {summary.EmailSubject}";
- finalBody = summary.TextBody;
- }
- // 测试阶段默认发送在我的邮箱
- string defualtEmail1 = "johnny.yang@pan-american-intl.com";
- string defualtEmail2 = "Roy.lei@pan-american-intl.com";
- await _qiYeWeChatApiService.EmailSendAsync(new EmailRequestDto
- {
- ToEmails = new List<string> {
- qwEmail,
- defualtEmail1,
- defualtEmail2
- },
- Subject = finalSubject,
- Body = finalBody,
- });
- }
- }
- catch (Exception ex)
- {
- // 记录解析 JSON 失败日志
- }
- }
- }
- /// <summary>
- /// 纯正则实现:剔除 HTML 标签、样式和脚本,保留核心文本
- /// </summary>
- private static string CleanHtmlToPlainText(string? html)
- {
- if (string.IsNullOrEmpty(html)) return string.Empty;
- // 1. 剔除脚本 (Script) 和 样式 (Style) 及其内部内容
- html = Regex.Replace(html, @"<(script|style)[^>]*?>.*?</\1>", "", RegexOptions.IgnoreCase | RegexOptions.Singleline);
- // 2. 剔除所有 HTML 标签
- html = Regex.Replace(html, @"<[^>]*>", " ");
- // 3. 将 HTML 实体字符转换回普通字符 (例如 -> 空格, < -> <)
- html = HttpUtility.HtmlDecode(html);
- // 4. 清理多余的空白字符和重复换行
- html = Regex.Replace(html, @"\s+", " "); // 将多个空格/换行合并为一个空格
- html = Regex.Replace(html, @"(\n\s*){2,}", "\n"); // 压缩重复换行
- return html.Trim();
- }
- public static string BuildMailSummaryPrompt(List<MailDto> mailList)
- {
- var rawDataJson = System.Text.Json.JsonSerializer.Serialize(mailList, new JsonSerializerOptions { WriteIndented = false });
- return $@"
- # Role: .NET 邮件情报分析引擎 (JSON-ONLY Mode)
- ## Task
- 解析以下 `rawDataJson` 数据,按 `Recipient` (收件人) 分组并生成深度分析简报。
- ## Constraints (Strict)
- 1. **Output Format**: 只输出标准的 JSON 数组代码块。严禁包含任何开场白、结尾问候、Markdown 解释文字或非 JSON 字符。
- 2. **HTML Rule**: `TextBody` 字段内仅允许使用 `<strong>` 和 `<br />`。严禁使用 `\n`、`<div>` 或其他标签。
- 3. **Naming Convention**:
- - 字典 Key/属性名: 必须使用 **PascalCase** (如: Recipient, EmailSubject, TextBody)。
- - 内部逻辑变量: 使用 **camelCase**。
- 4. **Logic**:
- - 按请求中的 `to` 字段进行分组。
- - 分析每组邮件的业务关联性,生成 [当日概览]、[详情摘要]、[分析结论]。
- ## Output Schema
- [
- {{
- ""Recipient"": ""string"",
- ""EmailSubject"": ""每日情报分析报告"",
- ""TextBody"": ""<strong>[收件人:...]</strong><br /><br /><strong>[核心概览]</strong><br />...分析内容...<br /><br /><strong>[分析结论]</strong><br />...""
- }}
- ]
- ## Input Data
- {rawDataJson}
- ## Execution
- Now, output the JSON array based on the logic above. No prose, no chat, just the JSON block.";
- }
- private static async Task NotifyEmptyEmails(List<int> userIds)
- {
- var userEmails = await _sqlSugar.Queryable<Sys_Users>().Where(x => x.IsDel == 0 && userIds.Contains(x.Id)).Select(x => x.Email).ToListAsync();
- if (userEmails.Any())
- {
- await _qiYeWeChatApiService.EmailSendAsync(new EmailRequestDto
- {
- ToEmails = userEmails,
- Subject = $"{DateTime.Now:yyyy-MM-dd} - 邮件汇总",
- Body = "昨日暂未收到有效邮件。"
- });
- }
- }
- public class AiSummaryResult
- {
- public string Recipient { get; set; } = string.Empty;
- public string EmailSubject { get; set; } = string.Empty;
- public string TextBody { get; set; } = string.Empty;
- }
- }
- }
|