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 webViewDict = new Dictionary(); private static readonly Dictionary> eventHandlers = new Dictionary>(); public static Dictionary 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; } /// /// 检查插件更新信息 /// public void CheckPluginUpgrade() { try { string source = HttpUtil.GetHttpSource(Config.WEB_PATH + "api/v1/common/download/version"); if (source == null) return; UpgradeSource data = JsonConvert.DeserializeObject(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 data = new Dictionary(); 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(); } /// /// 添加事件 /// /// /// public static void AddEventHandler(BridgeEvent eventName, BridgeEventHandler handler) { if (!eventHandlers.ContainsKey(eventName)) { eventHandlers.Add(eventName, new List()); } 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); } } /// /// 登录成功后通知后端 /// public void loginSuccess(string userinfo) { if (userinfo == null || userinfo.Length == 0) return; // Userinfo info = JsonConvert.DeserializeObject(userinfo); // 登录成功 展示 Globals.ThisAddIn.ribbon.ProcessLoginInfo(info); } // 获取文档所有文本数据 public Dictionary 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; } /// /// 获取文档数据 /// /// public string getDocumentData(int documentId) { Dictionary data = new Dictionary(); 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); } /// /// 根据位置获取文档区域文本 /// /// /// /// public string getParagraphTextByRange(int start, int end) { var list = Tools.GetTextListByParagraphRange(start, end); return Tools.GetJSONString(list); } /// /// 获取文档所有段落文本 /// /// 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; /// /// 读取文档原始文件并转换成base64 /// /// 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 list = JsonConvert.DeserializeObject>(content); document.InitProofread(list); } catch (Exception ex) { Logger.Log("Initial Content error:" + ex.Message + "\n" + ex.StackTrace + "\n\n"); return "false"; } return "true"; } /// /// 新增校对项 查找时的偏移量 /// //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); } } /// /// 导出勘误表 /// /// 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 list = JsonConvert.DeserializeObject>(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(); } } /// /// 设置当前文档的校对状态 /// /// /// /// public void SetCurrentDocumentProofreadStatus(int documentId, bool proofread, bool proofreading) { SetCurrentDocumentProofreadStatus(documentId, proofread, proofreading, false); } } }