Files
TechHelper/TechHelper.Client/Pages/Editor/EditorMain.razor.cs
2025-05-27 11:58:36 +08:00

258 lines
6.2 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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<QuestionGroup> QuestionS = new List<QuestionGroup>();
private bool lode = false;
BlazoredTextEditor QuillHtml;
string QuillHTMLContent;
string AIParseResult;
string Error;
string ProgStatues = string.Empty;
List<string> ParseResult = new List<string>();
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<ParsedQuestion>? 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<StringsList>(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<QuestionGroup>(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<QuestionGroup>(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<IJSObjectReference>("import",
"./scripts/jsTools.js");
}
private async Task CopyToClipboard()
{
try
{
// 调用 JavaScript 函数
bool success = await jSObjectReference.InvokeAsync<bool>("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<ParsedQuestion>();
_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, @"^(<p>)?\s*([一二三四五六七八九十]+\s*[、.]|\d+\s*[\.]).*?</p>", 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
});
}
}
}
}