2024-12-25 19:29:29 +08:00

792 lines
26 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 AIProofread.Controls;
using AIProofread.core;
using AIProofread.Model;
using AIProofread.Util;
using Microsoft.Office.Interop.Word;
using Microsoft.Office.Tools.Word;
using Microsoft.Web.WebView2.Core;
using Microsoft.Web.WebView2.WinForms;
using Newtonsoft.Json;
using NPOI.XSSF.UserModel;
using NPOI.XWPF.UserModel;
using Org.BouncyCastle.Asn1.Crmf;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Runtime.InteropServices;
using System.Text.RegularExpressions;
using System.Windows.Forms;
using UtilLib;
using Document = Microsoft.Office.Interop.Word.Document;
using Task = System.Threading.Tasks.Task;
namespace AIProofread
{
public enum BridgeEvent
{
LoginSuccess,
WindowClose
}
public delegate void BridgeEventHandler(object sender, EventArgs e);
[ClassInterface(ClassInterfaceType.AutoDual)]
[ComVisible(true)]
public class Bridge
{
public static Bridge bridge = new Bridge();
private static readonly Dictionary<string, WebView2> webViewDict = new Dictionary<string, WebView2>();
private static readonly Dictionary<BridgeEvent, List<BridgeEventHandler>> eventHandlers = new Dictionary<BridgeEvent, List<BridgeEventHandler>>();
public static Dictionary<int, ProofreadItem> marks;
private static int selectProofreadId = -1;
private static object missing = System.Reflection.Missing.Value;
private static UpgradeData CurrentUpgrade = null;
public void ShowUpgradeView()
{
// 统一使用更新程序
StartUpgradeProcess();
//if (CurrentUpgrade == null)
//{
// CheckPluginUpgrade();
// if (CurrentUpgrade == null)
// {
// showDialog("获取版本信息失败,请稍后再试");
// return;
// }
//}
//var needUpgrade = CurrentUpgrade.NeedUpgrade(Config.APP_VERSION);
//if (!needUpgrade)
//{
// showDialog("当前版本为最新版本,无需升级");
// return;
//}
//if (CurrentUpgrade.Ext == 1)
//{
// var ret = MessageBox.Show(CurrentUpgrade.Message, "是否确认更新", System.Windows.Forms.MessageBoxButtons.YesNo, System.Windows.Forms.MessageBoxIcon.Question);
// if (ret == DialogResult.Yes)
// {
// OpenUrlWithOsBrowser(CurrentUpgrade.DownloadUrl);
// }
//}
//else
//{
//}
}
public bool ShouldUpgradeForced()
{
return CurrentUpgrade != null && CurrentUpgrade.NeedUpgrade(Config.APP_VERSION) && CurrentUpgrade.UpgradeType == 1;
}
/// <summary>
/// 检查插件更新信息
/// </summary>
public void CheckPluginUpgrade()
{
try
{
string source = HttpUtil.GetHttpSource(Config.WEB_PATH + "api/v1/common/download/version");
if (source == null) return;
UpgradeSource data = JsonConvert.DeserializeObject<UpgradeSource>(source);
if (data == null || data.Code != 0) return;
CurrentUpgrade = data.Data;
// 是否需要强制升级
if (ShouldUpgradeForced())
{
var result = MessageBox.Show("插件有新的版本,是否立即更新?", "AI校对王提示", MessageBoxButtons.YesNo);
if (result == DialogResult.Yes)
{
// 显示升级框
ShowUpgradeView();
}
else
{
Globals.ThisAddIn.ribbon.SetBtnStatus("disable-by-upgrade", false);
}
}
}
catch (Exception ex)
{
Logger.Log(ex);
}
}
public string GetAppVersion()
{
Dictionary<string, object> data = new Dictionary<string, object>();
data["version"] = Config.APP_VERSION;
data["platform"] = Config.IS_WPS ? "wps" : "word";
data["environment"] = Config.APP_ENV.ToString();
return JsonConvert.SerializeObject(data);
}
public void SetBtnStatus(string key, bool status)
{
Globals.ThisAddIn.ribbon.SetBtnStatus(key, status);
}
public void ShowDialog(string message, string confirmText = "", string confirmAction = "")
{
Globals.ThisAddIn.ActiveDocument?.ShowDialog(message, confirmText, confirmAction);
}
public int getMinWIdth()
{
return Globals.ThisAddIn.GetMinWidth();
}
/// <summary>
/// 添加事件
/// </summary>
/// <param name="eventName"></param>
/// <param name="handler"></param>
public static void AddEventHandler(BridgeEvent eventName, BridgeEventHandler handler)
{
if (!eventHandlers.ContainsKey(eventName))
{
eventHandlers.Add(eventName, new List<BridgeEventHandler>());
}
eventHandlers[eventName].Add(handler);
}
public static void RemoveEventHandler(BridgeEvent eventName, BridgeEventHandler handler)
{
if (eventHandlers.ContainsKey(eventName))
{
eventHandlers[eventName].Remove(handler);
}
}
public void SetCurrentDocumentId(int id)
{
SetDocumentId(id, Globals.ThisAddIn.Application.ActiveDocument);
}
public void SetDocumentId(int id, Document document)
{
Globals.ThisAddIn.SetDocumentId(document, id);
}
public DocumentInfo GetDocumentById(int id)
{
return Globals.ThisAddIn.GetDocumentById(id);
}
public int GetCurrentDocumentId()
{
return Globals.ThisAddIn.ActiveDocument.Id;
}
public int GeIdBytDocument(Document document)
{
var doc = Globals.ThisAddIn.documentList.Get(document);
if (doc != null)
{
return doc.Id;
}
return doc != null ? doc.Id : 0;
}
// 打开网页
public void OpenUrlWithOsBrowser(string url)
{
try
{
Process.Start(url);
}
catch
{
ShowDialog("打开网页失败");
}
}
public static void StartUpgradeProcess(bool showFail = true)
{
try
{
string applicationBase = AppDomain.CurrentDomain.SetupInformation.ApplicationBase;
string path = "updater.exe";
ProcessStartInfo processStartInfo = new ProcessStartInfo(Path.Combine(applicationBase, Path.GetFileName(path)))
{
WorkingDirectory = applicationBase,
};
Process.Start(processStartInfo);
}
catch (Exception e)
{
Logger.Log(e);
if (showFail)
{
MessageBox.Show("启动升级程序失败,请重试");
}
}
}
public void StartProofread()
{
Globals.ThisAddIn.SendMessageToWeb("start", "login");
}
public void ShowCurrentPane()
{
Globals.ThisAddIn.ShowPanel();
}
public void HideCurrentPane()
{
Globals.ThisAddIn.HidePanel();
}
public void ShowLog(string message)
{
Logger.Log((Config.IS_WPS ? "WPS" : "WORD") + "-WEB", message);
}
public void ShowLoginForm(string action)
{
Globals.ThisAddIn.ShowLoginForm(action);
}
public void Logout(string action)
{
// web同步注销到ribbon
Globals.ThisAddIn.SyncLogout();
if(string.IsNullOrEmpty(action) || action != "disabled-send")
{
// ribbon 发送注销动作到 web
Globals.ThisAddIn.SendMessageToWeb("logout", null);
}
}
/// <summary>
/// 登录成功后通知后端
/// </summary>
public void loginSuccess(string userinfo)
{
if (userinfo == null || userinfo.Length == 0) return;
//
Userinfo info = JsonConvert.DeserializeObject<Userinfo>(userinfo);
// 登录成功 展示
Globals.ThisAddIn.ribbon.ProcessLoginInfo(info);
}
// 获取文档所有文本数据
public Dictionary<string, object> getAllText()
{
return Tools.GetAllText(Globals.ThisAddIn.Application.ActiveDocument);
}
public bool Saved(int documentId)
{
var document = documentId > 0 ? Globals.ThisAddIn.GetDocumentById(documentId) : Globals.ThisAddIn.ActiveDocument;
return document.CurrentDocument.Saved;
}
/// <summary>
/// 获取文档数据
/// </summary>
/// <returns></returns>
public string getDocumentData(int documentId)
{
Dictionary<string, object> data = new Dictionary<string, object>();
var documentInfo = documentId > 0 ? Globals.ThisAddIn.GetDocumentById(documentId) : Globals.ThisAddIn.ActiveDocument;
var doc = documentInfo.CurrentDocument;
if (ShouldUpgradeForced())
{
data.Add("code", 2);
data.Add("message", "请升级插件后再进行校对");
}
else if (doc.ProtectionType != WdProtectionType.wdNoProtection)
{
data.Add("code", 3);
data.Add("message", "文档受保护,无法编辑");
}
else
{
documentInfo.hasProcessMark = false;
data.Add("code", 0);
data.Add("message", "success");
data.Add("name", doc.Name);
//data.Add("documentId", Globals.ThisAddIn.ActiveDocument.Id);
data.Add("fullName", doc.FullName);
data.Add("documentId", GeIdBytDocument(doc));
data.Add("wordsCount", doc.Words.Count);
data.Add("charactersCount", doc.Characters.Count);
data.Add("content", Tools.GetAllText(doc));
}
return Tools.GetJSONString(data);
}
/// <summary>
/// 根据位置获取文档区域文本
/// </summary>
/// <param name="start"></param>
/// <param name="end"></param>
/// <returns></returns>
public string getParagraphTextByRange(int start, int end)
{
var list = Tools.GetTextListByParagraphRange(start, end);
return Tools.GetJSONString(list);
}
/// <summary>
/// 获取文档所有段落文本
/// </summary>
/// <returns></returns>
public string getAllParagraphs()
{
var doc = Globals.ThisAddIn.ActiveDocument;
if (doc == null)
{
return "";
}
return Tools.GetJSONString(doc.GetAllParagraphs());
}
public void getParagraphTextByRangeSync(int start, int end)
{
Task.Run(() =>
{
var list = Tools.GetTextListByParagraphRange(start, end);
Globals.ThisAddIn.SendMessageToWeb("getParagraphTextByRange", Tools.GetJSONString(list));
});
}
public int getTotalParagraphNumber() => Globals.ThisAddIn.ActiveDocument?.GetTotalParagraphNumber() ?? -1;
/// <summary>
/// 读取文档原始文件并转换成base64
/// </summary>
/// <returns></returns>
public string getDocumentFileData() => Globals.ThisAddIn.ActiveDocument?.GetOriginFileData() ?? "";
public void ShowUpgrade(string data, bool force = false)
{
Globals.ThisAddIn.ActiveDocument.ShowUpgrade(data, force);
}
public void noticeOtherWeb(string json, string targetWebName)
{
if (targetWebName != null)
{
if (webViewDict.ContainsKey(targetWebName))
{
SendMessageToWeb(webViewDict[targetWebName], json);
}
}
else
{
// 如果没有指定 则向所有 webview 发送消息
foreach (var item in webViewDict)
{
SendMessageToWeb(item.Value, json);
}
}
}
private void SendMessageToWeb(WebView2 webView, string json)
{
webView.CoreWebView2.PostWebMessageAsJson(json);
}
public async static void InitWebEnvAsync(string name, WebView2 webView)
{
try
{
webView.Name = name;
if (webViewDict.ContainsKey(webView.Name))
{
webViewDict[name] = webView;
}
else
{
webViewDict.Add(name, webView);
}
// 禁用web安全允许跨域 否则需要web编译为umd加载模式
var ops = new CoreWebView2EnvironmentOptions("--disable-web-security");
var env = await CoreWebView2Environment.CreateAsync(null, Config.WEB_DATA_PATH, ops);
await webView.EnsureCoreWebView2Async(env);
//webView.CoreWebView2.Settings.AreDevToolsEnabled = false;
//webView.CoreWebView2.Settings.AreDefaultScriptDialogsEnabled = false;
//webView.CoreWebView2.Settings.AreHostObjectsAllowed = true;
// 添加 js与客户端代理
webView.CoreWebView2.AddHostObjectToScript("bridge", bridge);
}
catch (Exception ex)
{
Logger.Log(ex);
}
}
public void clearAllProofreadMarkById(int documentId) => Globals.ThisAddIn.GetDocumentById(documentId)?.ClearAllProofreadMark();
public void ClearCurrentDocumentMarks() => Globals.ThisAddIn.ActiveDocument?.ClearAllProofreadMark();
public void removeBookmark(string markId) => DocumentUtil.RemoveBookmark(markId);
public string getAllBookmark()
{
return ToJSON(DocumentUtil.GetAllBookmark());
}
public string getSectionText()
{
return ToJSON(DocumentUtil.GetSectionText());
}
private static string ToJSON(object data)
{
return JsonConvert.SerializeObject(data);
}
public string GetCheckText()
{
var document = Globals.ThisAddIn.Application.ActiveDocument;
int count = Globals.ThisAddIn.Application.ActiveDocument.Paragraphs.Count;
if (count > 10000)
{
return document.Content.Text;
}
string text = "";
for (int i = 0; i < count; i++)
{
string input = document.Paragraphs[i + 1].Range.Text.Replace("\f\r", "");
string pattern = "[\\r\\f\\n]";
string replacement = "\t";
string text2 = Regex.Replace(input, pattern, replacement);
if (text2.EndsWith("\t"))
{
text2 = text2.Substring(0, text2.Length - 1);
}
text2 += "\r";
text += text2;
}
return text;
}
public string GetSelectedText()
{
// 文档对象
var document = Globals.ThisAddIn.Application.ActiveDocument;
// 获取选区
var selection = Globals.ThisAddIn.Application.Selection;
// 段落数
int count = selection.Paragraphs.Count;
if (count > 10000)
{
return selection.Text;
}
string text = "";
if (count == 1)
{
string input = selection.Text.Replace("\f\r", "");
string pattern = "[\\r\\f\\n]";
string replacement = "\t";
string text2 = Regex.Replace(input, pattern, replacement);
return text + text2;
}
for (int i = 0; i < count; i++)
{
string input;
if (i == 0)
{
int start = selection.Range.Start;
int end = selection.Paragraphs[i + 1].Range.End;
Document obj = document;
object Start = start;
object End = end;
input = obj.Range(ref Start, ref End).Text;
}
else if (i == count - 1)
{
int start2 = selection.Paragraphs[i + 1].Range.Start;
int end2 = selection.Range.End;
Document obj2 = document;
object End = start2;
object Start = end2;
input = obj2.Range(ref End, ref Start).Text;
}
else
{
input = selection.Paragraphs[i + 1].Range.Text;
}
input = input.Replace("\f\r", "");
string pattern2 = "[\\r\\f\\n]";
string replacement2 = "\t";
string text3 = Regex.Replace(input, pattern2, replacement2);
if (text3.EndsWith("\t"))
{
text3 = text3.Substring(0, text3.Length - 1);
}
text3 += "\r";
text += text3;
}
return text;
}
public void ShowSettingForm()
{
Globals.ThisAddIn.ActiveDocument.ShowSetting();
}
public void ShowWebView(string url, int width, int height, bool dialog)
{
Globals.ThisAddIn.ActiveDocument.ShowWebView(url, width, height, dialog);
}
public void MoveCursor(int pos)
{
var rng = Globals.ThisAddIn.Application.ActiveDocument.Range(pos, pos);
rng.Select();
}
public void SelectMarkById(int proofreadId, int documentId)
{
Globals.ThisAddIn.ActiveDocument?.SelectMarkById(proofreadId, false);
}
public void processMark(int proofreadId, int status)
{
Globals.ThisAddIn.ActiveDocument?.ProcessMark(proofreadId, status);
}
public string InitContent(string content, int documentId)
{
return InitContent(content, documentId, true);
}
public string InitContent(string content, int documentId, bool clearOriginMark)
{
try
{
// 根据文档编号 获取当前文档避免数据混乱
var document = documentId < 1 ? Globals.ThisAddIn.ActiveDocument :(Globals.ThisAddIn.GetDocumentById(documentId) ?? throw new Exception("没有找到校对文档对象"));
// 先清除所有数据
if (clearOriginMark) document.ClearAllProofreadMark();
List<CorrectContext> list = JsonConvert.DeserializeObject<List<CorrectContext>>(content);
document.InitProofread(list);
}
catch (Exception ex)
{
Logger.Log("Initial Content error:" + ex.Message + "\n" + ex.StackTrace + "\n\n");
return "false";
}
return "true";
}
/// <summary>
/// 新增校对项 查找时的偏移量
/// </summary>
//private static readonly int INSERT_FIND_OFFSET = 5;
public string MarkSentence(string content, int documentId)
{
// 初始化话
return InitContent(content, documentId, false);
}
public void ShowMessage(string message,int closeDelay=1000, bool showCloseBtn = true)
{
//FormMessage.ShowMessage(message, closeDelay);
Globals.ThisAddIn.ActiveDocument?.ShowMessage(message, closeDelay, showCloseBtn);
}
public void ShowConfirmMessage(string message, string confirmText, string confirmAction)
{
Globals.ThisAddIn.ActiveDocument.ShowDialog(message,confirmText,confirmAction);
}
public string ShowDialogMessage(string message)
{
var result = FormMessage.ShowMessage(message, "确认",null);
if (result == DialogResult.Retry)
{
return "retry";
}
return "ok";
}
// 保存文件
public string WriteText(string content, string path)
{
try
{
File.WriteAllText(path, content);
return BridgeResult.Success("ok");
}
catch (Exception ex)
{
return BridgeResult.Error(-1, ex.Message);
}
}
/// <summary>
/// 导出勘误表
/// </summary>
/// <returns></returns>
public string ExportProofreadResult()
{
try
{
Globals.ThisAddIn.ActiveDocument.ExportResult();
return BridgeResult.Success();
}
catch (Exception ex)
{
return BridgeResult.Error(-1, ex.Message);
}
}
public string ReadText(string path)
{
try
{
if (!File.Exists(path)) return BridgeResult.Error(-1, "文件不存在");
return BridgeResult.Success(File.ReadAllText(path));
}
catch (Exception ex)
{
return BridgeResult.Error(-1, ex.Message);
}
}
public void Focus()
{
// 使面板重新获取到焦点
Globals.ThisAddIn.ActiveDocument.FocusToPanel();
}
public string SaveCache(int documentId, string cache, bool silent)
{
var document = Globals.ThisAddIn.GetDocumentById(documentId);
if (document == null)
{
return BridgeResult.Success("ok");
}
if (!silent)
{
if (!document.CurrentDocument.Saved)
{
MessageBox.Show("请先保存文档");
return BridgeResult.Error(1, "请先保存文档");
}
}
else
{
// 静默时 自动保存文档
document.Save();
}
try
{
Logger.Log("SaveCache " + document.fileName + " used " + document.ProofreadCachePath);
if (File.Exists(document.ProofreadCachePath))
{
File.Delete(document.ProofreadCachePath);
}
File.WriteAllText(document.ProofreadCachePath, cache);
// 对缓存文件进行隐藏
File.SetAttributes(document.ProofreadCachePath, FileAttributes.Hidden);
return BridgeResult.Success("ok");
}
catch (Exception ex)
{
return BridgeResult.Error(-1, ex.Message);
}
}
public bool CacheExists(int documentId)
{
var document = Globals.ThisAddIn.GetDocumentById(documentId);
return File.Exists(document.ProofreadCachePath);
}
public string LoadCache()
{
var document = Globals.ThisAddIn.ActiveDocument;
if (!File.Exists(document.ProofreadCachePath))
{
return BridgeResult.Error(1, "cache-not-exists");
}
Logger.Log("Load cache " + document.fileName + " used " + document.ProofreadCachePath);
try
{
return BridgeResult.Success(File.ReadAllText(document.ProofreadCachePath));
}
catch (Exception ex)
{
return BridgeResult.Error(ex.Message);
}
}
public bool DeleteCache()
{
try
{
if (File.Exists(Globals.ThisAddIn.ActiveDocument.ProofreadCachePath))
{
File.Delete(Globals.ThisAddIn.ActiveDocument.ProofreadCachePath);
}
}
catch (Exception)
{
return false;
}
return true;
}
public string ShowConfirm(string message, string caption, string yesButtonText, string noButtonText)
{
var result = FormDialog.Show(message, caption, yesButtonText, noButtonText);
return BridgeResult.Success(result == DialogResult.Yes ? "yes" : "no");
}
public string InitProofreadCacheList(string content)
{
try
{
List<CorrectContext> list = JsonConvert.DeserializeObject<List<CorrectContext>>(content);
Globals.ThisAddIn.InitProofreadCacheList(list);
return BridgeResult.Success();
}
catch (Exception ex)
{
return BridgeResult.Error(ex);
}
}
public void SetCurrentDocumentProofreadStatus(int documentId, bool proofread, bool proofreading, bool checkIsActive = false)
{
if (documentId < 1) return;
var document = Globals.ThisAddIn.GetDocumentById(documentId);
if (document != null)
{
document.Proofread = proofread;
document.Proofreading = proofreading;
if (checkIsActive && documentId != Globals.ThisAddIn.ActiveDocument.Id) return;
document.CheckBtnStatus();
}
}
/// <summary>
/// 设置当前文档的校对状态
/// </summary>
/// <param name="documentId"></param>
/// <param name="proofread"></param>
/// <param name="proofreading"></param>
public void SetCurrentDocumentProofreadStatus(int documentId, bool proofread, bool proofreading)
{
SetCurrentDocumentProofreadStatus(documentId, proofread, proofreading, false);
}
}
}