258 lines
6.2 KiB
C#
258 lines
6.2 KiB
C#
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
|
||
});
|
||
}
|
||
}
|
||
|
||
}
|
||
} |