using Blazored.TextEditor; using Entities.Contracts; using Microsoft.AspNetCore.Components; using Microsoft.JSInterop; using MudBlazor; using System.Text.RegularExpressions; using TechHelper.Client.AI; using TechHelper.Client.Exam; using static Org.BouncyCastle.Crypto.Engines.SM2Engine; namespace TechHelper.Client.Pages.Editor { public enum ProgEnum { AIPrase, AIRectify } public partial class EditorMain { private List QuestionS = new List(); private bool lode = false; BlazoredTextEditor QuillHtml; string QuillHTMLContent; string AIParseResult; string Error; string ProgStatues = string.Empty; List ParseResult = new List(); public async Task GetHTML() { QuillHTMLContent = await this.QuillHtml.GetHTML(); } public async Task GetText() { QuillHTMLContent = await this.QuillHtml.GetText(); } private string EditorHtmlContent { get; set; } = string.Empty; private List? ParsedQuestions { get; set; } private bool _parseAttempted = false; public class ParsedQuestion { public int Id { get; set; } // 题目的序号 public string? Content { get; set; } // 题目的完整 HTML 内容 public string? Title { get; set; } // 题目的标题部分(可选,可以从 Content 中提取) } [Inject] public IAIService aIService { get; set; } [Inject] public ISnackbar Snackbar { get; set; } private async void ParseWithAI() { QuestionS.Clear(); ParseResult.Clear(); await GetText(); lode = true; StateHasChanged(); ProgStatues = ProgEnum.AIPrase.ToString(); ProgStatues = $"正在解析题组,请等待"; Snackbar.Add("正在解析题组,请等待", Severity.Info); StateHasChanged(); string respon = await aIService.CallGLM(QuillHTMLContent, AIConfiguration.BreakQuestions); if (respon == null) { lode = false; Snackbar.Add("出了点问题重试一下吧"); return; } var ParRespon = ExamParser.ParseExamXml(respon); if (ParRespon != null) { int i = 1; foreach (var item in ParRespon.Items) { ProgStatues = $"正在解析第{i}题, 请等待"; Snackbar.Add($"正在解析第{i}题, 请等待", Severity.Info); StateHasChanged(); i++; try { var parResult = await aIService.CallGLM(item, AIConfiguration.ParseSignelQuestion2); ParseResult.Add(parResult); } catch (Exception ex) { Snackbar.Add($"解析第{i}题时出现问题, 请稍后重试. 问题为:{ex.Message}", Severity.Error); } } } AIParseResult = respon; ProgStatues = ProgEnum.AIRectify.ToString(); Snackbar.Add($"解析完成", Severity.Info); //await ReCorrectXMLAsync(); ProgStatues = string.Empty; lode = false; StateHasChanged(); } private async Task ReCorrectXMLAsync() { string respon = string.Empty; try { foreach (var item in ParseResult) { //respon = await aIService.CallGLM(AIParseResult, AIConfiguration.ParseSignelQuestion); var xmlResult = ExamParser.ParseExamXml(item); QuestionS.Add(xmlResult); } } catch (Exception ex) { Snackbar.Add("出了点问题重试一下吧" + ex.Message, Severity.Error); } if (string.IsNullOrEmpty(respon)) { lode = false; Snackbar.Add("出了点问题重试一下吧", Severity.Error); } AIParseResult = respon; } private void ParseXML() { try { var paper = ExamParser.ParseExamXml(AIParseResult); //QuestionS = paper.QuestionGroups; Error = string.Empty; } catch (InvalidOperationException ex) { Snackbar.Add("解析出问题了" + ex.Message, Severity.Error); } catch (Exception ex) { Snackbar.Add("解析出问题了" + ex.Message, Severity.Error); Error = ex.Message; } } private void DeleteFromParse(int index) { if (index >= 0 && index < ParseResult.Count) { ParseResult.RemoveAt(index); StateHasChanged(); } } [Inject] public IJSRuntime JSRuntime { get; set; } private IJSObjectReference jSObjectReference { get; set; } protected override async Task OnInitializedAsync() { jSObjectReference = await JSRuntime.InvokeAsync("import", "./scripts/jsTools.js"); } private async Task CopyToClipboard() { try { // 调用 JavaScript 函数 bool success = await jSObjectReference.InvokeAsync("copyTextToClipboard", AIConfiguration.ParseSignelQuestion2); if (success) { Snackbar.Add("文本已成功复制到剪贴板!"); } else { Snackbar.Add("复制文本到剪贴板失败。"); } } catch (Exception ex) { Snackbar.Add($"发生错误: {ex.Message}"); Console.WriteLine($"复制到剪贴板时出错: {ex.Message}"); } } private void ParseQuestions() { ParsedQuestions = new List(); _parseAttempted = true; if (string.IsNullOrWhiteSpace(QuillHTMLContent)) { return; } // 定义题目开始和结束的标记 string startTag = "[题目开始]"; string endTag = "[题目结束]"; // 构建正则表达式,匹配从开始标记到结束标记之间的所有内容(包括换行) // (?s) 启用单行模式,让 . 匹配换行符 string pattern = Regex.Escape(startTag) + "(.*?)" + Regex.Escape(endTag); var matches = Regex.Matches(QuillHTMLContent, pattern, RegexOptions.Singleline); int questionId = 1; foreach (Match match in matches) { // 获取两个标记之间的纯内容 string rawQuestionHtml = match.Groups[1].Value; // 移除可能残留在内容中的标记(尽管正则表达式已经排除了它们,但这增加一层防护) string cleanedQuestionContent = rawQuestionHtml .Replace(startTag, "") .Replace(endTag, "") .Trim(); // 尝试从内容中提取标题(例如,匹配“一、”或“1.”开头的行) string? questionTitle = null; try { var firstLineMatch = Regex.Match(cleanedQuestionContent, @"^(

)?\s*([一二三四五六七八九十]+\s*[、.]|\d+\s*[.\.]).*?

", RegexOptions.IgnoreCase | RegexOptions.Singleline); if (firstLineMatch.Success) { // 从 HTML 中提取纯文本作为标题 questionTitle = Regex.Replace(firstLineMatch.Value, "<[^>]*>", "").Trim(); } } catch (Exception ex) { } ParsedQuestions.Add(new ParsedQuestion { Id = questionId++, Content = cleanedQuestionContent, Title = questionTitle }); } } } }