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 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() { 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 { StartUpgradeProcess(); } } 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()) //{ // // 显示升级框 // ShowUpgradeView(); //} } 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 showDialog(string message) { MessageBox.Show(message); } 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() { 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); MessageBox.Show("启动升级程序失败,请重试"); } } public void StartProofread() { Globals.ThisAddIn.SendMessageToWeb("start", "login"); } public void ShowCurrentPane() { Globals.ThisAddIn.ShowPanel(); } public void HideCurrentPane() { Globals.ThisAddIn.HidePanel(); } public void ShowLoginForm(string action) { Globals.ThisAddIn.ShowLoginForm(action); } public void Logout(string action) { // web同步注销到ribbon Globals.ThisAddIn.SyncLogout(); // 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 string getDocumentData() { Dictionary data = new Dictionary(); var documentInfo = Globals.ThisAddIn.ActiveDocument; var doc = documentInfo.CurrentDocument; //string ext = doc.FullName.ToLower(); // 如果是 //var shouldCheckSaved = ext.EndsWith(".wps") || doc.Paragraphs.Count < 200 || doc.Tables.Count < 20; // !shouldCheckSaved && if (!documentInfo.Saved()) { data.Add("code", 1); data.Add("message", "请保存文档后再进行校对"); } else 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) { //var upgradeData = JsonConvert.DeserializeObject(data); //var needUpgrade = upgradeData.NeedUpgrade(Config.APP_VERSION); //if (upgradeData.Ext == 1) //{ // if (!needUpgrade) // { // showDialog("当前版本为最新版本,无需升级"); // } // else // { // var ret = MessageBox.Show(upgradeData.Message, "是否确认更新", System.Windows.Forms.MessageBoxButtons.YesNo, System.Windows.Forms.MessageBoxIcon.Question); // if (ret == DialogResult.Yes) // { // OpenUrlWithOsBrowser(upgradeData.DownloadUrl); // } // } //} //else //{ // StartUpgradeProcess(); //} } 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() { FormSetting frm = new FormSetting(); frm.Show(); } 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 = 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 string ShowDialogMessage(string message) { var result = FormMessage.ShowMessage(message); 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 { DocumentUtil.ExportProofreadResult(); 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 string SaveCache(string cache, bool silent) { if (!silent) { if (!Globals.ThisAddIn.Application.ActiveDocument.Saved) { MessageBox.Show("请先保存文档"); return BridgeResult.Error(1, "请先保存文档"); } } try { File.WriteAllText(Globals.ThisAddIn.ActiveDocument.ProofreadCachePath, cache); return BridgeResult.Success("ok"); } catch (Exception ex) { return BridgeResult.Error(-1, ex.Message); } } public bool CacheExists() { return File.Exists(Globals.ThisAddIn.ActiveDocument.ProofreadCachePath); } public string LoadCache() { if (!File.Exists(Globals.ThisAddIn.ActiveDocument.ProofreadCachePath)) { return BridgeResult.Error(1, "cache-not-exists"); } try { return BridgeResult.Success(File.ReadAllText(Globals.ThisAddIn.ActiveDocument.ProofreadCachePath)); } catch (Exception ex) { return BridgeResult.Error(ex.Message); } } 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); } } } }