Compare commits

..

33 Commits

Author SHA1 Message Date
e28499b26f 版本号升级至2.2.6,新增版本说明弹窗功能
- 升级程序不再使用缓存文件,避免上一次下载的程序不完整
2025-07-04 11:35:30 +08:00
5c52c1a87a 版本号升级至2.2.5,FormWebView 隐藏窗口图标 2025-06-20 16:52:03 +08:00
16c24c10ec 启用多项功能开关,优化查找方法参数与健壮性
本次提交主要包括:
- 优化查找相关方法(FindBySentence、FindTextInRange),新增 prevOffset 和 findStart 参数,支持从指定偏移量和位置开始查找,提升查找灵活性与准确性(DocumentUtil.cs)
2025-06-05 23:51:36 +08:00
fc3773b65d 更新配置常量与调试代码调整
1. 在 `Config.cs` 中新增多个环境常量字符串:
   - 新增 `ALL_IN_ONE`、`PRE` 和新的 `PROD` 常量。
   - 删除旧的 `PROD` 常量,原值为 `"http://aijdw1.goldmye.com/"`。
2. 调整 `WEB_PATH` 的值:
   - `#if DEBUG` 下改为 `AppServer.PRE`。
   - 非 `DEBUG` 下保持为 `AppServer.PROD`。
3. 在 `Tools.cs` 中注释掉两行 `Debug.WriteLine` 调试代码,减少不必要的调试输出。
2025-05-21 11:29:36 +08:00
ff9a25d437 Bridge.cs 中,向 data 字典新增 BuildVersion 键值对。 2025-05-19 19:58:14 +08:00
8284a9d552 break: ActiveDocument 改为实时获取
优化调试逻辑,增强日志记录,简化代码结构

- 修改 AIProofread.csproj.user 的 <StartAction> 配置,调试时直接启动项目。
- Bridge.cs 中增加异常处理的详细错误信息。
- DocumentInfo.cs 增加日志记录,调整 RunInMainThread 方法逻辑。
- DocumentList.cs 删除过时的 XML 注释。
- ThisAddIn.cs 优化文档管理逻辑,调整 ActiveDocument 属性为只读,改进文档列表处理,删除冗余代码。
2025-05-09 16:59:27 +08:00
a54765e911 优化面板按钮逻辑
- 调整 `TaskPane_VisibleChanged` 方法逻辑,增加异步延迟处理和详细日志记录,修复 `CurrentDocument` 引用问题。
- 优化 `CheckBtnStatus` 方法,提升代码可读性并修正按钮状态逻辑。
- 改进 `TaskPane` 释放逻辑,增加对控件的重置操作。
2025-05-08 16:48:10 +08:00
32e85c62c0 优化日志记录、资源管理及功能支持
- 引入 log4net 库,统一日志记录方式,提升可维护性。
- 优化异常处理,增加详细日志记录,增强代码健壮性。
- 调整资源文件引用,新增图标资源,删除无用资源。
- 优化文档事件处理逻辑,改进面板显示与隐藏逻辑。
- 增加对 WPS 环境的支持,动态调整功能行为。
- 禁用部分功能(如常识性检测、客服、升级和帮助)。
- 删除冗余代码,清理注释,统一代码风格。
- 更新程序集版本至 2.2.5,改进调试与生产环境配置。
2025-05-08 13:57:12 +08:00
5b519f48e1 fixed: 修复首次加载插件面板初始化多个窗口或环境无法正确初始化 2025-04-23 18:02:17 +08:00
b1ace782f8 添加模块配置 2025-04-21 13:29:24 +08:00
d061406026 fix: 修正扩展初始化时面板没有初始化的问题 2025-04-19 18:36:27 +08:00
fa62b66a02 检测面板是否已经创建 2025-04-18 20:45:06 +08:00
5e4f692897 feat:版本改为2.2.5;消息提示框能够提示关闭消息;修复多处问题并优化功能实现 2025-04-17 16:53:32 +08:00
3c3ccb8847 feat: 更新程序集信息至 2.2.4 2025-04-15 22:13:43 +08:00
1644a1591f 添加版本 2025-04-15 17:22:25 +08:00
2bebf743ba feat: 日志底层组件采用log4net 2025-04-13 13:59:22 +08:00
fb2f5e0d16 feat:勘误表导出底层组件修改 2025-04-13 01:32:21 +08:00
cf148e9000 feat(ui): 调整FormLogin窗体和web控件尺寸
- 添加关闭事件,用于释放web资源
2025-04-09 21:24:45 +08:00
e52fd188b6 feat: 调整方法参数和文件保存逻辑 2025-04-03 23:36:38 +08:00
200f415ac6 perf: 📜️更新版本;对于特殊内容文档兼容 2025-03-30 14:28:18 +08:00
2b3e330841 feat: ️新增全局回调方法,优化修订模式处理
在 `Bridge.cs` 文件中:
- 修改 `ProcessStartInfo` 的 `Verb` 属性赋值方式,保持不变。
- 新增 `Callback` 方法,用于全局回调。
- 新增 `CheckInTrackRevisions` 方法,用于检查文档是否处于修订模式,并根据用户选择关闭修订模式或返回相应结果。
- 修改提示信息内容,并在用户选择不关闭修订模式时,返回相应错误信息。
- 调整 `JSONObject.Create()` 的链式调用格式。
- 调整 `InitProofreadCacheList` 方法的参数格式。

在 `FormMessage.cs` 文件中:
- 新增 `ShowMessage` 方法的重载版本,支持自定义确认和取消按钮的文本。

在 `DocumentInfo.cs` 文件中:
- 新增 `GlobalCallback` 方法,用于调用 Web 全局回调函数。

在 `ThisAddIn.cs` 文件中:
- 修改日志记录信息,增加文档修订模式的状态。
- 新增 `GlobalCallback` 方法,用于全局回调。
2025-03-29 21:25:19 +08:00
e8c18e6eb8 perf: 📜️强化常识性检测数据结构优化 2025-03-28 09:34:03 +08:00
342e32f49f fixed: 另存导致文档面板被关闭 2025-03-13 20:33:25 +08:00
d16d6d4671 fixed: ️修复文档关闭后再次打开展示多个面板 2025-03-10 16:46:47 +08:00
a296604f2c feat:新增模型选择 2025-03-06 22:35:04 +08:00
5013e10cb1 feat:添加模型选择菜单 2025-03-05 19:48:57 +08:00
31ee6d4894 fixed: 勘误表原文过长导致截取异常 2025-03-05 19:48:42 +08:00
03e0ffdce8 feat:客服调整;优化大文档及格式复杂文档卡片跳转卡顿 2025-03-05 15:36:24 +08:00
f418ec74e5 fixed: 修复ProofreadRangeInfo类丢失导致无法编译 2025-03-01 10:42:26 +08:00
e04d6104b2 feat: 添加并适配政务校对 2025-03-01 10:10:46 +08:00
d37882d6dd fixed: 校对后批注导致得百分号 2025-02-13 11:35:17 +08:00
b97e7d15ee 更新版本 2025-02-10 20:56:30 +08:00
d0126e6986 feat: 添加登录限制 2025-02-03 23:01:13 +08:00
64 changed files with 2984 additions and 652 deletions

5
.gitignore vendored
View File

@ -6,4 +6,7 @@ TestConsoleApp
obj
**/obj/Debug/**
**/obj/Release/**
**/obj/Test/**
**/obj/Test/**
**/**/obj/Debug/**
**/**/obj/Release/**
**/**/obj/Test/**

Binary file not shown.

View File

@ -128,6 +128,12 @@
<Reference Include="BouncyCastle.Cryptography, Version=2.0.0.0, Culture=neutral, PublicKeyToken=072edcf4a5328938, processorArchitecture=MSIL">
<HintPath>..\packages\BouncyCastle.Cryptography.2.3.1\lib\net461\BouncyCastle.Cryptography.dll</HintPath>
</Reference>
<Reference Include="DocumentFormat.OpenXml, Version=3.3.0.0, Culture=neutral, PublicKeyToken=8fb06cb64d019a17, processorArchitecture=MSIL">
<HintPath>..\packages\DocumentFormat.OpenXml.3.3.0\lib\net46\DocumentFormat.OpenXml.dll</HintPath>
</Reference>
<Reference Include="DocumentFormat.OpenXml.Framework, Version=3.3.0.0, Culture=neutral, PublicKeyToken=8fb06cb64d019a17, processorArchitecture=MSIL">
<HintPath>..\packages\DocumentFormat.OpenXml.Framework.3.3.0\lib\net46\DocumentFormat.OpenXml.Framework.dll</HintPath>
</Reference>
<Reference Include="Enums.NET, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7ea1c1650d506225, processorArchitecture=MSIL">
<HintPath>..\packages\Enums.NET.4.0.1\lib\net45\Enums.NET.dll</HintPath>
</Reference>
@ -137,11 +143,17 @@
<Reference Include="ICSharpCode.SharpZipLib, Version=1.4.2.13, Culture=neutral, PublicKeyToken=1b03e6acf1164f73, processorArchitecture=MSIL">
<HintPath>..\packages\SharpZipLib.1.4.2\lib\netstandard2.0\ICSharpCode.SharpZipLib.dll</HintPath>
</Reference>
<Reference Include="log4net, Version=3.0.4.0, Culture=neutral, PublicKeyToken=669e0ddf0bb1aa2a, processorArchitecture=MSIL">
<HintPath>..\packages\log4net.3.0.4\lib\net462\log4net.dll</HintPath>
</Reference>
<Reference Include="MathNet.Numerics, Version=5.0.0.0, Culture=neutral, PublicKeyToken=cd8b63ad3d691a37, processorArchitecture=MSIL">
<HintPath>..\packages\MathNet.Numerics.Signed.5.0.0\lib\net461\MathNet.Numerics.dll</HintPath>
</Reference>
<Reference Include="Microsoft.IO.RecyclableMemoryStream, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.IO.RecyclableMemoryStream.3.0.0\lib\netstandard2.0\Microsoft.IO.RecyclableMemoryStream.dll</HintPath>
<Reference Include="Microsoft.IO.RecyclableMemoryStream, Version=3.0.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.IO.RecyclableMemoryStream.3.0.1\lib\netstandard2.0\Microsoft.IO.RecyclableMemoryStream.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Office.Interop.Excel, Version=15.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c, processorArchitecture=MSIL">
<EmbedInteropTypes>True</EmbedInteropTypes>
</Reference>
<Reference Include="Microsoft.Web.WebView2.Core, Version=1.0.2210.55, Culture=neutral, PublicKeyToken=2a8ab48044d2601e, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.Web.WebView2.1.0.2210.55\lib\net45\Microsoft.Web.WebView2.Core.dll</HintPath>
@ -167,6 +179,7 @@
<Reference Include="NPOI.OpenXmlFormats, Version=2.7.1.0, Culture=neutral, PublicKeyToken=0df73ec7942b34e1, processorArchitecture=MSIL">
<HintPath>..\packages\NPOI.2.7.1\lib\netstandard2.0\NPOI.OpenXmlFormats.dll</HintPath>
</Reference>
<Reference Include="PresentationCore" />
<Reference Include="SixLabors.Fonts, Version=1.0.0.0, Culture=neutral, PublicKeyToken=d998eea7b14cab13, processorArchitecture=MSIL">
<HintPath>..\packages\SixLabors.Fonts.1.0.1\lib\netstandard2.0\SixLabors.Fonts.dll</HintPath>
</Reference>
@ -177,6 +190,9 @@
<Reference Include="System.Buffers, Version=4.0.3.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\packages\System.Buffers.4.5.1\lib\net461\System.Buffers.dll</HintPath>
</Reference>
<Reference Include="System.ComponentModel.Annotations, Version=4.2.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.ComponentModel.Annotations.5.0.0\lib\net461\System.ComponentModel.Annotations.dll</HintPath>
</Reference>
<Reference Include="System.ComponentModel.DataAnnotations" />
<Reference Include="System.Configuration" />
<Reference Include="System.Configuration.ConfigurationManager, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
@ -185,6 +201,7 @@
<Reference Include="System.Data" />
<Reference Include="System.Data.OracleClient" />
<Reference Include="System.Drawing" />
<Reference Include="System.IO.Compression, Version=4.2.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089, processorArchitecture=MSIL" />
<Reference Include="System.Memory, Version=4.0.1.2, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\packages\System.Memory.4.5.5\lib\net461\System.Memory.dll</HintPath>
</Reference>
@ -203,8 +220,8 @@
<Reference Include="System.Security.Cryptography.Pkcs, Version=6.0.0.3, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Security.Cryptography.Pkcs.6.0.3\lib\net461\System.Security.Cryptography.Pkcs.dll</HintPath>
</Reference>
<Reference Include="System.Security.Cryptography.Xml, Version=6.0.0.1, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\packages\System.Security.Cryptography.Xml.6.0.1\lib\net461\System.Security.Cryptography.Xml.dll</HintPath>
<Reference Include="System.Security.Cryptography.Xml, Version=8.0.0.2, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\packages\System.Security.Cryptography.Xml.8.0.2\lib\net462\System.Security.Cryptography.Xml.dll</HintPath>
</Reference>
<Reference Include="System.Security.Permissions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\packages\System.Security.Permissions.6.0.0\lib\net461\System.Security.Permissions.dll</HintPath>
@ -225,6 +242,7 @@
<Private>True</Private>
<Private>True</Private>
</Reference>
<Reference Include="System.Web" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Xml" />
<Reference Include="System.Core" />
@ -302,6 +320,12 @@
<Compile Include="Controls\FormDialog.Designer.cs">
<DependentUpon>FormDialog.cs</DependentUpon>
</Compile>
<Compile Include="Controls\FormLexicon.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="Controls\FormLexicon.Designer.cs">
<DependentUpon>FormLexicon.cs</DependentUpon>
</Compile>
<Compile Include="Controls\FormLoading.cs">
<SubType>Form</SubType>
</Compile>
@ -338,6 +362,12 @@
<Compile Include="Controls\FormMessage.Designer.cs">
<DependentUpon>FormMessage.cs</DependentUpon>
</Compile>
<Compile Include="Controls\FormReadme.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="Controls\FormReadme.Designer.cs">
<DependentUpon>FormReadme.cs</DependentUpon>
</Compile>
<Compile Include="Controls\FormSetting.cs">
<SubType>Form</SubType>
</Compile>
@ -362,11 +392,14 @@
<Compile Include="Controls\ProofreadMainControl.Designer.cs">
<DependentUpon>ProofreadMainControl.cs</DependentUpon>
</Compile>
<Compile Include="core\AppModule.cs" />
<Compile Include="core\BridgeResult.cs" />
<Compile Include="core\CommonSenseDetection.cs" />
<Compile Include="core\CorrectionCharacter.cs" />
<Compile Include="core\CorrectionFragmentAbstract.cs" />
<Compile Include="core\CorrectionRangeAbstract.cs" />
<Compile Include="core\CorrectResultExportor.cs" />
<Compile Include="core\DocumentReader.cs" />
<Compile Include="core\DocumentText.cs" />
<Compile Include="core\DocumentUtil.cs" />
<Compile Include="core\EventForwarder.cs" />
@ -375,7 +408,8 @@
<Compile Include="core\Tools.cs" />
<Compile Include="core\MainPanelWebMessage.cs" />
<Compile Include="core\ExportConfig.cs" />
<Compile Include="Logger.cs" />
<Compile Include="core\WebView2EventHandler.cs" />
<Compile Include="LogHelper.cs" />
<Compile Include="Model\BridgeResult.cs" />
<Compile Include="Model\CommonsenseDetectionItem.cs" />
<Compile Include="Model\DocumentContent.cs" />
@ -383,6 +417,7 @@
<Compile Include="Model\DocumentList.cs" />
<Compile Include="Model\ExportDataItem.cs" />
<Compile Include="Model\InsertMarkData.cs" />
<Compile Include="Model\ProofreadRangeInfo.cs" />
<Compile Include="ProofreadItem.cs" />
<Compile Include="Properties\AssemblyInfo.cs">
<SubType>Code</SubType>
@ -400,6 +435,9 @@
<EmbeddedResource Include="Controls\FormDialog.resx">
<DependentUpon>FormDialog.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Controls\FormLexicon.resx">
<DependentUpon>FormLexicon.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Controls\FormLoading.resx">
<DependentUpon>FormLoading.cs</DependentUpon>
</EmbeddedResource>
@ -418,6 +456,9 @@
<EmbeddedResource Include="Controls\FormMessage.resx">
<DependentUpon>FormMessage.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Controls\FormReadme.resx">
<DependentUpon>FormReadme.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Controls\FormSetting.resx">
<DependentUpon>FormSetting.cs</DependentUpon>
</EmbeddedResource>
@ -542,6 +583,17 @@
<ItemGroup>
<None Include="Resources\icon-ai-robot-wps.jpg" />
</ItemGroup>
<ItemGroup>
<None Include="Resources\icon-manual.png" />
</ItemGroup>
<ItemGroup>
<None Include="Resources\icon-manual-wps.jpg" />
</ItemGroup>
<ItemGroup>
<Content Include="favicon.ico" />
<None Include="Resources\icon-update-new-wps.jpg" />
<None Include="Resources\icon-update-new.png" />
</ItemGroup>
<PropertyGroup>
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">10.0</VisualStudioVersion>
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
@ -569,6 +621,9 @@
<PlatformTarget>AnyCPU</PlatformTarget>
<LangVersion>7.3</LangVersion>
</PropertyGroup>
<PropertyGroup>
<ApplicationIcon>favicon.ico</ApplicationIcon>
</PropertyGroup>
<!-- Include the build rules for a C# project. -->
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- Include additional build rules for an Office application add-in. -->

View File

@ -8,7 +8,7 @@
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|AnyCPU'">
<StartAction>Project</StartAction>
<StartProgram>C:\Soft\Kingsoft\WPS Office\12.1.0.18608\office6\wps.exe</StartProgram>
<StartProgram>C:\Soft\Kingsoft\WPS Office\12.1.0.20784\office6\wps.exe</StartProgram>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|AnyCPU'">
<StartAction>Project</StartAction>

View File

@ -2,22 +2,18 @@
using AIProofread.core;
using AIProofread.Model;
using AIProofread.Util;
using log4net;
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 NPOI;
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.Threading;
using System.Windows.Forms;
using UtilLib;
using Document = Microsoft.Office.Interop.Word.Document;
@ -45,11 +41,12 @@ namespace AIProofread
public static Dictionary<int, ProofreadItem> marks;
private static int selectProofreadId = -1;
//private static int selectProofreadId = -1;
private static object missing = System.Reflection.Missing.Value;
private static UpgradeData CurrentUpgrade = null;
public static readonly ILog Logger = LogHelper.GetLogger(typeof(Bridge));
public void ShowUpgradeView()
{
@ -112,6 +109,10 @@ namespace AIProofread
Globals.ThisAddIn.formCommonsenseDetection.SendMessageToWeb("show-history", null);
}
public void HasNewVersion()
{
Globals.ThisAddIn.ribbon.ShowNewVersionIcon();
}
/// <summary>
/// 检查插件更新信息
/// </summary>
@ -143,7 +144,7 @@ namespace AIProofread
}
catch (Exception ex)
{
Logger.Log(ex);
Logger.Error(ex);
}
}
@ -154,6 +155,8 @@ namespace AIProofread
data["version"] = Config.APP_VERSION;
data["platform"] = Config.IS_WPS ? "wps" : "word";
data["environment"] = Config.APP_ENV.ToString();
data["deviceId"] = Config.DeviceId;
data["buildVersion"] = Config.BuildVersion;
return JsonConvert.SerializeObject(data);
}
public void SetBtnStatus(string key, bool status)
@ -240,16 +243,19 @@ namespace AIProofread
try
{
string applicationBase = AppDomain.CurrentDomain.SetupInformation.ApplicationBase;
string path = "updater.exe";
ProcessStartInfo processStartInfo = new ProcessStartInfo(Path.Combine(applicationBase, Path.GetFileName(path)))
string path = Path.Combine(applicationBase, Path.GetFileName("updater.exe"));
ProcessStartInfo processStartInfo = new ProcessStartInfo()
{
WorkingDirectory = applicationBase,
FileName = path,
UseShellExecute = true,
Verb = "runas"
};
Process.Start(processStartInfo);
}
catch (Exception e)
{
Logger.Log(e);
Logger.Error("启动升级程序失败", e);
if (showFail)
{
MessageBox.Show("启动升级程序失败,请重试");
@ -273,13 +279,18 @@ namespace AIProofread
public void ShowLog(string message)
{
Logger.Log((Config.IS_WPS ? "WPS" : "WORD") + "-WEB", message);
Logger.Info((Config.IS_WPS ? "WPS" : "WORD") + "-WEB " + message);
}
public void ShowLoginForm(string action)
{
Globals.ThisAddIn.ShowLoginForm(action);
}
public void ShowLexiconForm()
{
//Globals.ThisAddIn.ShowLoginForm(action);
(new FormLexicon()).Show();
}
public void Logout(string action)
{
// web同步注销到ribbon
@ -309,6 +320,19 @@ namespace AIProofread
{
return Tools.GetAllText(Globals.ThisAddIn.Application.ActiveDocument);
}
public bool SaveDocument(int documentId)
{
var document = documentId > 0 ? Globals.ThisAddIn.GetDocumentById(documentId) : Globals.ThisAddIn.ActiveDocument;
try
{
document.Save();
return true;
}catch (Exception ex)
{
Logger.Error("保存文档失败", ex);
}
return false;
}
public bool Saved(int documentId)
{
@ -316,6 +340,43 @@ namespace AIProofread
return document.CurrentDocument.Saved;
}
public void Callback(string callbackId, string result)
{
Globals.ThisAddIn.GlobalCallback(callbackId, result);
}
/// <summary>
/// 判断是否处理修订模式,如果没有在修订模式则回调返回false
/// </summary>
/// <param name="documentId"></param>
/// <param name="callback"></param>
public void CheckInTrackRevisions(string message, int documentId, string callbackId)
{
var doc = documentId > 0 ? Globals.ThisAddIn.GetDocumentById(documentId) : Globals.ThisAddIn.ActiveDocument;
if (doc.CurrentDocument.TrackRevisions)
{
doc.RunInMainThread(() =>
{
var result = FormMessage.ShowMessage(message, "确认", "取消", null);
if (result == DialogResult.OK)
{
// 关闭修订模式
doc.CurrentDocument.TrackRevisions = false;
Callback(callbackId, "false");
}
else
{
Callback(callbackId, "true");
}
});
}
else
{
Callback(callbackId, "false");
}
}
/// <summary>
/// 获取文档数据
/// </summary>
@ -326,15 +387,31 @@ namespace AIProofread
var documentInfo = documentId > 0 ? Globals.ThisAddIn.GetDocumentById(documentId) : Globals.ThisAddIn.ActiveDocument;
var doc = documentInfo.CurrentDocument;
// 判断是否处理修订模式
if (doc.TrackRevisions)
{
var ret = MessageBox.Show("该文档已开启修订模型,请关闭此模式再进行校对。是否关闭?", "提示", MessageBoxButtons.YesNo);
if (ret == DialogResult.Yes)
{
doc.TrackRevisions = false;
}
else
{
data.Add("code", 1);
data.Add("message", "文档存在未处理的修订,请处理后再进行校对");
return Tools.GetJSONString(data);
}
}
// 判断是否需要强制升级
if (ShouldUpgradeForced())
{
data.Add("code", 2);
data.Add("message", "请升级插件后再进行校对");
data.Add("message", "请升级插件后再进行校对");
}
else if (doc.ProtectionType != WdProtectionType.wdNoProtection)
{
data.Add("code", 3);
data.Add("message", "文档受保护,无法编辑");
data.Add("message", "文档受保护,请另存文档后再进行校对");
}
else if (doc.ReadOnly)
{
@ -362,7 +439,24 @@ namespace AIProofread
data.Add("documentId", GeIdBytDocument(doc));
data.Add("wordsCount", doc.Words.Count);
data.Add("charactersCount", doc.Characters.Count);
data.Add("content", Tools.GetAllText(doc));
try
{
data.Add("content", Tools.GetAllText(doc));
}
catch (POIXMLException ex)
{
Logger.Error("校对文档格式有误或内容异常", ex);
data["code"] = 5;
data["message"] = "文档格式有误或内容异常,请另存文档后再进行校对";
}
catch (Exception ex)
{
Logger.Error("校对文档格式有误或内容异常", ex);
data["code"] = 6;
data["message"] = "文档格式有误或内容异常,请另存文档后再进行校对";
throw ex;
}
//if (loadingDialog != null && !loadingDialog.IsDisposed)
//{
// loadingDialog.Close();
@ -371,6 +465,22 @@ namespace AIProofread
return Tools.GetJSONString(data);
}
public string GetDocumentInfo(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;
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);
return Tools.GetJSONString(data);
}
/// <summary>
/// 根据位置获取文档区域文本
/// </summary>
@ -406,7 +516,7 @@ namespace AIProofread
var lineNumber = range.get_Information(WdInformation.wdFirstCharacterLineNumber);
return JSONObject.Create()
.Put("text",text)
.Put("text", text)
.Put("page", pageNumber)
.Put("line", lineNumber)
.ToString();
@ -486,20 +596,21 @@ namespace AIProofread
webViewDict.Add(name, webView);
}
Logger.Debug("初始化Main Pane Web环境 开始");
// 禁用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);
Logger.Debug("初始化Main Pane Web环境 结束");
}
catch (Exception ex)
{
Logger.Log(ex);
Debug.WriteLine("初始化web环境失败" + ex.Message);
Logger.Error("初始化web环境失败", ex);
//LogHelper.Log(ex);
}
}
@ -508,6 +619,20 @@ namespace AIProofread
public void ClearCurrentDocumentMarks() => Globals.ThisAddIn.ActiveDocument?.ClearAllProofreadMark();
public void removeBookmark(string markId) => DocumentUtil.RemoveBookmark(markId);
/// <summary>
/// 获取设备ID
/// </summary>
/// <returns></returns>
public string GetDeviceId()
{
return Config.DeviceId;
}
/// <summary>
/// 设置帮助文档地址
/// </summary>
/// <param name="url"></param>
public void SetHelpUrl(string url) => Config.USER_MANUAL_URL = url;
public string getAllBookmark()
{
@ -625,7 +750,6 @@ namespace AIProofread
public void SelectMarkById(int proofreadId, int documentId)
{
Globals.ThisAddIn.ActiveDocument?.SelectMarkById(proofreadId, false);
}
@ -651,7 +775,7 @@ namespace AIProofread
}
catch (Exception ex)
{
Logger.Log("Initial Content error:" + ex.Message + "\n" + ex.StackTrace + "\n\n");
Logger.Error("Initial Content error:", ex);
return "false";
}
return "true";
@ -688,32 +812,61 @@ namespace AIProofread
}
// 保存文件
public string WriteText(string content, string path)
public void WriteText(string content, string filename, string callbackId)
{
try
Globals.ThisAddIn.ActiveDocument.RunInMainThread(() =>
{
File.WriteAllText(path, content);
return BridgeResult.Success("ok");
}
catch (Exception ex)
{
return BridgeResult.Error(-1, ex.Message);
}
var json = JSONObject.Create();
try
{
string currentName = Globals.ThisAddIn.Application.ActiveDocument.Name;
// 去掉文件名后缀
currentName = currentName.Substring(0, currentName.LastIndexOf("."));
SaveFileDialog sfd = new SaveFileDialog
{
// 设置默认文件名
FileName = filename,
Filter = "文本文件|*.txt"
};
var result = sfd.ShowDialog();
// 如果用户取消选择,则返回
if (result != DialogResult.Cancel)
{
if (File.Exists(sfd.FileName))
{
File.Delete(sfd.FileName);
}
File.WriteAllText(sfd.FileName, content);
json.Put("status", "success");
}
}
catch (Exception ex)
{
json.Put("status", "error").Put("message", ex.Message);
}
Globals.ThisAddIn.GlobalCallback(
callbackId,
json.ToString()
);
});
//
}
/// <summary>
/// 导出勘误表
/// </summary>
/// <returns></returns>
public string ExportProofreadResult()
public string ExportProofreadResult(string modelType)
{
try
{
Globals.ThisAddIn.ActiveDocument.ExportResult();
Globals.ThisAddIn.ActiveDocument.ExportResult(modelType);
return BridgeResult.Success();
}
catch (Exception ex)
{
Logger.Error("导出勘误表失败:" + ex.Message, ex);
return BridgeResult.Error(-1, ex.Message);
}
}
@ -727,6 +880,7 @@ namespace AIProofread
}
catch (Exception ex)
{
Logger.Error("读取文件失败:" + ex.Message, ex);
return BridgeResult.Error(-1, ex.Message);
}
}
@ -737,6 +891,11 @@ namespace AIProofread
Globals.ThisAddIn.ActiveDocument.FocusToPanel();
}
public string GetProofreadOriginData()
{
return Tools.GetJSONString(Globals.ThisAddIn.ActiveDocument.GetProofreadOriginData());
}
public string SaveCache(int documentId, string cache, bool silent)
{
var document = Globals.ThisAddIn.GetDocumentById(documentId);
@ -759,7 +918,7 @@ namespace AIProofread
}
try
{
Logger.Log("SaveCache " + document.fileName + " used " + document.ProofreadCachePath);
Logger.Debug("SaveCache " + document.fileName + " used " + document.ProofreadCachePath);
if (File.Exists(document.ProofreadCachePath))
{
@ -772,6 +931,7 @@ namespace AIProofread
}
catch (Exception ex)
{
Logger.Error("保存缓存失败:" + ex.Message, ex);
return BridgeResult.Error(-1, ex.Message);
}
}
@ -789,13 +949,14 @@ namespace AIProofread
{
return BridgeResult.Error(1, "cache-not-exists");
}
Logger.Log("Load cache " + document.fileName + " used " + document.ProofreadCachePath);
Logger.Info("Load cache " + document.fileName + " used " + document.ProofreadCachePath);
try
{
return BridgeResult.Success(File.ReadAllText(document.ProofreadCachePath));
}
catch (Exception ex)
{
Logger.Error("加载缓存失败:" + ex.Message, ex);
return BridgeResult.Error(ex.Message);
}
}
@ -809,8 +970,9 @@ namespace AIProofread
File.Delete(Globals.ThisAddIn.ActiveDocument.ProofreadCachePath);
}
}
catch (Exception)
catch (Exception ex)
{
Logger.Error("删除缓存失败:" + ex.Message, ex);
return false;
}
return true;
@ -823,16 +985,18 @@ namespace AIProofread
return BridgeResult.Success(result == DialogResult.Yes ? "yes" : "no");
}
public string InitProofreadCacheList(string content)
public string InitProofreadCacheList(string content, string originData)
{
try
{
List<CorrectContext> list = JsonConvert.DeserializeObject<List<CorrectContext>>(content);
Globals.ThisAddIn.InitProofreadCacheList(list);
Dictionary<int, ProofreadRangeInfo> dics = string.IsNullOrEmpty(originData) ? null : JsonConvert.DeserializeObject<Dictionary<int, ProofreadRangeInfo>>(originData);
Globals.ThisAddIn.InitProofreadCacheList(list, dics);
return BridgeResult.Success();
}
catch (Exception ex)
{
Logger.Error("初始化缓存失败:" + ex.Message, ex);
return BridgeResult.Error(ex);
}
}

View File

@ -1,4 +1,5 @@
using System;
using System.IO;
using System.Text.RegularExpressions;
namespace AIProofread
@ -9,33 +10,63 @@ namespace AIProofread
Test,
Prod
}
public class AppServer
{
/// <summary>
/// 开发环境
/// </summary>
public const string DEV = "http://localhost:5173/";
/// <summary>
/// 一体机
/// </summary>
public const string ALL_IN_ONE = "http://112.48.25.226:89/";
/// <summary>
/// 果麦预发布环境
/// </summary>
public const string PRE = "https://pre-gm-plugin.gachafun.com/";
/// <summary>
/// 果麦生产环境
/// </summary>
public const string PROD = "https://gm-plugin.gachafun.com/";
/// <summary>
/// 测试环境
/// </summary>
public const string TEST = "http://tt-plugin.zverse.group/";
}
public class Config
{
public static readonly string APP_NAME = "AI校对王";
public static readonly string APP_VERSION = "2.1.1";
public static readonly string APP_VERSION = "2.2.6";
public static readonly string BuildVersion = "20250623_1757";
public static bool IS_WPS = false;
public static bool UpgradeForcedNotice = false;
public static readonly string APP_BASE_DIR = AppDomain.CurrentDomain.BaseDirectory;
public static readonly string CONFIG_FILE = AppDomain.CurrentDomain.BaseDirectory + "app.json";
public static string USER_MANUAL_URL = "https://aiprhelp.guomai.cn/";
/// <summary>
/// 文本背景色
/// </summary>
public static readonly string TextBackgroundColor = "#D6AA69";
#if DEBUG
public static readonly string TextBackgroundColor = "#E9DABB"; // e9dabb D6AA69
public static string DeviceId = "";
#if DEBUG
/// <summary>
/// 网页访问地址
/// </summary>
public static string WEB_PATH = "http://localhost:5173/"; //pre-gm-plugin.gachafun.com localhost:5173 gm2-plugin.zverse.group
public static string WEB_PATH = AppServer.DEV; //pre-gm-plugin.gachafun.com localhost:5173 gm2-plugin.zverse.group
public static bool RUN_IN_DEBUG = true;
public static AppEnvironment APP_ENV = AppEnvironment.Dev;
#else
public static string WEB_PATH = "https://gm-plugin.gachafun.com/"; // gm-plugin.gachafun.com pre-gm-plugin.gachafun.com
#else
public static string WEB_PATH = AppServer.PROD; // gm-plugin.gachafun.com pre-gm-plugin.gachafun.com
public static bool RUN_IN_DEBUG = false;
public static AppEnvironment APP_ENV = AppEnvironment.Prod;
#endif
#endif
public static readonly string APP_DATA_PATH = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\ai_proofread";
public static readonly string APP_LOG_PATH = APP_DATA_PATH + "\\logs\\";
public static readonly string APP_README_PATH = APP_DATA_PATH + "\\readme\\";
public static readonly string WEB_DATA_PATH = APP_DATA_PATH + "\\userdata";
/// <summary>
@ -44,6 +75,14 @@ namespace AIProofread
public static readonly string BOOKMARK_NAME_PREFIX = "ai_proofread_";
private static readonly Regex regex = new Regex("^ai_proofread_\\d+$");
public static string GetCurrentVersionReadmeCacheFile()
{
if (!Directory.Exists(APP_README_PATH))
{
Directory.CreateDirectory(APP_README_PATH);
}
return Path.Combine(APP_README_PATH, APP_VERSION + ".txt");
}
public static bool IsProofreadMark(string name)
{
@ -76,7 +115,8 @@ namespace AIProofread
/// <returns></returns>
public static string WebPath(string path)
{
return WEB_PATH + path;
Random r = new Random();
return WEB_PATH + path + (path.IndexOf("?") == -1 ? "?":"&") + $"ver={APP_VERSION}&r=" + r.NextDouble();
}
}
}

View File

@ -1,11 +1,9 @@
using Microsoft.Web.WebView2.Core;
using log4net;
using Microsoft.Web.WebView2.Core;
using Microsoft.Web.WebView2.WinForms;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace AIProofread.Controls
@ -14,6 +12,7 @@ namespace AIProofread.Controls
[ComVisible(true)]
public class BaseWinForm : Form
{
#region WIN32 API
[DllImport("Gdi32.dll", EntryPoint = "CreateRoundRectRgn")]
private static extern IntPtr CreateRoundRectRgn(
int nLeftRect, // x-coordinate of upper-left corner
@ -49,6 +48,9 @@ namespace AIProofread.Controls
private const int WM_NCHITTEST = 0x84; // variables for dragging the form
private const int HTCLIENT = 0x1;
private const int HTCAPTION = 0x2;
#endregion
private readonly ILog logger = LogHelper.GetLogger(typeof(BaseWinForm));
protected override CreateParams CreateParams
{
@ -110,7 +112,12 @@ namespace AIProofread.Controls
this.FormBorderStyle = FormBorderStyle.None;
}
protected async void InitWebView(WebView2 webView,String url,string name,Action callaback = null)
public void SetHeight(int height)
{
this.Height = height;
}
protected async void InitWebView(WebView2 webView, String url, string name, Action callaback = null)
{
//Bridge.InitWebEnvAsync(name, webView);
try
@ -123,16 +130,48 @@ namespace AIProofread.Controls
var eventForwarder = new EventForwarder(this);
webView.CoreWebView2.AddHostObjectToScript("event", eventForwarder);
webView.CoreWebView2.AddHostObjectToScript("host", this);
webView.CoreWebView2.AddHostObjectToScript("bridge", Bridge.bridge);
if(callaback != null)
if (callaback != null)
{
callaback();
}
webView.Source = new Uri(url);
}catch (Exception ex)
}
catch (Exception ex)
{
Logger.Log("\ninit webview error:" + ex.Message + "\n" + ex.StackTrace);
logger.Error("\ninit webview error:" + ex.Message, ex);
}
}
public void Download(string url)
{
Globals.ThisAddIn.ActiveDocument.RunInMainThread(() =>
{
var sfd = new SaveFileDialog();
sfd.Filter = "Excel文件|*.xlsx";
sfd.DefaultExt = ".xlsx";
if (sfd.ShowDialog() == DialogResult.OK)
{
var fileName = sfd.FileName;
Download(url, fileName);
}
});
}
public void Download(string url, string fileName)
{
// 现在url对应文件并保存到fileName
try
{
using (var client = new WebClient())
{
client.DownloadFile(url, fileName);
}
}
catch (Exception ex)
{
logger.Error("\nDownload error:" + ex.Message, ex);
}
}
}

View File

@ -55,6 +55,7 @@
this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
this.Name = "FormCommonsenseDetection";
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
this.Text = "常识性检测";
this.Load += new System.EventHandler(this.FormCommonsenseDetection_Load);
((System.ComponentModel.ISupportInitialize)(this.MainWebView)).EndInit();
this.ResumeLayout(false);

View File

@ -1,8 +1,8 @@
using AIProofread.core;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Threading;
using UtilLib;
namespace AIProofread.Controls
@ -13,8 +13,7 @@ namespace AIProofread.Controls
{
private bool initialized = false;
private string action;
private object data;
private List<WebMessage> actions = new List<WebMessage>();
public FormCommonsenseDetection()
{
@ -45,17 +44,24 @@ namespace AIProofread.Controls
return;
}
// 添加到队列
this.action = action;
this.data = data;
actions.Add(new WebMessage(action, data));
//this.action = action;
//this.data = data;
}
public void InitializationCompleted()
{
if (!this.initialized && !string.IsNullOrEmpty(this.action))
if (!this.initialized && actions.Count > 0) // !string.IsNullOrEmpty(this.action)
{
SendToWeb(this.action, this.data);
this.action = null;
this.data = null;
actions.ForEach(item =>
{
SendToWeb(item.Message, item.Data);
});
// clear
actions.Clear();
//SendToWeb(this.action, this.data);
//this.action = null;
//this.data = null;
}
this.initialized = true;
}

View File

@ -40,7 +40,7 @@
this.WebViewContact.Dock = System.Windows.Forms.DockStyle.Fill;
this.WebViewContact.Location = new System.Drawing.Point(0, 0);
this.WebViewContact.Name = "WebViewContact";
this.WebViewContact.Size = new System.Drawing.Size(380, 216);
this.WebViewContact.Size = new System.Drawing.Size(620, 450);
this.WebViewContact.TabIndex = 0;
this.WebViewContact.ZoomFactor = 1D;
//
@ -48,7 +48,7 @@
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(380, 216);
this.ClientSize = new System.Drawing.Size(620, 450);
this.Controls.Add(this.WebViewContact);
this.Name = "FormContact";
this.ShowIcon = false;

View File

@ -4,12 +4,15 @@ using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace AIProofread.Controls
{
[ClassInterface(ClassInterfaceType.AutoDual)]
[ComVisible(true)]
public partial class FormContact : BaseWinForm
{
public FormContact()

View File

@ -0,0 +1,66 @@
namespace AIProofread.Controls
{
partial class FormLexicon
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.MainWebView = new Microsoft.Web.WebView2.WinForms.WebView2();
((System.ComponentModel.ISupportInitialize)(this.MainWebView)).BeginInit();
this.SuspendLayout();
//
// MainWebView
//
this.MainWebView.AllowExternalDrop = true;
this.MainWebView.CreationProperties = null;
this.MainWebView.DefaultBackgroundColor = System.Drawing.Color.White;
this.MainWebView.Dock = System.Windows.Forms.DockStyle.Fill;
this.MainWebView.Location = new System.Drawing.Point(0, 0);
this.MainWebView.Name = "MainWebView";
this.MainWebView.Size = new System.Drawing.Size(1000, 640);
this.MainWebView.TabIndex = 0;
this.MainWebView.ZoomFactor = 1D;
//
// FormLexicon
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(1000, 640);
this.Controls.Add(this.MainWebView);
this.Name = "FormLexicon";
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
this.Text = "FormLexicon";
this.Load += new System.EventHandler(this.FormLexicon_Load);
((System.ComponentModel.ISupportInitialize)(this.MainWebView)).EndInit();
this.ResumeLayout(false);
}
#endregion
private Microsoft.Web.WebView2.WinForms.WebView2 MainWebView;
}
}

View File

@ -0,0 +1,21 @@
using System;
using System.Runtime.InteropServices;
namespace AIProofread.Controls
{
[ClassInterface(ClassInterfaceType.AutoDual)]
[ComVisible(true)]
public partial class FormLexicon : BaseWinForm
{
public FormLexicon()
{
InitializeComponent();
}
private void FormLexicon_Load(object sender, EventArgs e)
{
// 初始化
InitWebView(MainWebView, Config.WebPath("lexicon"), "lexicon");
}
}
}

View File

@ -0,0 +1,120 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

View File

@ -5,7 +5,7 @@ namespace AIProofread.Controls
{
public partial class FormLogger : Form
{
private ListView LogListView;
private ListView LogListView = new ListView();
public FormLogger()
{
@ -96,7 +96,7 @@ namespace AIProofread.Controls
private void FormLogger_FormClosed(object sender, FormClosedEventArgs e)
{
Logger.LoggerForm = null;
LogHelper.LoggerForm = null;
}
private void TsmiClear_Click(object sender, EventArgs e)

View File

@ -1,8 +1,11 @@
using System;
using System.Runtime.InteropServices;
using System.Windows.Forms;
namespace AIProofread.Controls
{
[ClassInterface(ClassInterfaceType.AutoDual)]
[ComVisible(true)]
public partial class FormLogin : BaseWinForm
{
@ -11,6 +14,19 @@ namespace AIProofread.Controls
public FormLogin()
{
InitializeComponent();
this.FormClosed += (s, e) =>
{
// 关闭时释放资源
try
{
if (web != null)
{
web.Dispose();
web = null;
}
}
catch { };
};
//Bridge.InitWebEnvAsync("login", web);
//Bridge.AddEventHandler(BridgeEvent.LoginSuccess, OnLoginSuccess);
}
@ -18,6 +34,19 @@ namespace AIProofread.Controls
{
this.action = action;
InitializeComponent();
this.FormClosed += (s, e) =>
{
// 关闭时释放资源
try
{
if (web != null)
{
web.Dispose();
web = null;
}
}
catch { };
};
}
private void OnLoginSuccess(object sender, EventArgs e)
@ -28,9 +57,9 @@ namespace AIProofread.Controls
private void FormLogin_Load(object sender, EventArgs e)
{
//this.web.Source = new Uri(Config.WebPath("#login"));
InitWebView(web, Config.WebPath("login?action=" + this.action), "login");
var r = new FormLogin();
InitWebView(web, Config.WebPath("login?action=" + this.action + "&version=" + Config.APP_VERSION + "&t=" + DateTime.Now.Ticks), "login");
}
}
}

View File

@ -85,6 +85,24 @@ namespace AIProofread.Controls
formMessage.Show();
return formMessage;
}
public static DialogResult ShowMessage(string message, string confirmText = "确认",string cancelText="取消", string confirmAction = null)
{
FormMessage formMessage = new FormMessage();
formMessage.SetMessage(message);
formMessage.currentConfirmAction = confirmAction;
formMessage.BtnClose.Text = cancelText;
if (string.IsNullOrEmpty(confirmText))
{
formMessage.HideConfirm();
}
else
{
formMessage.BtnConfirm.Text = confirmText;
formMessage.ResetButtons();
}
return formMessage.ShowDialog();
}
public static DialogResult ShowMessage(string message, string confirmText = "确认", string confirmAction = null)
{
FormMessage formMessage = new FormMessage();
@ -105,6 +123,11 @@ namespace AIProofread.Controls
private void BtnClose_Click(object sender, EventArgs e)
{
if (!string.IsNullOrEmpty(currentConfirmAction))
{
string time = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
Globals.ThisAddIn.SendMessageToWeb(currentConfirmAction, "cancel");
}
this.Close();
}
@ -113,7 +136,7 @@ namespace AIProofread.Controls
if (!string.IsNullOrEmpty(currentConfirmAction))
{
string time = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
Globals.ThisAddIn.SendMessageToWeb(currentConfirmAction, time);
Globals.ThisAddIn.SendMessageToWeb(currentConfirmAction, "confirm");
}
this.Close();
}

View File

@ -0,0 +1,68 @@
namespace AIProofread.Controls
{
partial class FormReadme
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.WebView_ReadMe = new Microsoft.Web.WebView2.WinForms.WebView2();
((System.ComponentModel.ISupportInitialize)(this.WebView_ReadMe)).BeginInit();
this.SuspendLayout();
//
// WebView_ReadMe
//
this.WebView_ReadMe.AllowExternalDrop = true;
this.WebView_ReadMe.CreationProperties = null;
this.WebView_ReadMe.DefaultBackgroundColor = System.Drawing.Color.White;
this.WebView_ReadMe.Dock = System.Windows.Forms.DockStyle.Fill;
this.WebView_ReadMe.Location = new System.Drawing.Point(0, 0);
this.WebView_ReadMe.Name = "WebView_ReadMe";
this.WebView_ReadMe.Size = new System.Drawing.Size(600, 480);
this.WebView_ReadMe.TabIndex = 0;
this.WebView_ReadMe.ZoomFactor = 1D;
//
// FormReadme
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(600, 480);
this.Controls.Add(this.WebView_ReadMe);
this.Name = "FormReadme";
this.ShowIcon = false;
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
this.Text = "版本更新说明";
this.TopMost = true;
this.Load += new System.EventHandler(this.FormReadme_Load);
((System.ComponentModel.ISupportInitialize)(this.WebView_ReadMe)).EndInit();
this.ResumeLayout(false);
}
#endregion
private Microsoft.Web.WebView2.WinForms.WebView2 WebView_ReadMe;
}
}

View File

@ -0,0 +1,55 @@
using AIProofread.core;
using System;
using System.IO;
using System.Runtime.InteropServices;
namespace AIProofread.Controls
{
[ClassInterface(ClassInterfaceType.AutoDual)]
[ComVisible(true)]
public partial class FormReadme : BaseWinForm
{
/// <summary>
/// 单例实例。
/// </summary>
private static FormReadme INSTANCE = null;
public FormReadme()
{
InitializeComponent();
// 写入缓存
File.WriteAllText(Config.GetCurrentVersionReadmeCacheFile(), DateTime.Now.ToString("yyyy-M-d"));
}
/// <summary>
/// 获取单例对象。
/// </summary>
public static FormReadme GetInstance(bool newInstance = true)
{
if (newInstance && (INSTANCE == null || INSTANCE.IsDisposed))
{
INSTANCE = new FormReadme();
}
return INSTANCE;
}
public void CloseAndDispose()
{
if (INSTANCE != null && !INSTANCE.IsDisposed)
{
INSTANCE.Close();
INSTANCE = null;
}
}
private void FormReadme_Load(object sender, EventArgs e)
{
// 初始化
InitWebView(WebView_ReadMe, Config.WebPath("version-readme"), "version-readme", () =>
{
WebView_ReadMe.CoreWebView2.AddHostObjectToScript("readme", this);
});
}
}
}

View File

@ -0,0 +1,120 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

View File

@ -52,6 +52,7 @@
this.ClientSize = new System.Drawing.Size(800, 450);
this.Controls.Add(this.WebView);
this.Name = "FormWebView";
this.ShowIcon = false;
this.Text = "FormWebView";
this.Load += new System.EventHandler(this.FormWebView_Load);
((System.ComponentModel.ISupportInitialize)(this.WebView)).EndInit();

View File

@ -1,5 +1,6 @@
using Microsoft.Office.Interop.Word;

using Microsoft.Web.WebView2.Core;
using Microsoft.Web.WebView2.WinForms;
using System;
using System.Windows.Forms;
@ -11,15 +12,55 @@ namespace AIProofread.Controls
{
InitializeComponent();
Bridge.InitWebEnvAsync("main", web);
//this.minWidth = 420 * LabelWidth() / 42;
//this.MinimumSize = new System.Drawing.Size(this.minWidth, 0);
}
private bool isShowingErrorPage = false;
public void WebView2NavigationCompleted(object sender, CoreWebView2NavigationCompletedEventArgs e)
{
if (isShowingErrorPage)
{
return;
}
if (e.IsSuccess)
{
isShowingErrorPage = false;
return;
}
isShowingErrorPage = true;
string errorPageHtml = @"
<html>
<head>
<title></title>
<style>
body { font-family: sans-serif; text-align: center; padding-top: 50px; user-select: none; }
h1 { color: #d00; }
</style>
</head>
<body oncontextmenu='return false;'>
<h1></h1>
<p></p>
<a href=" + "\"javascript:window.chrome.webview.postMessage('reload');\"" + @">重新加载</a>
</body>
</html>";
(sender as WebView2).CoreWebView2.NavigateToString(errorPageHtml);
}
private void ProofreadMainControl_Load(object sender, EventArgs e)
{
this.web.Source = new Uri(Config.WebPath("correct?version=" + Config.APP_VERSION + "&t=" + DateTime.Now.Ticks));
this.web.NavigationCompleted += WebView2NavigationCompleted;
this.web.WebMessageReceived += (s, ex) =>
{
if (ex.TryGetWebMessageAsString() == "reload")
{
isShowingErrorPage = false;
web.Source = new Uri(Config.WebPath("correct"));
}
};
this.web.Source = new Uri(Config.WebPath("correct" ));
//this.SizeChanged += ProofreadMainControl_SizeChanged;
}

103
AIProofread/LogHelper.cs Normal file
View File

@ -0,0 +1,103 @@
using AIProofread.Controls;
using log4net.Config;
using log4net;
using System;
using System.IO;
using log4net.Appender;
using log4net.Layout;
using log4net.Repository.Hierarchy;
namespace AIProofread
{
public class LogHelper
{
public static FormLogger LoggerForm;
//private static readonly string AppDataPath = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
public static ILog Logger = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
static LogHelper()
{
//log4net.GlobalContext.Properties["APP_DATA"] = Config.APP_LOG_PATH;
//XmlConfigurator.Configure();
//Logger = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
Hierarchy hierarchy = (Hierarchy)LogManager.GetRepository();
PatternLayout layout = new PatternLayout("%date [%thread] %-5level %logger - %message%newline");
layout.ActivateOptions();
//string appDataPath = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
//string logFilePath = Path.Combine(appDataPath, "YourAppName", "logs");
RollingFileAppender roller = new RollingFileAppender();
roller.File = Config.APP_LOG_PATH;
roller.AppendToFile = true;
roller.RollingStyle = RollingFileAppender.RollingMode.Date;
roller.DatePattern = "yyyy-MM-dd'.txt'";
roller.StaticLogFileName = false;
roller.Layout = layout;
roller.ActivateOptions();
hierarchy.Root.AddAppender(roller);
hierarchy.Root.Level = log4net.Core.Level.Info;
hierarchy.Configured = true;
}
/// <summary>
///
/// </summary>
/// <param name="msg"></param>
public static void Log(string tag, string message)
{
string time = DateTime.Now.ToString("HH:mm:ss");
// 如果日志窗口已经打开,则显示日志
if (LoggerForm != null && !LoggerForm.IsDisposed && LoggerForm.Visible)
{
LoggerForm.Log(time, tag, message);
}
if (!Directory.Exists(Config.APP_LOG_PATH))
{
Directory.CreateDirectory(Config.APP_LOG_PATH);
}
Logger.Debug($"[{tag}] {message}");
//try
//{
// string path = Config.APP_LOG_PATH + DateTime.Now.ToString("yyyy-MM-dd") + ".txt";
// StreamWriter streamWriter = File.AppendText(path);
// streamWriter.WriteLine("***************************[" + tag + "]***************************");
// streamWriter.WriteLine("消息:" + message);
// streamWriter.WriteLine("时间:" + time);
// streamWriter.WriteLine();
// streamWriter.Flush();
// streamWriter.Close();
// streamWriter.Dispose();
//}
//catch (Exception) { }
}
public static void Log(string msg)
{
Log((Config.IS_WPS ? "WPS" : "WORD"), msg);
}
public static void Log(Exception e)
{
Logger.Error(Config.IS_WPS ? "WPS" : "WORD" + e.ToString(), e);
//Log(e.Message + "\n" + e.StackTrace);
}
public static void Log(string tag, Exception e)
{
Logger.Error(tag, e);
}
public static void LogToWeb(string msg)
{
if (Config.RUN_IN_DEBUG)
{
Globals.ThisAddIn.SendMessageToWeb("DEBUG-LOG", msg);
}
}
internal static ILog GetLogger(Type type)
{
return LogManager.GetLogger(type);
}
}
}

View File

@ -1,67 +0,0 @@
using AIProofread.Controls;
using System;
using System.Collections.Generic;
using System.IO;
using System.Windows.Interop;
namespace AIProofread
{
public class Logger
{
public static FormLogger LoggerForm;
//private static readonly string AppDataPath = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
/// <summary>
///
/// </summary>
/// <param name="msg"></param>
public static void Log(string tag,string message)
{
string time = DateTime.Now.ToString("HH:mm:ss");
// 如果日志窗口已经打开,则显示日志
if (LoggerForm != null && !LoggerForm.IsDisposed && LoggerForm.Visible)
{
LoggerForm.Log(time, tag, message);
return;
}
string path = Config.APP_LOG_PATH + DateTime.Now.ToString("yyyy-MM-dd") + ".txt";
if (!Directory.Exists(Config.APP_LOG_PATH))
{
Directory.CreateDirectory(Config.APP_LOG_PATH);
}
try
{
StreamWriter streamWriter = File.AppendText(path);
streamWriter.WriteLine("***************************[" + tag + "]***************************");
streamWriter.WriteLine("消息:" + message);
streamWriter.WriteLine("时间:" + time);
streamWriter.WriteLine();
streamWriter.Flush();
streamWriter.Close();
streamWriter.Dispose();
}
catch (Exception e) { }
}
public static void Log(string msg)
{
Log((Config.IS_WPS ? "WPS" : "WORD"), msg);
}
public static void Log(Exception e)
{
Log(e.Message + "\n" + e.StackTrace);
}
public static void Log(string tag, Exception e)
{
Log(tag,e.Message + "\n" + e.StackTrace);
}
public static void LogToWeb(string msg)
{
if (Config.RUN_IN_DEBUG)
{
Globals.ThisAddIn.SendMessageToWeb("DEBUG-LOG", msg);
}
}
}
}

View File

@ -2,11 +2,14 @@
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Runtime.InteropServices;
using System.Threading;
using System.Windows.Forms;
using AIProofread.Controls;
using AIProofread.core;
using AIProofread.Util;
using DocumentFormat.OpenXml.Office2013.WebExtentionPane;
using log4net;
using Microsoft.Office.Interop.Word;
using Newtonsoft.Json;
using UtilLib;
@ -19,6 +22,7 @@ namespace AIProofread.Model
/// </summary>
public class DocumentInfo
{
public ILog Logger = LogHelper.GetLogger(typeof(DocumentInfo));
public static readonly int MIN_WIDTH = 420;
private static char[] ArticleSpecialChars = new char[4] { '\a', '\r', '\v', '\f' };
@ -73,8 +77,8 @@ namespace AIProofread.Model
}
}
public bool IsActive { get; internal set; }
public bool PaneVisible { get; set; }
public bool IsActive { get; internal set; } = false;
public bool PaneVisible { get; set; } = false;
public int Id { get; set; }
public CustomTaskPane TaskPane { get; set; }
@ -92,6 +96,7 @@ namespace AIProofread.Model
// 初始化
public DocumentInfo(Document doc)
{
Logger.Debug("new DocumentInfo for " + doc.Name);
this.CurrentDocument = doc;
Initialize();
}
@ -101,10 +106,34 @@ namespace AIProofread.Model
/// </summary>
public void ShowPane()
{
if (null != TaskPane)
if (null == TaskPane)
{
TaskPane.Visible = PaneVisible = true;
CreateTaskPane();
}
Logger.Debug("TaskPane.Visible {" + TaskPane == null ? "null" : (TaskPane.Visible ? "true" : "false") + " => true " + fileName);
TaskPane.Visible = PaneVisible = true;
}
/// <summary>
/// 隐藏面板
/// </summary>
public void HidePane()
{
//if (!PaneVisible) return;
ShowDocumentStatus("HidePane");
Logger.Debug($"TaskPane.Visible {TaskPane.Visible} => false");
TaskPane.Visible = PaneVisible = false;
}
public void RunInMainThread(Action action,bool isClose = false)
{
Logger.Debug("RunInMainThread for " + fileName);
if (null == TaskPane && !isClose)
{
CreateTaskPane();
}
TaskPane.Control.BeginInvoke(action);
}
public void ShowDialog(string message, string confirmText, string confirmAction)
@ -150,16 +179,7 @@ namespace AIProofread.Model
private void ShowDocumentStatus(string tag)
{
Logger.Log($"{fileName} {tag} PaneVisible is {PaneVisible} Poofread is {Proofread} Proofreading is {Proofreading}");
}
/// <summary>
/// 隐藏面板
/// </summary>
public void HidePane()
{
ShowDocumentStatus(" HidePane");
if (null != TaskPane) TaskPane.Visible = PaneVisible = false;
// Logger.Log($"{fileName} {tag} PaneVisible is {PaneVisible} Poofread is {Proofread} Proofreading is {Proofreading}");
}
/// <summary>
@ -167,51 +187,64 @@ namespace AIProofread.Model
/// </summary>
public void Active()
{
ShowDocumentStatus(" Active");
IsActive = true;
if (Config.IS_WPS && null != TaskPane && PaneVisible)
try
{
TaskPane.Visible = true;
Logger.Debug("激活 for " + CurrentDocument.Name + " 没有 visible is " + PaneVisible);
ShowDocumentStatus("Active");
IsActive = true;
if (Config.IS_WPS && null != TaskPane)
{
TaskPane.Visible = PaneVisible;
}
}
catch (Exception e)
{
Logger.Error("Active Error", e);
}
}
public void Deactive()
{
ShowDocumentStatus(" Deactive");
IsActive = false;
if (Config.IS_WPS)
try
{
if (PaneVisible)
{
// 异步等待一段时间 重新设置为true防止面板关闭时触发事件
ThreadPool.QueueUserWorkItem(state =>
{
Thread.Sleep(1000);
PaneVisible = true;
});
}
if (null != TaskPane && PaneVisible)
ShowDocumentStatus("Deactive");
IsActive = false;
if (Config.IS_WPS && null != TaskPane)
{
PaneVisible = TaskPane.Visible;
TaskPane.Visible = false;
Logger.Debug("取消 for " + CurrentDocument.Name + " current visible " + PaneVisible);
}
}
catch (Exception e)
{
Logger.Error("Deactive Error", e);
}
}
public void Dispose()
{
try
{
// 判断TaskPane是否已经释放
if (null == TaskPane) return;
if (TaskPane.Control.IsDisposed) return;
ProofreadMainControl control = (ProofreadMainControl)TaskPane.Control;
control.ResetWeb();
HidePane();
TaskPane?.Dispose();
// 释放com
try
{
Marshal.ReleaseComObject(CurrentDocument);
}
catch (Exception) { }
}
catch (Exception e)
{
Logger.Log("Error", e);
LogHelper.Log("Error", e);
}
}
@ -246,13 +279,14 @@ namespace AIProofread.Model
// 创建pane 并初始化
public void CreateTaskPane()
{
Logger.Debug("CreateTaskPane");
var control = new ProofreadMainControl();
if (MinWidth < 10)
{
MinWidth = MIN_WIDTH * control.LabelWidth() / 42;
}
// 创建pane
TaskPane = Globals.ThisAddIn.CustomTaskPanes.Add(control, " ");
TaskPane = Globals.ThisAddIn.CustomTaskPanes.Add(control, Config.RUN_IN_DEBUG ? CurrentDocument.Name : " ");
// 默认隐藏
TaskPane.Visible = false;
// 设置宽度
@ -264,21 +298,36 @@ namespace AIProofread.Model
TaskPane.VisibleChanged += TaskPane_VisibleChanged;
}
/// <summary>
/// 检查按钮状态
/// </summary>
public void CheckBtnStatus()
{
//
if (Globals.ThisAddIn.ribbon != null)
{
Globals.ThisAddIn.ribbon.BtnShowPanel.Enabled = !PaneVisible && Proofread;
var visible = TaskPane.Visible;
Globals.ThisAddIn.ribbon.BtnShowPanel.Enabled = !visible && Proofread;
Globals.ThisAddIn.ribbon.SetCommonBtnStatus(!Proofreading);
}
}
private void TaskPane_VisibleChanged(object sender, EventArgs e)
{
// 如果已经隐藏 则记录隐藏用于(WPS)多面板的切换的处理
PaneVisible = TaskPane.Visible;
// 异步等待500ms
System.Threading.Tasks.Task.Delay(1000).ContinueWith(t =>
{
Logger.Debug($"2==> VisibleChanged {CurrentDocument.Name} is {TaskPane.Visible}");
if (Config.IS_WPS)
{
if (CurrentDocument == Globals.ThisAddIn.ActiveDocument.CurrentDocument)
{
// 如果已经隐藏 则记录隐藏用于(WPS)多面板的切换的处理
PaneVisible = TaskPane.Visible;
}
}
Globals.ThisAddIn.ActiveDocument?.CheckBtnStatus();
});
CheckBtnStatus();
//Globals.ThisAddIn.ribbon.BtnShowPanel.Enabled = !TaskPane.Visible && Proofread;
}
@ -288,7 +337,11 @@ namespace AIProofread.Model
this.fileName = CurrentDocument.FullName;
ranges.Clear();
ComputeUniqueId();
if (TaskPane == null) CreateTaskPane();
if (TaskPane == null)
{
Logger.Debug("Initialize(334) and CreateTaskPane for " + CurrentDocument.Name);
CreateTaskPane();
}
}
@ -510,6 +563,22 @@ namespace AIProofread.Model
}
public void GlobalCallback(string callbackId, string result)
{
ProofreadMainControl control = (ProofreadMainControl)TaskPane.Control;
try
{
if (control.web.CoreWebView2 == null)
{
Thread.Sleep(1000);
}
control.web.CoreWebView2.ExecuteScriptAsync($"window.__global_callback_function('{callbackId}','{result}');");
}
catch (Exception ex)
{
LogHelper.Log("GlobalCallback", "call web global function error \n" + ex.Message + "\n" + callbackId + result);
}
}
public void SendMessageToWeb(string msg, object data)
{
var json = JsonConvert.SerializeObject(new WebMessage(msg, data));
@ -524,7 +593,7 @@ namespace AIProofread.Model
}
catch (Exception ex)
{
Logger.Log("SendMessage", "send message to web error \n" + ex.Message + "\n" + msg + data.ToString());
LogHelper.Log("SendMessage", "send message to web error \n" + ex.Message + "\n" + msg + data.ToString());
}
}
@ -548,7 +617,7 @@ namespace AIProofread.Model
}
catch (Exception ex)
{
Logger.Log("ClearAllProofreadMark", ex);
LogHelper.Log("ClearAllProofreadMark", ex);
}
// 清空marks
marks.Clear();
@ -596,9 +665,13 @@ namespace AIProofread.Model
//object goNext = WdGoToDirection.wdGoToNext;
//Globals.ThisAddIn.Application.ActiveWindow.Selection.GoTo(ref goToLine, ref goNext, ref lineNum);
//
object bookmark = WdGoToItem.wdGoToBookmark;
object bookmarkName = mark.Name;
Globals.ThisAddIn.Application.ActiveWindow.Selection.GoTo(ref bookmark, ref missing, ref missing, ref bookmarkName);
//object bookmark = WdGoToItem.wdGoToBookmark;
//object bookmarkName = mark.Name;
var targetRange = mark.Range;
// 选中
targetRange.Select();
Globals.ThisAddIn.Application.ActiveWindow.ScrollIntoView(targetRange);//.Selection.GoTo(ref bookmark, ref missing, ref missing, ref bookmarkName);
//
//mark.DisableCharacterSpaceGrid = false;
// 先滚动到可视区域
@ -622,9 +695,9 @@ namespace AIProofread.Model
List<InsertMarkData> insertMarks = new List<InsertMarkData>();
foreach (var correct in list)
{
if(Logger.LoggerForm != null)
if (LogHelper.LoggerForm != null)
{
Logger.Log(string.Format("correct content:{0}", correct.Insert));
LogHelper.Log(string.Format("correct content:{0}", correct.Insert));
}
int currentOffset = correct.SentenceOffset;
if (correct.CorrectItems != null && correct.CorrectItems.Count > 0)
@ -634,11 +707,11 @@ namespace AIProofread.Model
foreach (var item in correct.CorrectItems)
{
if (marks.ContainsKey(item.Id)) continue;
Logger.Log(string.Format("mark type {0} data {1}->{2}", item.Tag, item.Origin, item.Text));
// Logger.Log(string.Format("mark type {0} data {1}->{2}", item.Tag, item.Origin, item.Text));
int _prev = prevOffset;
bool isDisabled = false;
// 判断查找内容是否在原始数据中,否则直跳过
if(item.Tag != "i" && item.Origin.Trim().Length > 0)
if (item.Tag != "i" && item.Origin.Trim().Length > 0)
{
isDisabled = correct.Insert.IndexOf(item.Origin) == -1;
}
@ -671,7 +744,7 @@ namespace AIProofread.Model
}
catch (Exception e)
{
Logger.Log(string.Format("mark color error {0}", e.Message));
LogHelper.Log(string.Format("mark color error {0}", e.Message));
}
}
else
@ -684,7 +757,7 @@ namespace AIProofread.Model
{ "new_text",correct.NewText },
{ "paragraph_num",correct.ParagraphNumber },
};
Logger.Log(JsonConvert.SerializeObject(msg));
LogHelper.Log(JsonConvert.SerializeObject(msg));
}
}
}
@ -737,7 +810,7 @@ namespace AIProofread.Model
}
public void InitProofreadCache(List<CorrectContext> list)
public void InitProofreadCache(List<CorrectContext> list, Dictionary<int, ProofreadRangeInfo> itemInfoDic)
{
marks.Clear();
@ -749,6 +822,19 @@ namespace AIProofread.Model
if (mark != null)
{
var pi = new ProofreadItem(item, correct.Insert, mark, Id);
// 是否存在样式信息
if (itemInfoDic != null && itemInfoDic.ContainsKey(item.Id))
{
// 获取样式信息并还原
var info = itemInfoDic[item.Id];
try
{
pi.originColor = info.Color;
pi.originBackgroundColor = info.Background;
pi.originSize = info.Size;
}
catch (Exception ex) { LogHelper.Log(ex); }
}
marks.Add(item.Id, pi);
}
});
@ -827,6 +913,10 @@ namespace AIProofread.Model
// 采纳
marks[proofreadId].Process(status);
}
else
{
Logger.Debug("不存在此校对项");
}
}
internal bool Saved()
@ -851,9 +941,10 @@ namespace AIProofread.Model
try
{
CurrentDocument.Save();
}catch (Exception ex)
}
catch (Exception ex)
{
Logger.Log(ex);
LogHelper.Log(ex);
}
}
public void FocusToPanel()
@ -862,7 +953,7 @@ namespace AIProofread.Model
TaskPane.Control.Focus();
}
internal void Close()
public void Close()
{
try
{
@ -870,23 +961,24 @@ namespace AIProofread.Model
marks.Clear();
// 清除区域相关数据
ranges.Clear();
TaskPane.Dispose();
// TaskPane.Dispose();
this.Dispose();
}
catch (Exception ex)
{
Logger.Log(ex);
LogHelper.Log(ex);
}
}
public void ExportResult()
public void ExportResult(string modelType)
{
TaskPane.Control.BeginInvoke(new Action(() =>
{
DocumentUtil.ExportProofreadResult();
DocumentUtil.ExportProofreadResult(modelType);
}));
}
internal void ShowUpgrade(string data, bool force)
public void ShowUpgrade(string data, bool force)
{
TaskPane.Control.BeginInvoke(new Action(() =>
{
@ -896,6 +988,7 @@ namespace AIProofread.Model
if (force)
{
// 已经强制更新但被忽略过则不再提示
if (Config.UpgradeForcedNotice) return;
var result = MessageBox.Show(upgradeData.Message, "是否确认更新", System.Windows.Forms.MessageBoxButtons.YesNo, System.Windows.Forms.MessageBoxIcon.Question);
@ -963,5 +1056,31 @@ namespace AIProofread.Model
}
}));
}
public Dictionary<int, ProofreadRangeInfo> GetProofreadOriginData()
{
Dictionary<int, ProofreadRangeInfo> dic = new Dictionary<int, ProofreadRangeInfo>();
// 变量文档所有marks 记录mark对应range的背景、大小、颜色
foreach (var item in marks)
{
if (item.Value.mark != null)
{
// 添加到数据
dic.Add(item.Key, new ProofreadRangeInfo()
{
Background = item.Value.originBackgroundColor,
Color = item.Value.originColor,
Size = item.Value.originSize
});
}
}
return dic;
}
public void CheckPanel()
{
LogHelper.Log(CurrentDocument.FullName + $" TaskPane visible {PaneVisible} has " + (TaskPane == null ? "null" : "exists"));
if (TaskPane == null) CreateTaskPane();
}
}
}

View File

@ -1,9 +1,9 @@
using Microsoft.Office.Interop.Word;
using log4net;
using log4net.Repository.Hierarchy;
using Microsoft.Office.Interop.Word;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace AIProofread.Model
{
@ -12,6 +12,7 @@ namespace AIProofread.Model
/// </summary>
public class DocumentList
{
public ILog Logger = LogHelper.GetLogger(typeof(DocumentList));
public List<DocumentInfo> documentList = new List<DocumentInfo>();
public DocumentInfo ActiveDocument { get; set; }
public int Count => documentList.Count;
@ -23,7 +24,7 @@ namespace AIProofread.Model
public void Clear()
{
documentList.ForEach(doc =>{ doc.Dispose(); });
documentList.ForEach(doc => { doc.Dispose(); });
documentList.Clear();
}
@ -102,24 +103,22 @@ namespace AIProofread.Model
{
return documentList.IndexOf(item);
}
/// <summary>
/// 设置当前激活的文档
/// </summary>
/// <param name="originDocument"></param>
public DocumentInfo SetActiveDocument(Document originDocument)
{
Logger.Debug("SetActiveDocument(113): " + originDocument.Name);
if (originDocument == null) return null;
var document = Get(originDocument);
// 如果不存在,则添加
var document = InitDocument(originDocument);
if (document == null)
{
document = new DocumentInfo(originDocument);
Add(document);
Logger.Error("Document not exists SetActiveDocument");
return null;
}
if (ActiveDocument == document) return document;
else if (Globals.ThisAddIn.IsWPS)
if (ActiveDocument != null && ActiveDocument.CurrentDocument != originDocument)
{
// WPS 只有一个窗口 所以需要先关闭之前文档的面板
ActiveDocument?.Deactive();
@ -128,6 +127,7 @@ namespace AIProofread.Model
ActiveDocument = document;
//document.IsActive = true;
document.Active();
document.CheckBtnStatus();
return document;
}
@ -135,5 +135,25 @@ namespace AIProofread.Model
{
documentList.ForEach(d => d.HidePane());
}
public DocumentInfo InitDocument(Document originDocument)
{
var document = Get(originDocument);
try
{
// 如果不存在,则添加
if (document == null)
{
Logger.Debug("Document not exists,InitDocument: " + originDocument.Name);
document = new DocumentInfo(originDocument);
Add(document);
}
}catch(Exception ex)
{
Logger.Error("InitDocument error: " + ex.Message,ex);
}
return document;
}
}
}

View File

@ -1,5 +1,7 @@
using Microsoft.Office.Interop.Word;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Text;
using UtilLib;
@ -26,23 +28,71 @@ namespace AIProofread.Model
{
var sentence = item.OriginSentence;
var isInsert = item.content.Tag == "i";
if (sentence.Length <= MAX_WORD_LENGTH && !isInsert)
var limitLength = Math.Max(item.content.Origin.Length, MAX_WORD_LENGTH);
if (sentence.Length <= limitLength && !isInsert)
{
return sentence;
}
var range = item.mark.Range;
if (isInsert)
{
Debug.WriteLine("GetReadDocumentFilePath Start ==>", DateTime.Now.ToLongTimeString());
}
// 截取中间位置
if(sentence.Length > limitLength)
{
try
{
var middlePosition = limitLength / 2;
var cutStart = item.content.Start - middlePosition;
// 越界了
if (cutStart < 0)
{
cutStart = 0;
}
var originText = sentence.Substring(cutStart, Math.Min(sentence.Length - cutStart, limitLength));
if (!isInsert)
{
item.content.Start = item.content.Start - cutStart;
item.content.End = item.content.End - cutStart;
return originText;
}
}
catch (Exception ex)
{
LogHelper.Log(ex);
}
}
var sb = new StringBuilder();
if (sentence.Length <= limitLength && isInsert)
{
var before = item.content.Start == 0 ? string.Empty: sentence.Substring(0, item.content.Start);
var after = item.content.Start >= sentence.Length ? string.Empty : sentence.Substring(item.content.Start);
if (!string.IsNullOrEmpty(before))
{
sb.Append(before);
}
//
sb.Append(ToolUtil.GetBlankText(item.content.Text.Length, "˽"));
if (!string.IsNullOrEmpty(after))
{
sb.Append(after);
}
item.content.Start = item.content.Start;
item.content.End = item.content.Start + 1;
return sb.ToString().Trim();
}
var range = item.mark.Range;
// 获取range所在句子
//var first = range.Sentences.First.Start;
//var last = range.Sentences.Last.End;
var sentences = range.Sentences;
var sb = new StringBuilder();
foreach (Microsoft.Office.Interop.Word.Range s in sentences)
{
var str = s.Text;
if (isInsert && range.Start >= s.Start && range.End <= s.End)
{
sb.Append(str.Replace(" ", "˽"));
sb.Append(str.Replace(" ", "˽"));
}
else
{
@ -50,6 +100,7 @@ namespace AIProofread.Model
}
}
var first = sentences.First;
// 内容位置:用于后续标红
item.content.Start = range.Start - first.Start;
item.content.End = range.End - first.Start;
return sb.ToString().Trim();

View File

@ -0,0 +1,11 @@
using Microsoft.Office.Interop.Word;
namespace AIProofread.Model
{
public class ProofreadRangeInfo
{
public float Size { get; set; }
public WdColor Background { get; set; }
public WdColor Color { get; set; }
}
}

View File

@ -14,13 +14,13 @@ namespace UtilLib
public Bookmark mark;
public string OriginSentence { get; set; }
public CorrectItem content;
private float originSize;
private WdColor originColor;
private WdColor originBackgroundColor;
public float originSize;
public WdColor originColor;
public WdColor originBackgroundColor;
public string Name { get; set; }
public int DocumentId { get; set; }
public ProofreadItem(CorrectItem content,string originSentence,int documentId)
public ProofreadItem(CorrectItem content, string originSentence, int documentId)
{
this.content = content;
this.DocumentId = documentId;
@ -76,7 +76,7 @@ namespace UtilLib
private void OnMarkSelected(object sender, Microsoft.Office.Tools.Word.SelectionEventArgs e)
{
//throw new System.NotImplementedException();
Bridge.bridge.SelectMarkById(content.Id,DocumentId);
Bridge.bridge.SelectMarkById(content.Id, DocumentId);
}
public void Select()
@ -96,7 +96,7 @@ namespace UtilLib
}
catch (Exception e)
{
Logger.Log(e);
LogHelper.Log(e);
}
}
@ -113,7 +113,7 @@ namespace UtilLib
}
catch (Exception e)
{
Logger.Log(e);
LogHelper.Log(e);
}
}
@ -131,7 +131,34 @@ namespace UtilLib
}
catch (Exception e)
{
Logger.Log(e);
LogHelper.Log(e);
}
}
private void PrepareCommentProcess(Bookmark mark)
{
var doc = Globals.ThisAddIn.Application.ActiveDocument;
var fullRange = doc.Range();
var range = mark.Range;
var checkRange = doc.Range(
Math.Max(range.Start - 2, fullRange.Start),
Math.Min(range.End + 2, fullRange.End)
);
var comments = checkRange.Comments;
// 判断当前书签选区内容是否有评论
if (comments != null && comments.Count > 0)
{
LogHelper.Log("有批注");
foreach (Microsoft.Office.Interop.Word.Comment item in comments)
{
// 判断当前评论和书签选区是否一致
if (item.Scope.Start == range.Start && item.Scope.End == range.End)
{
LogHelper.Log("删除批注:" + item.Range.Text);
// 删除评论
item.Delete();
}
}
}
}
@ -148,6 +175,7 @@ namespace UtilLib
// 采纳
if (status == AcceptStatus.Accept)
{
PrepareCommentProcess(mark);
if (content.Tag == "r" || content.Tag == "i")
{
mark.Text = content.Text;
@ -194,12 +222,20 @@ namespace UtilLib
// 判断书签范围内是否有批注
if (rng.Text?.IndexOf("%") != -1 && rng.Comments != null && rng.Comments.Count > 0)
if (rng.Text?.IndexOf("%") != -1)
{
for (var i = 1; i < rng.Comments.Count; i++)
LogHelper.Log($"处理百分号问题:有批注");
if (rng.Comments != null && rng.Comments.Count > 0)
{
var comment = rng.Comments[i];
comment.Scope.Text = comment.Scope.Text.Replace("%", "");
for (var i = 1; i < rng.Comments.Count; i++)
{
var comment = rng.Comments[i];
comment.Scope.Text = comment.Scope.Text.Replace("%", "");
}
}
else
{
rng.Text = rng.Text.Replace("%", "");
}
}
}

View File

@ -7,11 +7,11 @@ using System.Security;
// 控制。更改这些特性值可修改
// 与程序集关联的信息。
[assembly: AssemblyTitle("AI校对王")]
[assembly: AssemblyDescription("AI校对王 2.1.0")]
[assembly: AssemblyDescription("AI校对王 2.2.6")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("果麦文化")]
[assembly: AssemblyProduct("AI校对王 2.1.0")]
[assembly: AssemblyCopyright("Copyright © GuoMai 2024")]
[assembly: AssemblyCompany("果麦文化传媒股份有限公司")]
[assembly: AssemblyProduct("AI校对王 2.2.6")]
[assembly: AssemblyCopyright("Copyright © 果麦文化传媒股份有限公司 2025")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
@ -33,6 +33,6 @@ using System.Security;
//可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值,
// 方法是按如下所示使用“*”: :
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("2.0")]
[assembly: AssemblyFileVersion("2.1.0.0")]
[assembly: AssemblyVersion("2.2.6.0")]
[assembly: AssemblyFileVersion("2.2.6.0")]

View File

@ -230,6 +230,26 @@ namespace AIProofread.Properties {
}
}
/// <summary>
/// 查找 System.Drawing.Bitmap 类型的本地化资源。
/// </summary>
internal static System.Drawing.Bitmap icon_manual {
get {
object obj = ResourceManager.GetObject("icon-manual", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// 查找 System.Drawing.Bitmap 类型的本地化资源。
/// </summary>
internal static System.Drawing.Bitmap icon_manual_wps {
get {
object obj = ResourceManager.GetObject("icon-manual-wps", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// 查找 System.Drawing.Bitmap 类型的本地化资源。
/// </summary>
@ -360,6 +380,26 @@ namespace AIProofread.Properties {
}
}
/// <summary>
/// 查找 System.Drawing.Bitmap 类型的本地化资源。
/// </summary>
internal static System.Drawing.Bitmap icon_update_new {
get {
object obj = ResourceManager.GetObject("icon-update-new", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// 查找 System.Drawing.Bitmap 类型的本地化资源。
/// </summary>
internal static System.Drawing.Bitmap icon_update_new_wps {
get {
object obj = ResourceManager.GetObject("icon-update-new-wps", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// 查找 System.Drawing.Bitmap 类型的本地化资源。
/// </summary>

View File

@ -157,6 +157,9 @@
<data name="icon-update-wps" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\icon-update-wps.jpg;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="icon-manual" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\icon-manual.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="icon-setting" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\icon-setting.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
@ -178,12 +181,18 @@
<data name="favicon" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\favicon.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="icon-ai-robot-wps" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\icon-ai-robot-wps.jpg;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="icon-refresh-wps" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\icon-refresh-wps.jpg;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="icon-clear" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\icon-clear.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="icon-manual-wps" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\icon-manual-wps.jpg;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="button_default" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\button_default.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
@ -196,6 +205,9 @@
<data name="logo_no_text" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\logo_no_text.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="logo_no_text_wps" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\logo_no_text_wps.jpg;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="logo_wps" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\logo_wps.jpg;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
@ -211,8 +223,8 @@
<data name="icon-panel" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\icon-panel.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="logo_no_text_wps" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\logo_no_text_wps.jpg;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
<data name="icon-ai-robot" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\icon-ai-robot.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="icon-logout" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\icon-logout.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
@ -223,10 +235,10 @@
<data name="icon-proofread" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\icon-proofread.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="icon-ai-robot" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\icon-ai-robot.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
<data name="icon-update-new" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\icon-update-new.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="icon-ai-robot-wps" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\icon-ai-robot-wps.jpg;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
<data name="icon-update-new-wps" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\icon-update-new-wps.jpg;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
</root>

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 843 B

View File

@ -41,7 +41,9 @@ namespace AIProofread
Microsoft.Office.Tools.Ribbon.RibbonDropDownItem ribbonDropDownItemImpl3 = this.Factory.CreateRibbonDropDownItem();
this.tabAIProofread = this.Factory.CreateRibbonTab();
this.group1 = this.Factory.CreateRibbonGroup();
this.BtnProofreadAll = this.Factory.CreateRibbonButton();
this.menuProofreadList = this.Factory.CreateRibbonMenu();
this.BtnProofreadExact = this.Factory.CreateRibbonButton();
this.BtnProofreadFull = this.Factory.CreateRibbonButton();
this.BtnExportProofreadResult = this.Factory.CreateRibbonButton();
this.btnClear = this.Factory.CreateRibbonButton();
this.btnOpenLexicon = this.Factory.CreateRibbonButton();
@ -62,15 +64,16 @@ namespace AIProofread
this.LblNickname = this.Factory.CreateRibbonLabel();
this.group2 = this.Factory.CreateRibbonGroup();
this.BtnShowPanel = this.Factory.CreateRibbonButton();
this.BtnShowManual = this.Factory.CreateRibbonButton();
this.grpDebug = this.Factory.CreateRibbonGroup();
this.btnShowPane = this.Factory.CreateRibbonButton();
this.btnHidePane = this.Factory.CreateRibbonButton();
this.BtnOpenLog = this.Factory.CreateRibbonButton();
this.button1 = this.Factory.CreateRibbonButton();
this.BtnOpenLogger = this.Factory.CreateRibbonButton();
this.BtnTest = this.Factory.CreateRibbonButton();
this.BtnOpenAppDir = this.Factory.CreateRibbonButton();
this.BtnShowVersion = this.Factory.CreateRibbonButton();
this.button2 = this.Factory.CreateRibbonButton();
this.dropDown1 = this.Factory.CreateRibbonDropDown();
this.tabAIProofread.SuspendLayout();
this.group1.SuspendLayout();
@ -93,7 +96,7 @@ namespace AIProofread
//
// group1
//
this.group1.Items.Add(this.BtnProofreadAll);
this.group1.Items.Add(this.menuProofreadList);
this.group1.Items.Add(this.BtnExportProofreadResult);
this.group1.Items.Add(this.btnClear);
this.group1.Items.Add(this.btnOpenLexicon);
@ -101,20 +104,35 @@ namespace AIProofread
this.group1.Items.Add(this.btnSetting);
this.group1.Name = "group1";
//
// BtnProofreadAll
// menuProofreadList
//
this.BtnProofreadAll.ControlSize = Microsoft.Office.Core.RibbonControlSize.RibbonControlSizeLarge;
this.BtnProofreadAll.Image = global::AIProofread.Properties.Resources.icon_proofread;
this.BtnProofreadAll.Label = "全文校对\r\n";
this.BtnProofreadAll.Name = "BtnProofreadAll";
this.BtnProofreadAll.ShowImage = true;
this.BtnProofreadAll.Click += new Microsoft.Office.Tools.Ribbon.RibbonControlEventHandler(this.BtnProofreadAll_Click);
this.menuProofreadList.ControlSize = Microsoft.Office.Core.RibbonControlSize.RibbonControlSizeLarge;
this.menuProofreadList.Image = global::AIProofread.Properties.Resources.icon_proofread;
this.menuProofreadList.Items.Add(this.BtnProofreadExact);
this.menuProofreadList.Items.Add(this.BtnProofreadFull);
this.menuProofreadList.Label = "全文校对\r\n";
this.menuProofreadList.Name = "menuProofreadList";
this.menuProofreadList.ShowImage = true;
//
// BtnProofreadExact
//
this.BtnProofreadExact.Label = "优先查准";
this.BtnProofreadExact.Name = "BtnProofreadExact";
this.BtnProofreadExact.ShowImage = true;
this.BtnProofreadExact.Click += new Microsoft.Office.Tools.Ribbon.RibbonControlEventHandler(this.BtnProofreadExact_Click);
//
// BtnProofreadFull
//
this.BtnProofreadFull.Label = "优先查全";
this.BtnProofreadFull.Name = "BtnProofreadFull";
this.BtnProofreadFull.ShowImage = true;
this.BtnProofreadFull.Click += new Microsoft.Office.Tools.Ribbon.RibbonControlEventHandler(this.BtnProofreadFull_Click);
//
// BtnExportProofreadResult
//
this.BtnExportProofreadResult.ControlSize = Microsoft.Office.Core.RibbonControlSize.RibbonControlSizeLarge;
this.BtnExportProofreadResult.Image = global::AIProofread.Properties.Resources.icon_export;
this.BtnExportProofreadResult.Label = "导出勘误表\r\n";
this.BtnExportProofreadResult.Label = "勘误表导出\r\n";
this.BtnExportProofreadResult.Name = "BtnExportProofreadResult";
this.BtnExportProofreadResult.ShowImage = true;
this.BtnExportProofreadResult.Click += new Microsoft.Office.Tools.Ribbon.RibbonControlEventHandler(this.BtnExportProofreadResult_Click);
@ -144,7 +162,7 @@ namespace AIProofread
this.menuSencenDect.Items.Add(this.btnDetectionAll);
this.menuSencenDect.Items.Add(this.btnDetectionParagraph);
this.menuSencenDect.Items.Add(this.btnDetectionHistory);
this.menuSencenDect.Label = "常识性检测\r\n";
this.menuSencenDect.Label = "常识性校对助手\r\n";
this.menuSencenDect.Name = "menuSencenDect";
this.menuSencenDect.ShowImage = true;
//
@ -237,7 +255,9 @@ namespace AIProofread
this.btnLogin.Image = global::AIProofread.Properties.Resources.icon_user;
this.btnLogin.Label = "用户登录\r\n";
this.btnLogin.Name = "btnLogin";
this.btnLogin.ScreenTip = "用户登录\r\n";
this.btnLogin.ShowImage = true;
this.btnLogin.SuperTip = "通过手机验证码或者密码登录账号";
this.btnLogin.Click += new Microsoft.Office.Tools.Ribbon.RibbonControlEventHandler(this.btnLogin_Click);
//
// btnLogout
@ -265,27 +285,38 @@ namespace AIProofread
// group2
//
this.group2.Items.Add(this.BtnShowPanel);
this.group2.Items.Add(this.BtnShowManual);
this.group2.Name = "group2";
//
// BtnShowPanel
//
this.BtnShowPanel.ControlSize = Microsoft.Office.Core.RibbonControlSize.RibbonControlSizeLarge;
this.BtnShowPanel.Enabled = false;
this.BtnShowPanel.Image = global::AIProofread.Properties.Resources.icon_panel;
this.BtnShowPanel.Label = "显示面板\r\n";
this.BtnShowPanel.Name = "BtnShowPanel";
this.BtnShowPanel.ShowImage = true;
this.BtnShowPanel.Click += new Microsoft.Office.Tools.Ribbon.RibbonControlEventHandler(this.BtnShowPanel_Click);
//
// BtnShowManual
//
this.BtnShowManual.ControlSize = Microsoft.Office.Core.RibbonControlSize.RibbonControlSizeLarge;
this.BtnShowManual.Image = global::AIProofread.Properties.Resources.icon_manual;
this.BtnShowManual.Label = "用户手册\r\n";
this.BtnShowManual.Name = "BtnShowManual";
this.BtnShowManual.ShowImage = true;
this.BtnShowManual.Click += new Microsoft.Office.Tools.Ribbon.RibbonControlEventHandler(this.BtnShowManual_Click);
//
// grpDebug
//
this.grpDebug.Items.Add(this.btnShowPane);
this.grpDebug.Items.Add(this.btnHidePane);
this.grpDebug.Items.Add(this.BtnOpenLog);
this.grpDebug.Items.Add(this.button1);
this.grpDebug.Items.Add(this.BtnOpenLogger);
this.grpDebug.Items.Add(this.BtnTest);
this.grpDebug.Items.Add(this.BtnOpenAppDir);
this.grpDebug.Items.Add(this.BtnShowVersion);
this.grpDebug.Items.Add(this.button2);
this.grpDebug.Items.Add(this.dropDown1);
this.grpDebug.Label = "开发调试";
this.grpDebug.Name = "grpDebug";
@ -309,12 +340,6 @@ namespace AIProofread
this.BtnOpenLog.Name = "BtnOpenLog";
this.BtnOpenLog.Click += new Microsoft.Office.Tools.Ribbon.RibbonControlEventHandler(this.BtnOpenLog_Click);
//
// button1
//
this.button1.Label = "更新测试版本";
this.button1.Name = "button1";
this.button1.Click += new Microsoft.Office.Tools.Ribbon.RibbonControlEventHandler(this.button1_Click);
//
// BtnOpenLogger
//
this.BtnOpenLogger.Label = "打开日志窗口";
@ -339,6 +364,12 @@ namespace AIProofread
this.BtnShowVersion.Name = "BtnShowVersion";
this.BtnShowVersion.Click += new Microsoft.Office.Tools.Ribbon.RibbonControlEventHandler(this.BtnShowVersion_Click);
//
// button2
//
this.button2.Label = "打开登录窗口";
this.button2.Name = "button2";
this.button2.Click += new Microsoft.Office.Tools.Ribbon.RibbonControlEventHandler(this.button2_Click);
//
// dropDown1
//
ribbonDropDownItemImpl1.Label = "开发";
@ -380,7 +411,6 @@ namespace AIProofread
internal Microsoft.Office.Tools.Ribbon.RibbonLabel LblNickname;
internal Microsoft.Office.Tools.Ribbon.RibbonLabel LblDate;
internal Microsoft.Office.Tools.Ribbon.RibbonButton btnLogin;
internal Microsoft.Office.Tools.Ribbon.RibbonButton BtnProofreadAll;
internal Microsoft.Office.Tools.Ribbon.RibbonButton btnClear;
internal Microsoft.Office.Tools.Ribbon.RibbonButton btnOpenLexicon;
internal Microsoft.Office.Tools.Ribbon.RibbonButton btnSetting;
@ -390,7 +420,6 @@ namespace AIProofread
internal Microsoft.Office.Tools.Ribbon.RibbonButton btnShowPane;
internal Microsoft.Office.Tools.Ribbon.RibbonButton btnHidePane;
internal Microsoft.Office.Tools.Ribbon.RibbonButton BtnOpenLog;
internal Microsoft.Office.Tools.Ribbon.RibbonButton button1;
internal Microsoft.Office.Tools.Ribbon.RibbonGroup Group;
internal Microsoft.Office.Tools.Ribbon.RibbonButton ButtonSaveCache;
internal Microsoft.Office.Tools.Ribbon.RibbonButton ButtonLoadCache;
@ -407,6 +436,11 @@ namespace AIProofread
internal Microsoft.Office.Tools.Ribbon.RibbonButton btnDetectionAll;
internal Microsoft.Office.Tools.Ribbon.RibbonButton btnDetectionParagraph;
internal Microsoft.Office.Tools.Ribbon.RibbonButton btnDetectionHistory;
internal Microsoft.Office.Tools.Ribbon.RibbonButton BtnShowManual;
internal Microsoft.Office.Tools.Ribbon.RibbonMenu menuProofreadList;
internal Microsoft.Office.Tools.Ribbon.RibbonButton BtnProofreadExact;
internal Microsoft.Office.Tools.Ribbon.RibbonButton BtnProofreadFull;
internal Microsoft.Office.Tools.Ribbon.RibbonButton button2;
}
partial class ThisRibbonCollection

View File

@ -11,38 +11,49 @@ using System.Text;
using AIProofread.core;
using System.Windows.Forms;
using AIProofread.Properties;
using System.Security.Policy;
namespace AIProofread
{
public partial class Ribbon1
{
private bool IS_LOGIN = false;
private static bool IS_WPS = false;
private Userinfo currentLoginUserinfo;
private void Ribbon1_Load(object sender, RibbonUIEventArgs e)
{
//btnLogin.Label = "用户\n登录";
//btnLogout.Label = "退出\n登录";
Globals.ThisAddIn.ribbon = this;
ShowDebug();
InitModule();
}
/// <summary>
/// 用于调试或测试
/// </summary>
public void ShowDebug()
public void InitModule()
{
if (Config.RUN_IN_DEBUG)
{
grpDebug.Visible = true;
}
menuProofreadList.Visible = AppModule.ENABLE_PROOFREAD;
BtnExportProofreadResult.Visible = AppModule.ENABLE_EXPORT_PROOFREAD_RESULT;
btnOpenLexicon.Visible = AppModule.ENABLE_LEXICON_MANAGE;
menuSencenDect.Visible = AppModule.ENABLE_COMMONSENSE_CHECK;
btnSetting.Visible = AppModule.ENABLE_SETTING;
ButtonSaveCache.Visible = AppModule.ENABLE_SAVE_CACHE;
ButtonLoadCache.Visible = AppModule.ENABLE_LOAD_CACHE;
BtnGetContact.Visible = AppModule.ENABLE_CUSTOMER_SERVICE;
BtnUpdate.Visible = AppModule.ENABLE_UPGRADE;
BtnShowManual.Visible = AppModule.ENABLE_HELP;
// 调试面板
grpDebug.Visible = Config.RUN_IN_DEBUG;
}
public void SetCommonBtnStatus(bool status)
{
BtnProofreadAll.Enabled = status;
// BtnProofreadAll.Enabled = status;
menuProofreadList.Enabled = status;
btnClear.Enabled = status;
btnOpenLexicon.Enabled = status;
btnSetting.Enabled = status;
@ -68,6 +79,7 @@ namespace AIProofread
else if (key == "disable-by-upgrade")
{
SetCommonBtnStatus(status);
BtnUpdate.Enabled = true;
BtnShowPanel.Enabled = status;
}
}
@ -77,9 +89,7 @@ namespace AIProofread
/// </summary>
public void InitWPS()
{
IS_WPS = true;
BtnProofreadAll.Image = AIProofread.Properties.Resources.icon_proofread_wps;
menuProofreadList.Image = AIProofread.Properties.Resources.icon_proofread_wps;
btnClear.Image = AIProofread.Properties.Resources.icon_clear_wps;
btnOpenLexicon.Image = AIProofread.Properties.Resources.icon_book_wps;
btnSetting.Image = AIProofread.Properties.Resources.icon_setting_wps;
@ -95,6 +105,7 @@ namespace AIProofread
BtnShowPanel.Image = AIProofread.Properties.Resources.icon_panel_wps;
// 导出校对结果
BtnExportProofreadResult.Image = AIProofread.Properties.Resources.icon_export_wps;
BtnShowManual.Image = AIProofread.Properties.Resources.icon_manual_wps;
}
public void ProcessLoginInfo(Userinfo userinfo)
@ -120,7 +131,7 @@ namespace AIProofread
}
catch (Exception ex)
{
Logger.Log(this.Name, ex);
LogHelper.Log(this.Name, ex);
}
}
Globals.ThisAddIn.LoginFormList.Clear();
@ -131,6 +142,7 @@ namespace AIProofread
/// </summary>
public void ProcessLogout()
{
Globals.ThisAddIn.CloseReadmeIfShown();
IS_LOGIN = false;
currentLoginUserinfo = null;
ToggleLogin();
@ -151,12 +163,14 @@ namespace AIProofread
// 弹出登录窗口
private void btnLogin_Click(object sender, RibbonControlEventArgs e)
{
Globals.ThisAddIn.CloseReadmeIfShown();
Bridge.bridge.ShowLoginForm(null);
}
// 注销登录
private void btnLogout_Click(object sender, RibbonControlEventArgs e)
{
Globals.ThisAddIn.CloseReadmeIfShown();
Globals.ThisAddIn.ActiveDocument.ShowDialog(currentLoginUserinfo.phone + " 退出AI校对王", "确定", "logout");
//Globals.ThisAddIn.ShowDialog("退出AI校对王",)
@ -167,37 +181,47 @@ namespace AIProofread
//Globals.ThisAddIn.SendMessageToWeb("confirm-logout", null);
}
public void ShowNewVersionIcon()
{
Globals.ThisAddIn.CloseReadmeIfShown();
BtnUpdate.Image = Globals.ThisAddIn.IsWPS? Resources.icon_update_new_wps : Resources.icon_update_new;
}
private void btnOpenLexicon_Click(object sender, RibbonControlEventArgs e)
{
Globals.ThisAddIn.CloseReadmeIfShown();
Globals.ThisAddIn.SendMessageToWeb("show-lexicon", null);
//(new FormLexicon()).Show();
}
private void btnSetting_Click(object sender, RibbonControlEventArgs e)
{
Globals.ThisAddIn.CloseReadmeIfShown();
Globals.ThisAddIn.SendMessageToWeb("show-setting", null);
}
private void BtnGetContact_Click(object sender, RibbonControlEventArgs e)
{
(new FormContact()).ShowDialog();
Globals.ThisAddIn.CloseReadmeIfShown();
var frm = new FormContact();
Globals.ThisAddIn.ActiveDocument.RunInMainThread(() =>
{
frm.ShowDialog();
});
}
private void BtnUpdate_Click(object sender, RibbonControlEventArgs e)
{
Globals.ThisAddIn.CloseReadmeIfShown();
//System.Windows.Forms.MessageBox.Show("当前插件是最新版本");
//Globals.ThisAddIn.SendMessageToWeb("upgrade", Config.APP_VERSION);
Bridge.bridge.ShowUpgradeView();
}
private void BtnProofreadAll_Click(object sender, RibbonControlEventArgs e)
{
string time = DateTime.Now.ToString("yyyy - MM - dd HH: mm:ss: fff:ffffff");
Globals.ThisAddIn.SendMessageToWeb("start", time);
}
private void btnClear_Click(object sender, RibbonControlEventArgs e)
{
Globals.ThisAddIn.CloseReadmeIfShown();
//DocumentUtil.ClearProofreadMarks();
Globals.ThisAddIn.ActiveDocument.ShowDialog("请确认是否清除此文档的所有校对标注?", "确定", "clear-tips");
@ -210,11 +234,13 @@ namespace AIProofread
private void btnShowPane_Click(object sender, RibbonControlEventArgs e)
{
Globals.ThisAddIn.CloseReadmeIfShown();
Globals.ThisAddIn.ShowPanel();
}
private void btnHidePane_Click(object sender, RibbonControlEventArgs e)
{
Globals.ThisAddIn.CloseReadmeIfShown();
Globals.ThisAddIn.HidePanel();
}
@ -450,7 +476,7 @@ namespace AIProofread
}
catch (Exception exception)
{
Logger.Log(exception);
LogHelper.Log(exception);
}
return result;
}
@ -474,12 +500,12 @@ namespace AIProofread
private void BtnOpenLogger_Click(object sender, RibbonControlEventArgs e)
{
// 判断日志窗口是否已经存在或者打开
if (Logger.LoggerForm == null || Logger.LoggerForm.IsDisposed)
if (LogHelper.LoggerForm == null || LogHelper.LoggerForm.IsDisposed)
{
// 创建日志窗口
Logger.LoggerForm = new FormLogger();
LogHelper.LoggerForm = new FormLogger();
}
Logger.LoggerForm.Show();
LogHelper.LoggerForm.Show();
}
private int GetRangeParagraphNumber(Range range)
@ -538,16 +564,19 @@ namespace AIProofread
private void ButtonLoadCache_Click(object sender, RibbonControlEventArgs e)
{
Globals.ThisAddIn.CloseReadmeIfShown();
Globals.ThisAddIn.ShowDialog("即将加载最近保存的进度,新的修改可能会丢失!", "确定", "load-cache");
}
private void BtnShowPanel_Click(object sender, RibbonControlEventArgs e)
{
Globals.ThisAddIn.CloseReadmeIfShown();
Globals.ThisAddIn.SendMessageToWeb("show-panel", "");
}
private void BtnOpenAppDir_Click(object sender, RibbonControlEventArgs e)
{
Globals.ThisAddIn.CloseReadmeIfShown();
// 打开日志目录
Process.Start(AppDomain.CurrentDomain.BaseDirectory);
}
@ -556,11 +585,13 @@ namespace AIProofread
private void BtnExportProofreadResult_Click(object sender, RibbonControlEventArgs e)
{
Globals.ThisAddIn.CloseReadmeIfShown();
Globals.ThisAddIn.SendMessageToWeb("export-result", "");
}
private void BtnShowVersion_Click(object sender, RibbonControlEventArgs e)
{
Globals.ThisAddIn.CloseReadmeIfShown();
Globals.ThisAddIn.SendMessageToWeb("show-version", "");
}
@ -568,11 +599,13 @@ namespace AIProofread
private void btnDetectionAll_Click(object sender, RibbonControlEventArgs e)
{
Globals.ThisAddIn.CloseReadmeIfShown();
Globals.ThisAddIn.SendMessageToWeb("show-check-all", "");
}
private void btnDetectionParagraph_Click(object sender, RibbonControlEventArgs e)
{
Globals.ThisAddIn.CloseReadmeIfShown();
// 获取当前选中的选区的首尾段落起始与结束位置
var start = currectSelectRange.Start; // .Paragraphs.First.Range
var end = currectSelectRange.End; // .Paragraphs.Last.Range
@ -583,6 +616,7 @@ namespace AIProofread
private void btnDetectionHistory_Click(object sender, RibbonControlEventArgs e)
{
Globals.ThisAddIn.CloseReadmeIfShown();
Globals.ThisAddIn.SendMessageToWeb("show-check-history", "");
}
@ -607,5 +641,37 @@ namespace AIProofread
btnDetectionAll.Enabled = allStatus;
btnDetectionParagraph.Enabled = rangeStatus;
}
private void BtnShowManual_Click(object sender, RibbonControlEventArgs e)
{
Globals.ThisAddIn.CloseReadmeIfShown();
try
{
Process.Start(Config.USER_MANUAL_URL);
}catch (Exception) {
Globals.ThisAddIn.ActiveDocument.ShowMessage("打开用户手册失败", 2000, false);
}
}
private void BtnProofreadExact_Click(object sender, RibbonControlEventArgs e)
{
Globals.ThisAddIn.CloseReadmeIfShown();
//
Globals.ThisAddIn.ActiveDocument.CheckPanel();
Globals.ThisAddIn.SendMessageToWeb("start", "exact");
}
private void BtnProofreadFull_Click(object sender, RibbonControlEventArgs e)
{
Globals.ThisAddIn.CloseReadmeIfShown();
Globals.ThisAddIn.ActiveDocument.CheckPanel();
Globals.ThisAddIn.SendMessageToWeb("start", "full");
}
private void button2_Click(object sender, RibbonControlEventArgs e)
{
Globals.ThisAddIn.CloseReadmeIfShown();
Bridge.bridge.ShowLoginForm(null);
}
}
}

View File

@ -117,7 +117,22 @@
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<metadata name="BtnProofreadAll.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<metadata name="tabAIProofread.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="group1.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="menuProofreadList.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="BtnProofreadExact.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="BtnProofreadFull.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="BtnExportProofreadResult.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="btnClear.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
@ -126,13 +141,91 @@
<metadata name="btnOpenLexicon.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="menuSencenDect.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="btnDetectionAll.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="btnDetectionParagraph.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="btnDetectionHistory.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="btnSetting.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="Group.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="ButtonSaveCache.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="ButtonLoadCache.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="grpOther.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="BtnGetContact.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="BtnUpdate.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="btnLogin.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="btnLogout.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="LblDate.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="LblNickname.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="group2.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="BtnShowPanel.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="BtnShowManual.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="grpDebug.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="btnShowPane.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="btnHidePane.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="BtnOpenLog.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="BtnOpenLogger.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="BtnTest.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="BtnOpenAppDir.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="BtnShowVersion.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="button2.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="dropDown1.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="$this.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
</root>

View File

@ -8,18 +8,16 @@ using AIProofread.Controls;
using UtilLib;
using AIProofread.Model;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Threading.Tasks;
//using CustomTaskPane = Microsoft.Office.Core.CustomTaskPane;
//using CustomTaskPane = Microsoft.Office.Tools.CustomTaskPane;
//using NPOI.SS.Formula.Functions;
using log4net;
namespace AIProofread
{
public partial class ThisAddIn
{
// LogManager.GetLogger(typeof(ThisAddIn))
public ILog Logger = LogHelper.GetLogger(typeof(ThisAddIn));
public static SynchronizationContext FmainThreadContext;
public string AddinName = " ";
@ -36,6 +34,7 @@ namespace AIProofread
/// 校对面板
/// </summary>
public ProofreadMainControl proofreadPanel;
private bool alreadyShowReadme = false;
/// <summary>
/// 工具栏
/// </summary>
@ -57,11 +56,20 @@ namespace AIProofread
/// <summary>
/// 当前文档信息
/// </summary>
public DocumentInfo ActiveDocument { get; set; }
public DocumentInfo ActiveDocument
{
get
{
return documentList.SetActiveDocument(Application.ActiveDocument);
}
}
/// <summary>
/// 智能常识检测对话框 = new FormCommonsenseDetection()
/// </summary>
public FormCommonsenseDetection formCommonsenseDetection;
/// <summary>
/// 是否为wps
/// </summary>
public bool IsWPS { get; set; }
public List<FormLogin> LoginFormList = new List<FormLogin>();
@ -92,25 +100,26 @@ namespace AIProofread
formCommonsenseDetection = null;
}
private void ProcessApplicationException(object sender,UnhandledExceptionEventArgs e)
private void ProcessApplicationException(object sender, UnhandledExceptionEventArgs e)
{
Logger.Log("UnhandledException",e.ExceptionObject as Exception);
Logger.Error("UnhandledException", e.ExceptionObject as Exception);
}
private void ProcessApplicationFormException(object sender, System.Threading.ThreadExceptionEventArgs e)
{
Logger.Log("ProcessApplicationFormException", e.Exception);
Logger.Error("ProcessApplicationFormException", e.Exception);
}
private void ThisAddIn_Startup(object sender, System.EventArgs e)
{
try
{
InitDeviceId();
AppInitialize();
//formCommonsenseDetection.ShowInTaskbar = false;
//formCommonsenseDetection.Show();
Logger.Log("ThisAddIn_Startup IS_WPS --> " + IsWPS);
Logger.Debug("ThisAddIn_Startup Platform --> " + (IsWPS ? "WPS" : "WORD"));
// 捕获全局异常
AppDomain.CurrentDomain.UnhandledException += ProcessApplicationException;
System.Windows.Forms.Application.ThreadException += ProcessApplicationFormException;
@ -121,7 +130,7 @@ namespace AIProofread
Application.WindowActivate += Application_WindowActivate;
//Application.WindowDeactivate += Application_WindowDeactivate;
Application.DocumentBeforeSave += Application_DocumentBeforeSave; ;
Application.DocumentBeforeSave += Application_DocumentBeforeSave;
(Application as ApplicationEvents4_Event).NewDocument += Application_NewDocument;
Application.DocumentChange += Application_DocumentChange;
@ -130,46 +139,127 @@ namespace AIProofread
//CheckPluginUpgradeInfo();
// CheckDocumentClosedTick();
// 定时检测文档是否关闭
_timer = new System.Timers.Timer(10000);
_timer.Elapsed += CheckDocumentClosed;
_timer.AutoReset = true;
_timer.Enabled = true;
//_timer = new System.Timers.Timer(10000);
//_timer.Elapsed += CheckDocumentClosed;
//_timer.AutoReset = true;
//_timer.Enabled = true;
try
{
// 默认已经打开了文档 直接初始化
if (Application.Documents.Count > 0 && Application.ActiveDocument != null)
{
Logger.Debug("ThisAddIn_Startup 开始初始化当前文档");
documentList.InitDocument(Application.ActiveDocument);
// 直接初始化面板
// info.CheckPanel();
Logger.Debug("ThisAddIn_Startup 结束初始化当前文档");
}
}
catch (Exception ex)
{
Logger.Error("Initialize documentlist Error ", ex);
}
}
catch (Exception ex1)
{
Logger.Log("Startup", ex1.ToString());
Logger.Error("Startup Error", ex1);
}
}
private void Application_DocumentBeforePrint(Document Doc, ref bool Cancel)
{
throw new NotImplementedException();
}
// 异步获取设备唯一标识
public void InitDeviceId()
{
System.Threading.Tasks.Task.Run(() =>
{
try
{
var deviceId = Tools.GetDeviceId();
if (string.IsNullOrEmpty(deviceId))
{
deviceId = Tools.GetDeviceId();
}
if (!string.IsNullOrEmpty(deviceId))
{
Config.DeviceId = deviceId;
Logger.Info("设备唯一标识:" + deviceId);
}
}
catch (Exception ex)
{
Logger.Error("InitDeviceId Error:", ex);
}
});
}
public void CheckDocumentClosed(object sender, System.Timers.ElapsedEventArgs e)
{
var existsList = new List<string>();
//Logger.Log("检测文档是否关闭 ...");
var existsList = new List<Document>();
try
{
if (documentList.Count == 0 || CurrentWordApplication.Documents.Count == documentList.Count) return;
var docList = CurrentWordApplication.Documents;
if (documentList.Count == 0 || docList.Count == existsList.Count) return;
existsList.Clear();
foreach (Document item in CurrentWordApplication.Documents)
foreach (Document item in docList)
{
existsList.Add(item.FullName);
existsList.Add(item);
}
// 检测文档是否关闭
foreach (var item in documentList.documentList)
for (int i = documentList.documentList.Count - 1; i >= 0; i--)
{
if (!existsList.Contains(item.fileName))
var item = documentList.documentList[i];
// 判断文档对象是否已经被移除
if (item.CurrentDocument == null)
{
Logger.Log("检测到文档关闭,已移除:" + item.fileName);
documentList.Remove(item);
continue;
}
// 可能出现另存问题 所以需要更新文件名称
//var oldName = item.fileName;
//var currentName = item.CurrentDocument.FullName;
//if (oldName != currentName)
//{
// item.fileName = currentName;
//}
if (!existsList.Contains(item.CurrentDocument))
{
Logger.Debug("检测到文档关闭,已移除:" + item.fileName);
try
{
item.RunInMainThread(() =>
{
item.Dispose();
}, true);
}
catch (Exception ex1)
{
Logger.Error("移除已关闭文档->释放面板", ex1);
}
try
{
documentList.Remove(item);
}
catch (Exception ex2)
{
Logger.Error("移除已关闭文档", ex2);
}
}
}
}
catch (Exception ex)
{
Logger.Log(ex);
Logger.Error("检测已关闭文档", ex);
}
//await System.Threading.Tasks.Task.Run(() =>
// {
@ -194,21 +284,21 @@ namespace AIProofread
}
catch (Exception ex)
{
Logger.Log("检测升级信息异常: " + ex.ToString());
Logger.Error("检测升级信息异常: ", ex);
}
});
}
private void Application_DocumentBeforeSave(Document originDocument, ref bool SaveAsUI, ref bool Cancel)
{
Logger.Log("DocumentSave", originDocument.Name + "\r\n");
//LogHelper.Log("DocumentSave", originDocument.Name + "\r\n");
if (CurrentWordApplication.Documents.Count == 0)
{
return;
}
if (ActiveDocument == null) return;
// TODO 完成缓存保存
//if (ActiveDocument == null) return;
//// TODO 完成缓存保存
}
@ -224,30 +314,31 @@ namespace AIProofread
// 启动地址
applicationStartupPath = System.Windows.Forms.Application.StartupPath;
Logger.Debug("applicationStartupPath --> " + applicationStartupPath);
// 判断是否是WPS
if (applicationStartupPath.Contains("WPS"))
{
Config.IS_WPS = true;
IsWPS = true;
try
{
Globals.Ribbons.Ribbon1.InitWPS();
}
catch (Exception ex)
{
Logger.Log("Init WPS Error " + ex.Message);
Logger.Error("Init WPS Error ", ex);
}
}
string verTextFile = Config.APP_BASE_DIR + Path.GetFileName("app_version.txt");
try
{
File.WriteAllText(verTextFile, Config.APP_VERSION);
}
catch (Exception ex)
{
Logger.Log("Write App Version Error " + ex.Message);
}
//string verTextFile = Config.APP_BASE_DIR + Path.GetFileName("app_version.txt");
//try
//{
// File.WriteAllText(verTextFile, Config.APP_VERSION);
//}
//catch (Exception ex)
//{
// Logger.Error("Write App Version Error ", ex);
//}
Logger.Info("init " + (Config.IS_WPS ? "WPS" : "WORD") + " end");
}
private void InitAppByConfig()
@ -257,7 +348,7 @@ namespace AIProofread
if (File.Exists(Config.CONFIG_FILE))
{
string content = File.ReadAllText(Config.CONFIG_FILE);
Logger.Log("INIT", "Found app.json " + content);
//LogHelper.Log("INIT", "Found app.json " + content);
if (content == null || content.Length == 0) return;
AppConfig config = JsonConvert.DeserializeObject<AppConfig>(content);
@ -274,10 +365,10 @@ namespace AIProofread
);
}
Config.RUN_IN_DEBUG = config.AppRunInDebug;
if (Config.APP_ENV != AppEnvironment.Prod && this.ribbon != null)
{
this.ribbon.ShowDebug();
}
//if (Config.APP_ENV != AppEnvironment.Prod && this.ribbon != null)
//{
// this.ribbon.Ini();
//}
}
}
catch (Exception) { }
@ -285,22 +376,29 @@ namespace AIProofread
private void Application_DocumentChange()
{
ShowVersionReadme();
// 检测是否存在打开的文档
if (CurrentWordApplication.Documents.Count == 0)
{
return;
}
//var document = CurrentWordApplication.ActiveDocument;
// 设置当前文档
ActiveDocument = documentList.SetActiveDocument(CurrentWordApplication.ActiveDocument);
ActiveDocument.CheckBtnStatus();
Logger.Log("Application_DocumentChange -- " + ActiveDocument.fileName);
var currentDocument = CurrentWordApplication.ActiveDocument;
Logger.Debug("DocumentChange => " + currentDocument.Name);
CheckDocumentClosed(null, null);
if (formCommonsenseDetection != null)
{
formCommonsenseDetection.SendMessageToWeb("document-change", null);
}
if (InDocumentInList(currentDocument))
{
documentList.InitDocument(currentDocument);
}
//var document = documentList.InitDocument(CurrentWordApplication.ActiveDocument);
//if (document == null) return;
}
public void SetActiveDocument(Document doc)
{
ActiveDocument = documentList.SetActiveDocument(doc);
}
private void Application_WindowDeactivate(Document doc, Window Wn)
{
@ -312,6 +410,24 @@ namespace AIProofread
//}
}
/// <summary>
/// 判断当前文档是否在列表中
/// </summary>
/// <param name="doc"></param>
/// <returns></returns>
private bool InDocumentInList(Document doc)
{
if (doc == null) return false;
foreach (Document item in Application.Documents)
{
if (item == doc)
{
return true;
}
}
return false;
}
/// <summary>
/// 激活文档
/// </summary>
@ -319,8 +435,20 @@ namespace AIProofread
/// <param name="Wn"></param>
private void Application_WindowActivate(Document activeDoc, Window Wn)
{
ActiveDocument = documentList.SetActiveDocument(activeDoc);
Logger.Log("Application_WindowActivate -- " + ActiveDocument.fileName);
ShowVersionReadme();
Logger.Debug("WindowActivate -- " + activeDoc.Name);
if (activeDoc != null && InDocumentInList(activeDoc))
{
Logger.Debug("DocumentChange -- " + activeDoc.Name
+ " 修订模式: is " + activeDoc.TrackRevisions
+ ActiveDocument?.CurrentDocument?.Name + "==》" + activeDoc.Name);
documentList.SetActiveDocument(activeDoc);
//// 设置当前文档
//ActiveDocument = document;
}
//// 当前文档添加书签集合
//if (!allMarks.ContainsKey(activeDoc))
//{
@ -352,13 +480,12 @@ namespace AIProofread
/// <param name="Cancel"></param>
private void Application_DocumentBeforeClose(Document currentDoc, ref bool Cancel)
{
Logger.Log("DocumentBeforeClose", currentDoc.FullName);
//if (allMarks.ContainsKey(currentDoc))
//{
// allMarks.Remove(currentDoc);
//}
//DisposePanel(currentDoc);
Logger.Debug("will close " + currentDoc.Name);
var doc = documentList.Get(currentDoc);
if (Config.IS_WPS && doc != null)
{
doc.HidePane();
}
}
//public void ActiveCurrentDocumentMarks(Document document)
@ -374,12 +501,41 @@ namespace AIProofread
private void Application_NewDocument(Document doc)
{
Logger.Log("NewDocument", doc.Name);
//LogHelper.Log("NewDocument" + doc.Name);
}
private void ShowVersionReadme()
{
if (alreadyShowReadme || File.Exists(Config.GetCurrentVersionReadmeCacheFile()))
{
return;
}
alreadyShowReadme = true;
FormReadme.GetInstance().Show();
//ActiveDocument?.RunInMainThread(() =>
//{
//});
}
/// <summary>
/// 如果Readme显示 则关闭
/// </summary>
public void CloseReadmeIfShown()
{
try
{
FormReadme.GetInstance(false).CloseAndDispose();
}
catch (Exception ex)
{
Logger.Error("CloseReadme Error", ex);
}
}
private void Application_DocumentOpen(Document doc)
{
Logger.Log("DocumentOpen", doc.Name);
//LogHelper.Log("DocumentOpen " + doc.Name);
ShowVersionReadme();
}
@ -393,46 +549,71 @@ namespace AIProofread
FmainThreadContext.Send(d, null);
}
//private void ProofreadPanel_SizeChanged(object sender, EventArgs e)
//{
// // 处理最小宽度
// if (customTaskPane != null && customTaskPane.Width < MinWidth && customTaskPane.Visible)
// {
// SendKeys.Send("{ESC}");
// customTaskPane.Width = MinWidth;
// }
//}
private void Application_WindowSelectionChange(Selection s)
{
// 处理当前文档选区,用于判断是否显示常识性检测
ribbon.ParseSelectionChange(s);
if (ActiveDocument == null || !s.Active) return;
// 当前选区是否存在书签
if (s.Range.Start != s.Range.End || s.Bookmarks.Count == 0) return;
var bookmarks = s.Bookmarks;
// 获取当前选区书签的起始位置
var currentPosition = s.Range.Start;
if (s.Bookmarks != null)
// Logger.Info("当前选区书签数量: " + s.Bookmarks.Count);
// 遍历书签 找到所需的书签
foreach (Bookmark item in s.Bookmarks)
{
if (s.Range.Start == s.Range.End) // 说明是点击呀
// 判断书签的选区不包含当前选中区域
if (currentPosition < item.Range.Start || currentPosition > item.Range.End)
{
//var count = s.Bookmarks.Count;
if (s.Bookmarks.Count >= 1) // 只有这一个
{
foreach (Bookmark item in s.Bookmarks)
{
int proofreadId = Config.GetBookmarkIdByName(item.Name);
if (proofreadId > 0)
{
// 只选择第一个书签
// TODO: 优化
//Bridge.bridge.SelectMarkById(proofreadId, 0);
ActiveDocument?.SelectMarkById(proofreadId, true);
return;
}
}
}
ReleaseComObject(item);
continue;
}
Logger.Debug("当前选区书签名称: " + item.Name + "范围:" + item.Range.Start + "," + item.Range.End);
//Logger.Debug("当前选区书签内容: " + item.Range.Text);
// 获取书签id
int proofreadId = Config.GetBookmarkIdByName(item.Name);
// 释放com对象
ReleaseComObject(item);
Logger.Debug("当前选区proofreadId: " + proofreadId);
if (proofreadId > 0)
{
//var targetRange = item.Range;
//// 选中
//targetRange.Select();
//Globals.ThisAddIn.Application.ActiveWindow.ScrollIntoView(targetRange);
// 只选择第一个书签
ActiveDocument?.SelectMarkById(proofreadId, true);
ReleaseComObject(bookmarks);
return;
}
//
}
ReleaseComObject(bookmarks);
//Bridge.bridge.SelectMarkById(-1, 0);
}
public int MyProperty { get; set; }
// 释放COM对象
private void ReleaseComObject(object obj)
{
if (obj != null)
{
try
{
System.Runtime.InteropServices.Marshal.ReleaseComObject(obj);
}
catch (Exception ex)
{
Logger.Error("ReleaseComObject Error", ex);
}
finally
{
obj = null;
}
}
}
public void SendMessageToWeb(string msg, object data)
{
@ -442,16 +623,22 @@ namespace AIProofread
ActiveDocument?.SendMessageToWeb(msg, data);
}
public void GlobalCallback(string callbackId, string result)
{
documentList.SetActiveDocument(Application.ActiveDocument)?.GlobalCallback(callbackId, result);
}
// 显示面板
public void ShowPanel()
{
ActiveDocument?.ShowPane();
documentList.SetActiveDocument(Application.ActiveDocument)?.ShowPane();
}
// 隐藏面板
public void HidePanel()
{
ActiveDocument?.HidePane();
documentList.SetActiveDocument(Application.ActiveDocument)?.HidePane();
}
/// <summary>
@ -498,14 +685,12 @@ namespace AIProofread
private void ThisAddIn_Shutdown(object sender, System.EventArgs e)
{
// PanelModule.DisposeCTP();
//this.proofreadPanel.Dispose();
// 取消捕获全局异常事件
AppDomain.CurrentDomain.UnhandledException -= ProcessApplicationException;
System.Windows.Forms.Application.ThreadException -= ProcessApplicationFormException;
Logger.Log("shutdown");
Logger.Debug("shutdown");
documentList.Clear();
if(_timer != null)
if (_timer != null)
{
_timer.Stop();
}
@ -537,7 +722,7 @@ namespace AIProofread
public DocumentInfo GetDocumentById(int id)
{
return documentList.GetById(id);
return id <= 0 ? ActiveDocument : documentList.GetById(id);
}
@ -560,8 +745,8 @@ namespace AIProofread
}
//public string LoadCacheByPath()
//{
//public string LoadCacheByPath()
//{
//}
@ -577,15 +762,15 @@ namespace AIProofread
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InternalStartup()
private void InternalStartup()
{
this.Startup += new System.EventHandler(ThisAddIn_Startup);
this.Shutdown += new System.EventHandler(ThisAddIn_Shutdown);
}
public void InitProofreadCacheList(System.Collections.Generic.List<CorrectContext> list)
public void InitProofreadCacheList(List<CorrectContext> list, Dictionary<int, ProofreadRangeInfo> dics)
{
ActiveDocument?.InitProofreadCache(list);
ActiveDocument?.InitProofreadCache(list, dics);
}
#endregion

View File

@ -1,5 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<configSections>
<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler,log4net"/>
</configSections>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
@ -12,7 +15,7 @@
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Security.Cryptography.Xml" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-6.0.0.1" newVersion="6.0.0.1" />
<bindingRedirect oldVersion="0.0.0.0-8.0.0.2" newVersion="8.0.0.2" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Numerics.Vectors" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
@ -22,6 +25,60 @@
<assemblyIdentity name="System.Runtime.CompilerServices.Unsafe" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-5.0.0.0" newVersion="5.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Microsoft.IO.RecyclableMemoryStream" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-3.0.1.0" newVersion="3.0.1.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
<log4net>
<!-- Define some output appenders -->
<appender name="rollingAppender" type="log4net.Appender.RollingFileAppender">
<file value="${APP_DATA}"/>
<!--追加日志内容-->
<appendToFile value="true"/>
<!--防止多线程时不能写Log,官方说线程非安全-->
<lockingModel type="log4net.Appender.FileAppender+MinimalLock"/>
<!--可以为:Once|Size|Date|Composite-->
<!--Composite为Size和Date的组合-->
<rollingStyle value="Composite"/>
<!--当备份文件时,为文件名加的后缀,这里可以作为每一天的日志分别存储不同的文件-->
<datePattern value="yyyy-MM-dd&quot;.txt&quot;"/>
<StaticLogFileName value="false"/>
<!--日志最大个数,都是最新的-->
<!--rollingStyle节点为Size时,只能有value个日志-->
<!--rollingStyle节点为Composite时,每天有value个日志-->
<maxSizeRollBackups value="20"/>
<!--可用的单位:KB|MB|GB-->
<maximumFileSize value="5MB"/>
<!--置为true,当前最新日志文件名永远为file节中的名字-->
<staticLogFileName value="true"/>
<!--输出级别在INFO和ERROR之间的日志-->
<filter type="log4net.Filter.LevelRangeFilter">
<param name="LevelMin" value="DEBUG"/>
<param name="LevelMax" value="FATAL"/>
</filter>
<layout type="log4net.Layout.PatternLayout">
<!--日志输出格式:时间 日志类型 日志内容-->
<conversionPattern value="%date [%thread] %-5level %logger - %message%newline"/>
</layout>
</appender>
<!-- levels: OFF > FATAL > ERROR > WARN > INFO > DEBUG > ALL -->
<root>
<priority value="ALL"/>
<level value="ALL"/>
<appender-ref ref="rollingAppender"/>
</root>
</log4net>
</configuration>

View File

@ -0,0 +1,42 @@
namespace AIProofread.core
{
public class AppModule
{
/// <summary>
/// 是否启用导出校对结果
/// </summary>
public const bool ENABLE_EXPORT_PROOFREAD_RESULT = true;
/// <summary>
/// 是否词库管理
/// </summary>
public const bool ENABLE_LEXICON_MANAGE = true;
/// <summary>
/// 是否启用常识性检测
/// </summary>
public const bool ENABLE_COMMONSENSE_CHECK = true;
/// <summary>
/// 设置功能
/// </summary>
public const bool ENABLE_SETTING = true;
/// <summary>
/// 是否校对功能
/// </summary>
public const bool ENABLE_PROOFREAD = true;
/// <summary>
/// 优先查全
/// </summary>
public const bool ENABLE_PROOFREAD_FULL = true;
/// <summary>
/// 优先查准exact
/// </summary>
public const bool ENABLE_PROOFREAD_EXACT = true;
public const bool ENABLE_SAVE_CACHE = true;
public const bool ENABLE_LOAD_CACHE = true;
public const bool ENABLE_CUSTOMER_SERVICE = true;
public const bool ENABLE_UPGRADE = true;
public const bool ENABLE_HELP = true;
}
}

View File

@ -0,0 +1,476 @@
using AIProofread.Model;
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Spreadsheet;
using DocumentFormat.OpenXml;
using UtilLib;
using System;
using log4net;
namespace AIProofread.core
{
public class CorrectResultExportor
{
public ILog Logger = LogHelper.GetLogger(typeof(CorrectResultExportor));
// 设置表头
private static readonly string[] HeaderCols =
{
"序号","页","行","详细信息","异常", "建议","处理状态"
};
private static CorrectResultExportor exportor = new CorrectResultExportor();
private HexBinaryValue primaryColor = new HexBinaryValue("FFD6AA69");
private HexBinaryValue whiteColor = new HexBinaryValue("FFFFFFFF");
private HexBinaryValue blackColor = new HexBinaryValue("FF000000");
private CorrectResultExportor()
{
}
public static CorrectResultExportor GetInstance()
{
return exportor;
}
private Stylesheet CreateStyleSheet()
{
// 字体样式(默认和微软雅黑)
Fonts fonts = new Fonts(
new Font( // 默认字体
new FontName() { Val = "宋体" },
new FontSize() { Val = 11 }
),
new Font( // 微软雅黑字体
new FontName() { Val = "黑体" },
new RunFont() { Val = "黑体" },
new FontSize() { Val = 11 }
),
new Font( // 首行表头
new FontName() { Val = "黑体" },
new RunFont() { Val = "黑体" },
new FontSize() { Val = 11 },
new Color() { Rgb = primaryColor } // 字体颜色
),
new Font( // 首行表头
new FontName() { Val = "宋体" },
new RunFont() { Val = "宋体" },
new FontSize() { Val = 11 }
)
);
// 背景填充(黑色/金色)
Fills fills = new Fills(
new Fill(new PatternFill() { PatternType = PatternValues.None }),
new Fill(new PatternFill()
{
PatternType = PatternValues.Solid,
ForegroundColor = new ForegroundColor() { Rgb = blackColor }
}),
new Fill(new PatternFill()
{
PatternType = PatternValues.Solid,
ForegroundColor = new ForegroundColor() { Rgb = blackColor }
})
);
// 边框样式
Borders borders = new Borders(
new Border(), // 默认无边框
new Border(
new LeftBorder() { Style = BorderStyleValues.Thin, Color = new Color() { Rgb = blackColor } },
new RightBorder() { Style = BorderStyleValues.Thin, Color = new Color() { Rgb = blackColor } },
new TopBorder() { Style = BorderStyleValues.Thin, Color = new Color() { Rgb = blackColor } },
new BottomBorder() { Style = BorderStyleValues.Thin, Color = new Color() { Rgb = blackColor } },
new DiagonalBorder()
)
);
// 单元格样式
CellFormats cellFormats = new CellFormats(
new CellFormat() // 默认
{
ApplyAlignment = true,
Alignment = new Alignment()
{
Horizontal = HorizontalAlignmentValues.Left,
Vertical = VerticalAlignmentValues.Center,
WrapText = true
}
},
new CellFormat() // 首行
{
FontId = 2, // 使用黑体字体
FillId = 2, // 使用黑色背景
ApplyFont = true,
ApplyFill = true,
ApplyAlignment = true,
Alignment = new Alignment()
{
Horizontal = HorizontalAlignmentValues.Center,
Vertical = VerticalAlignmentValues.Center,
WrapText = true
}
},
new CellFormat() // 单纯的黑体
{
FontId = 1,
ApplyFont = true,
ApplyAlignment = true,
Alignment = new Alignment()
{
Horizontal = HorizontalAlignmentValues.Center,
Vertical = VerticalAlignmentValues.Center,
WrapText = true
}
},
new CellFormat() // 单纯的黑体
{
FontId = 3,
ApplyFont = true,
Alignment = new Alignment()
{
Horizontal = HorizontalAlignmentValues.Left,
Vertical = VerticalAlignmentValues.Center,
WrapText = true
}
}
);
return new Stylesheet(fonts, fills, borders, cellFormats);
}
/// <summary>
/// 使用Excel COM导出
/// </summary>
/// <param name="fileName"></param>
public void ExportResult(string fileName)
{
// 创建计时器,用于计算运行时间
var stopwatch = new System.Diagnostics.Stopwatch();
stopwatch.Start();
// 获取要导出的数据
var exportDataItems = ExportDataItem.GetExportData(Globals.ThisAddIn.ActiveDocument.marks);
// 创建Excel对象
using (SpreadsheetDocument document = SpreadsheetDocument.Create(fileName, SpreadsheetDocumentType.Workbook))
{
#region Workbook Worksheet
WorkbookPart workbookPart = document.AddWorkbookPart();
// 设置样式
var stylesPart = workbookPart.AddNewPart<WorkbookStylesPart>();
stylesPart.Stylesheet = CreateStyleSheet();
stylesPart.Stylesheet.Save();
// 创建工作簿
workbookPart.Workbook = new Workbook();
WorksheetPart worksheetPart = workbookPart.AddNewPart<WorksheetPart>();
var worksheet = new Worksheet();
// 冻结首行
worksheet.Append(new SheetViews(
new SheetView()
{
WorkbookViewId = 0,
Pane = new Pane()
{
VerticalSplit = 1,
TopLeftCell = "A2",
ActivePane = PaneValues.BottomLeft,
State = PaneStateValues.Frozen
}
}
));
worksheetPart.Worksheet = worksheet;
// 创建
Sheets sheets = document.WorkbookPart.Workbook.AppendChild(new Sheets());
// 美化sheet
StyleSheet(worksheet); // column 必须在sheet data 之前
worksheet.Append(new SheetData());
Sheet sheet = new Sheet()
{
Id = document.WorkbookPart.GetIdOfPart(worksheetPart),
SheetId = 1,
Name = "Sheet1"
};
sheets.Append(sheet);
#endregion
// 获取 SheetData
SheetData sheetData = worksheetPart.Worksheet.GetFirstChild<SheetData>();
// 创建表头
CreateHeader(sheetData);
int rowIndex = 1;
foreach (var item in exportDataItems)
{
// 创建行
try
{
CreateRow(sheetData, item, ref rowIndex);
}
catch (Exception ex)
{
Logger.Error("导出勘误表异常:" + ex.Message, ex);
}
}
// 筛选
worksheetPart.Worksheet.Append(new AutoFilter { Reference = "A1:G1" });
//sheet.Append(new AutoFilter() { Reference = "A1:G1"});
}
stopwatch.Stop();
Logger.Info("导出勘误表" + fileName + "完成,运行时间:" + stopwatch.Elapsed.TotalMilliseconds + "毫秒");
}
private void StyleSheet(Worksheet worksheet)
{
// 设置列宽
Columns columns = new Columns();
SetColumnWidth(1, 0, columns); // 隐藏第一列
SetColumnWidth(2, 3, 6, columns);
SetColumnWidth(4, 80, columns);
SetColumnWidth(5, 6, 20, columns);
SetColumnWidth(7, 10, columns);
worksheet.Append(columns);
}
private void SetColumnWidth(uint colIndex, int width, Columns columns)
{
SetColumnWidth(colIndex, colIndex, width, columns);
}
private void SetColumnWidth(uint startColIndex, uint endColIndex, int width, Columns columns)
{
columns.Append(
new Column()
{
Min = startColIndex, // 从第1列开始
Max = endColIndex, // 到第3列结束
Width = width, // 宽度值(一般 8.43 为默认)
CustomWidth = true,
Hidden = width <= 0,
}
);
}
private void CreateHeader(SheetData sheetData)
{
// 创建表头行
Row headerRow = new Row() { Height = 40, CustomHeight = true };
foreach (var header in HeaderCols)
{
headerRow.AppendChild(new Cell()
{
DataType = CellValues.String,
StyleIndex = 1, // 设置背景为黑色,字体为金色
CellValue = new CellValue(header)
});
}
sheetData.AppendChild(headerRow);
}
private void CreateRow(SheetData sheetData, ExportDataItem item, ref int rowIndex)
{
var it = item.Item;
Row row = new Row();
// 写入数据
// 1. 序号
CreateNormalCell(rowIndex, row);
// 2. 页码
CreateNormalCell(item.PageNumber, row);
// 3. 行号
CreateNormalCell(item.LineNumber, row);
// 4. 引用原文(详细信息)
CreateOriginSentenceCell(row, item);
// 5. 异常
CreateNormalCell(it.Origin, row, 3);
// 6. 建议
CreateCorrectSuggestCell(row, item);
// 7. 处理状态
CreateNormalCell(StatusText(it.IsAccept), row, 2);
sheetData.AppendChild(row);
rowIndex++;
}
private string StatusText(int status)
{
if (status == AcceptStatus.Accept) return "已采纳";
else if (status == AcceptStatus.Review) return "已复核";
else if (status == AcceptStatus.Ignore) return "已忽略";
return "未处理";
}
/// <summary>
/// 创建普通单元格
/// </summary>
/// <param name="value"></param>
/// <param name="row"></param>
/// <param name="styleIndex">样式索引id,从0开始</param>
private void CreateNormalCell(object value, Row row, uint styleIndex)
{
row.AppendChild(new Cell()
{
DataType = CellValues.String,
StyleIndex = styleIndex,
CellValue = new CellValue(value == null ? string.Empty : value.ToString()) { Space = SpaceProcessingModeValues.Preserve }
});
}
private void CreateNormalCell(object value, Row row)
{
row.AppendChild(new Cell()
{
DataType = CellValues.String,
CellValue = new CellValue(value == null ? string.Empty : value.ToString()) { Space = SpaceProcessingModeValues.Preserve }
});
}
/// <summary>
/// 创建引用原文(详细信息)单元格
/// </summary>
/// <param name="row"></param>
/// <param name="item"></param>
private void CreateOriginSentenceCell(Row row, ExportDataItem item)
{
var it = item.Item;
string originSentence = item.OriginSentence.TrimEnd();
//var startIndex = it.Tag == "i" || it.Start < originSentence.Length - 1 ? it.Start : originSentence.IndexOf(it.Origin);
var cell = new Cell()
{
DataType = CellValues.InlineString,
StyleIndex = 3
};
var beforeText = it.Start == 0 ? null : originSentence.Substring(0, it.Start);
var richTextLength = it.Tag == "i" ? it.Text.Length:it.Origin.Length; // it.Tag == "i" ? 1 : it.Text.Length
var richText = originSentence.Substring(it.Start, richTextLength);
var afterText = it.Start >= originSentence.Length ? null : originSentence.Substring(it.Start + richTextLength);
var inlineString = new InlineString();
AppendRichTextToCell(beforeText, inlineString);
AppendRichTextToCell(richText, inlineString, "FFFF0000");
AppendRichTextToCell(afterText, inlineString);
cell.InlineString = inlineString;
row.AppendChild(cell);
}
private void CreateCorrectSuggestCell(Row row, ExportDataItem item)
{
var it = item.Item;
var cell = new Cell()
{
DataType = CellValues.InlineString,
StyleIndex = 3
};
var inlineString = new InlineString();
var suggest = it.Text;
if (it.Tag == "r")
{
string tag = "";
if (it.Type == "blacklist")
{
tag = "黑名单";
}
else
{
// 易错词 标点 不标识
if (it.Type == "confusion" || it.Type == "model" || it.Type == "other" || it.Type == "punctuation")
{
//row.CreateCell(5).SetCellValue(suggest);
}
else if (!string.IsNullOrEmpty(it.Type) && ExportConfig.ErrorTypeMap.ContainsKey(it.Type.ToLower()))
{
tag = $"【提示】{ExportConfig.ErrorTypeMap[it.Type.ToLower()]}";
}
else if (!string.IsNullOrEmpty(it.Addition) && it.Addition.Trim().Length > 0 && it.Addition != "提示")
{
tag = $"【提示】{it.Addition}";
}
}
if (!string.IsNullOrEmpty(tag))
{
AppendNormalTextToCell(suggest + " ", inlineString);
AppendRichTextToCell(tag, inlineString, "000000", "黑体");
}
else
{
AppendNormalTextToCell(suggest, inlineString);
}
}
else
{
string tag = "";
if (it.Type == "incorrect_expression")
{
tag = "表述有误";
}
else if (it.Type == "sensitive")
{
tag = "敏感词";
}
else if (it.Type == "blacklist" || it.Type == "blacklist_mask")
{
tag = "黑名单";
}
else if (it.Type == "fallen_officers")
{
tag = "疑似落马官员";
}
else if (it.Tag == "i")
{
AppendNormalTextToCell(it.Text, inlineString);
tag = " 新增";
}
else if (it.Tag == "d")
{
tag = "删除";
}
if (tag.Length > 0)
{
AppendRichTextToCell(tag, inlineString, "000000", "黑体");
}
else
{
AppendNormalTextToCell(suggest, inlineString);
}
}
cell.InlineString = inlineString;
row.AppendChild(cell);
}
private void AppendNormalTextToCell(string text, InlineString inlineString, string color = "FF000000", string fontName = "宋体")
{
if (string.IsNullOrEmpty(text)) return;
var props = new RunProperties(
new FontSize() { Val = 11 }
);
if (color != "FF000000") props.Append(new Color() { Rgb = new HexBinaryValue(color) });
if (fontName != "宋体") props.Append(new RunFont() { Val = fontName });
var run = new Run(
props,
new Text(text) { Space = SpaceProcessingModeValues.Preserve }
);
inlineString.Append(run);
}
private void AppendRichTextToCell(string text, InlineString inlineString, string color = "FF000000", string fontName = "宋体")
{
if (string.IsNullOrEmpty(text)) return;
var props = new RunProperties(
new FontSize() { Val = 11 }
);
if (color != "000000") props.Append(new Color() { Rgb = new HexBinaryValue(color) });
if (fontName != "宋体") props.Append(new RunFont() { Val = fontName });
var run = new Run(props, new Text(text) { Space = SpaceProcessingModeValues.Preserve });
inlineString.Append(run);
}
}
}

View File

@ -0,0 +1,76 @@
using System.Runtime.InteropServices;
using System.Windows.Forms;
using System;
using Word = Microsoft.Office.Interop.Word;
using System.Collections.Generic;
namespace AIProofread.core
{
public class ProcessingContext
{
public Word.Range Range { get; set; }
public int GlobalIndex { get; set; }
}
public class DocumentReader
{
private static readonly Stack<ProcessingContext> _processingStack = new Stack<ProcessingContext>();
public static List<DocumentText> ReadByVSTO(Word.Document _doc, Word.Application _app, List<DocumentText> list)
{
//List<DocumentText> list = new List<DocumentText>();
try
{
// 关闭屏幕更新
_app.ScreenUpdating = false;
// 初始化堆栈:处理所有顶级 StoryRanges
foreach (Word.Range storyRange in _doc.StoryRanges)
{
_processingStack.Push(new ProcessingContext
{
Range = storyRange,
GlobalIndex = 0,
});
}
// 迭代处理堆栈中的每个 Range
while (_processingStack.Count > 0)
{
var context = _processingStack.Pop();
ProcessElement(context.Range, context.GlobalIndex, list);
Marshal.ReleaseComObject(context.Range);
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
finally
{
_app.ScreenUpdating = true;
Marshal.ReleaseComObject(_doc);
}
return list;
}
private static void ProcessElement(Word.Range range, int globalIndex, List<DocumentText> list)
{
if (range.Text?.Trim() == "\r\a")
{
globalIndex++;
return;
}
var paragraphs = range.Paragraphs;
// Debug.WriteLine($"Processing element: {range.Text}");
// 处理段落
foreach (Word.Paragraph paragraph in paragraphs)
{
list.Add(new DocumentText
{
Text = paragraph.Range.Text,
ParagraphNumber = globalIndex + 1
});
Marshal.ReleaseComObject(paragraph);
globalIndex++;
}
}
}
}

View File

@ -13,21 +13,18 @@ using NPOI.XSSF.UserModel;
using System.Windows.Forms;
using NPOI.SS.UserModel;
using System.IO;
using SixLabors.Fonts.Tables.AdvancedTypographic;
using MathNet.Numerics.LinearAlgebra.Factorization;
using System.Linq;
using NPOI.SS.Formula.Functions;
using AIProofread.Model;
using System.Xml.Linq;
using NPOI.SS.Util;
using NPOI.HSSF.Util;
using static NPOI.HSSF.Util.HSSFColor;
using AIProofread.core;
using log4net;
namespace AIProofread
{
public class DocumentUtil
{
static int markId = 0;
public static readonly ILog Logger = LogHelper.GetLogger(typeof(DocumentUtil));
/// <summary>
/// 添加一个书签
@ -112,11 +109,17 @@ namespace AIProofread
//mark.Range.Underline = WdUnderline.wdUnderlineNone;
try
{
// feat(20250305): 清除批注的时候,如果监测到书签位置是空格,把空格给删了吧(无缓冲记录时)
string text = mark.Range.Text;
if (text != null && text.Trim().Length == 0)
{
mark.Range.Text = "";
}
mark.Delete();
}
catch (Exception e)
{
Logger.Log("remove mark", e);
Logger.Error("remove mark" + e.Message, e);
}
}
}
@ -141,23 +144,6 @@ namespace AIProofread
mark.Delete();
}
}
//foreach (var mark in document.Bookmarks)
//{
// if (markId != null)
// {
// if (mark.Name == markId)
// {
// // 删除
// mark.Delete();
// mark.Range.Shading.BackgroundPatternColor = (WdColor)WdColorIndex.wdAuto;
// return;
// }
// }
// else
// {
// mark.Delete();
// }
//}
}
public static System.Collections.Generic.List<string> GetSectionText()
@ -253,52 +239,11 @@ namespace AIProofread
{ "search_end",range.End },
{ "search_text",range.Text }
};
Logger.Log(JsonConvert.SerializeObject(msg1));
//while (range.Find.Found)
//{
// var obj4 = range.Document;
// MatchControl = range.Start;
// MatchAlefHamza = range.End;
// var range2 = obj4.Range(ref MatchControl, ref MatchAlefHamza);
// num3 = range2.End;
// if (range2.Text == findText)
// {
// return range2;
// }
// break;
// //if (findIndex == num)
// //{
// //}
// //num++;
// //range.Find.MatchByte = true;
// //Find find2 = range.Find;
// //MatchAlefHamza = missword;
// //MatchControl = true;
// //MatchDiacritics = Type.Missing;
// //MatchKashida = Type.Missing;
// //Replace = Type.Missing;
// //ReplaceWith = Type.Missing;
// //Format = Type.Missing;
// //Wrap = Type.Missing;
// //Forward = Type.Missing;
// //MatchAllWordForms = Type.Missing;
// //MatchSoundsLike = Type.Missing;
// //MatchWildcards = Type.Missing;
// //MatchWholeWord = Type.Missing;
// //Start = Type.Missing;
// //End = Type.Missing;
// //// 再次重复查找
// //find2.Execute(ref MatchAlefHamza, ref MatchControl, ref MatchDiacritics, ref MatchKashida, ref Replace, ref ReplaceWith, ref Format, ref Wrap, ref Forward, ref MatchAllWordForms, ref MatchSoundsLike, ref MatchWildcards, ref MatchWholeWord, ref Start, ref End);
//}
//if (num3 == 0)
//{
// return null;
//}
Logger.Debug(JsonConvert.SerializeObject(msg1));
}
catch (Exception ex)
{
Logger.Log(ex);
Logger.Error(ex);
}
return null;
}
@ -326,24 +271,9 @@ namespace AIProofread
}
catch (Exception ex)
{
Logger.Log(ex);
Logger.Error(ex);
}
return null;
//if(bookmark == null)
//{
// foreach (var m in marks)
// {
// var mark = m as Bookmark;
// var name = mark.Name;
// var tag = mark.Tag?.ToString();
// if(tag == markName || name == markName)
// {
// return mark;
// }
// }
//}
//return bookmark as Bookmark;
}
public static Bookmark FindRangeAndCreateBookmark(CorrectItem correct, CorrectContext sentense, Microsoft.Office.Interop.Word.Document document, ref int prevOffset)
@ -380,12 +310,12 @@ namespace AIProofread
}
catch (Exception ex)
{
Logger.Log("create mark error:" + ex.Message + "\n" + ex.StackTrace + "\n\n");
Logger.Error("create mark error:" + ex.Message + "\n" + ex.StackTrace + "\n\n");
}
return bookmark;
}
private static Range FindBySentence(Range paraRange, CorrectContext c, CorrectItem item, Microsoft.Office.Interop.Word.Document document)
private static Range FindBySentence(Range paraRange, CorrectContext c, CorrectItem item, Microsoft.Office.Interop.Word.Document document, int prevOffset)
{
try
{
@ -403,6 +333,7 @@ namespace AIProofread
}
//int count = 0;
var range = document.Range(offset + item.Start, offset + item.End + 1);
#region
//while (true && count++ < 10)
//{
// //
@ -427,6 +358,7 @@ namespace AIProofread
// Logger.Log(dce);
// }
//}
#endregion
// 比对原始内容与校对原文是否一致
if (range.Text == item.Origin)
{
@ -436,7 +368,7 @@ namespace AIProofread
// 直接找
var range1 = document.Range(offset + item.Start, offset + item.End + 1);
// 兼容空格的全角与半角
if(item.Origin == " " && (range1.Text == " " || range1.Text == " " || range1.Text.Trim().Length == 0))
if (item.Origin == " " && (range1.Text == " " || range1.Text == " " || range1.Text.Trim().Length == 0))
{
return range1;
}
@ -445,20 +377,26 @@ namespace AIProofread
{
return range1;
}
// 执行查找
return FindTextInRange(sentence, item.Origin);
return FindTextInRange(sentence, item.Origin,prevOffset);
}
catch (Exception)
catch (Exception e)
{
Logger.Error("find by sentence error",e);
}
return null;
}
public static Range FindTextInRange(Range range, string searchText)
public static Range FindTextInRange(Range range, string searchText,int prevOffset, int findStart = -1)
{
try
{
if (findStart > 0)
{
range.Start = range.Start + findStart;
}
Find find = range.Find;
if (range.Comments.Count > 0)
{
@ -471,7 +409,8 @@ namespace AIProofread
find.Wrap = WdFindWrap.wdFindContinue;
find.Execute();
if (find.Found) return range;
} catch (Exception) { }
}
catch (Exception) { }
return null;
}
@ -487,7 +426,7 @@ namespace AIProofread
//var offset = paraStart + c.SentenceOffset;
////var cutLength = Math.Min(c.InsertLen, paraText.Length - offset);
var originFindRange = FindBySentence(paraRange, c, item, document);
var originFindRange = FindBySentence(paraRange, c, item, document, prevOffset);
if (originFindRange != null) return originFindRange;
// 如果是新增 则查找定位
@ -519,7 +458,7 @@ namespace AIProofread
if (prevOffset >= paraText.Length)
{
// 查找位置已经超过了整段长度了
Logger.Log("prevOffset:" + prevOffset + " paraText.Length:" + paraText.Length);
Logger.Debug("prevOffset:" + prevOffset + " paraText.Length:" + paraText.Length);
return null;
}
// 执行查找
@ -556,7 +495,7 @@ namespace AIProofread
if (range.Text == item.Origin) { return range; }
}
// 使用find查找
var r = FindTextInRange(paraRange, item.Origin);
var r = FindTextInRange(paraRange, item.Origin, prevOffset);
if (r != null)
{
// 判断找到的range是否和查找区域误差过大
@ -571,14 +510,15 @@ namespace AIProofread
}
public static void ExportProofreadResult()
public static void ExportProofreadResult(string modelType)
{
string currentName = Globals.ThisAddIn.Application.ActiveDocument.Name;
// 去掉文件名后缀
currentName = currentName.Substring(0, currentName.LastIndexOf("."));
SaveFileDialog sfd = new SaveFileDialog();
modelType = modelType == "full" ? "查全" : "查准";
// 设置默认文件名
sfd.FileName = currentName + "_勘误表.xlsx";
sfd.FileName = currentName + $"_勘误表_优先{modelType}.xlsx";
sfd.Filter = "Excel文件|*.xlsx";
var result = sfd.ShowDialog();
// 如果用户取消选择,则返回
@ -593,23 +533,24 @@ namespace AIProofread
// 判断原始文件是否可以删除
if (File.GetAttributes(sfd.FileName).HasFlag(FileAttributes.ReadOnly))
{
Globals.ThisAddIn.ShowDialog("已经存在名勘误表文件,请更换名称或手动删除", null, null);
Globals.ThisAddIn.ShowDialog("已经存在名勘误表文件,请更换名称或手动删除", null, null);
return;
}
// 删除文件 重新写入新数据避免出现未知不可控bug
File.Delete(sfd.FileName);
}
ProcessExport(sfd.FileName);
//ProcessExport(sfd.FileName);
CorrectResultExportor.GetInstance().ExportResult(sfd.FileName);
Globals.ThisAddIn.ActiveDocument?.ShowMessage("导出勘误表成功", 2000, false);
}
catch (Exception e)
{
Logger.Log(e);
Logger.Error("导出勘误表失败",e);
Globals.ThisAddIn.ShowDialog("导出勘误表失败,请重试", null, null);
}
}
private static NPOI.SS.UserModel.ICell CreateCell(IRow row, int colIndex, IFont font, string text,ICellStyle style = null)
private static NPOI.SS.UserModel.ICell CreateCell(IRow row, int colIndex, IFont font, string text, ICellStyle style = null)
{
var cell = row.CreateCell(colIndex);
if (font != null)
@ -622,7 +563,7 @@ namespace AIProofread
{
cell.SetCellValue(text);
}
if(style != null)
if (style != null)
{
cell.CellStyle = style;
@ -633,6 +574,11 @@ namespace AIProofread
}
return cell;
}
private static int RGB(int red, int green, int blue)
{
return red + (green << 8) + (blue << 16);
}
private static void ProcessExport(string fileName)
{
@ -640,6 +586,7 @@ namespace AIProofread
{
var book = new XSSFWorkbook();
var sheet = book.CreateSheet("Sheet1");
#region
var simHeiFont = CreateBaseFont(book, "黑体", 11);
simHeiFont.Color = NPOI.HSSF.Util.HSSFColor.Black.Index;
// 设置表格样式
@ -667,7 +614,7 @@ namespace AIProofread
};
// 设置表头筛选及冻结 2.0.5 2024-12-30修改
sheet.CreateFreezePane(0, 1,0,1);
sheet.CreateFreezePane(0, 1, 0, 1);
sheet.SetAutoFilter(CellRangeAddress.ValueOf("A1:G1"));
// 设置表头为白色
@ -676,13 +623,13 @@ namespace AIProofread
headerFont.FontName = "黑体"; // 设置字体
headerFont.FontHeightInPoints = 11; // 字体大小
var themeColor = new XSSFColor(new byte[] { 214, 170, 105 }); // 首行背景色黑色,字体用主题金色
((XSSFFont)headerFont).SetColor(themeColor);
((XSSFFont)headerFont).SetColor(themeColor);
headerStyle.SetFont(headerFont); // 应用字体
// 设置背景颜色为黑色
headerStyle.FillForegroundColor = HSSFColor.Black.Index; // 设置前景色
headerStyle.FillPattern = FillPattern.SolidForeground; // 使用实心填充模式
// 对齐方式
headerStyle.VerticalAlignment = VerticalAlignment.Center; // 垂直居中
headerStyle.Alignment = NPOI.SS.UserModel.HorizontalAlignment.Center; // 水平居中
@ -711,6 +658,7 @@ namespace AIProofread
var alignCenterStyle = book.CreateCellStyle();
alignCenterStyle.VerticalAlignment = VerticalAlignment.Center;
alignCenterStyle.Alignment = NPOI.SS.UserModel.HorizontalAlignment.Center;
#endregion
foreach (var item in list)
{
try
@ -731,42 +679,16 @@ namespace AIProofread
#region
string originSentence = item.OriginSentence.TrimEnd();
var startIndex = it.Tag == "i" || it.Start < originSentence.Length - 1 ? it.Start : originSentence.IndexOf(it.Origin);
//var endIndex = startIndex + (it.Tag == "i" ? it.Text.Length : it.Origin.Length);
//if (it.Tag == "i")
//{
// // ˽
// // 对查找内容引用红色
// try
// {
// originSentence = originSentence.Substring(0, startIndex) + GetInsertContentByLength(it.Text.Length) + originSentence.Substring(startIndex);
// }
// catch (Exception e)
// {
// Logger.Log(e);
// }
//}
//// 执行查找
//if (it.Tag == "i")
//{
// var blankText = ToolUtil.GetBlankText(it.Text.Length);
// startIndex = originSentence.IndexOf(blankText);
//}
XSSFRichTextString originText = new XSSFRichTextString(originSentence);
originText.ApplyFont(blackFont);
//// 不要越界鸟(不一定采用后端返回数据)
//if (startIndex < endIndex && startIndex < originSentence.Length - 1 && endIndex < originSentence.Length - 1)
//{
// // 对查找内容引用红色
// originText.ApplyFont(startIndex, endIndex, redFont);
//}
try
{
originText.ApplyFont(it.Start, it.Start + (it.Tag == "i" ? it.Text.Length : it.Origin.Length), redFont);
}
catch (Exception e)
{
Logger.Log(e);
Logger.Error(e);
}
var oriCell = row.CreateCell(3);
@ -841,6 +763,10 @@ namespace AIProofread
{
tag = "黑名单";
}
else if (it.Type == "fallen_officers")
{
tag = "落马官员";
}
else if (it.Tag == "i")
{
startIndex = it.Text.Length + 1;
@ -873,7 +799,7 @@ namespace AIProofread
}
catch (Exception ex)
{
Logger.Log(ex);
Logger.Error(ex);
}
id++;
}
@ -881,7 +807,6 @@ namespace AIProofread
// 保存到文件
book.Write(fs);
//Globals.ThisAddIn.ShowMessage("导出成功", 3000);
Globals.ThisAddIn.ActiveDocument?.ShowMessage("导出勘误表成功", 2000, false);
}
}

View File

@ -1,11 +1,15 @@
using Microsoft.Office.Interop.Word;
using AIProofread.core;
using Microsoft.Office.Interop.Word;
using Newtonsoft.Json;
using NPOI;
using NPOI.POIFS.FileSystem;
using NPOI.XWPF.UserModel;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.IO.Compression;
using System.Runtime.InteropServices;
using System.Security.Cryptography;
namespace AIProofread
@ -36,7 +40,64 @@ namespace AIProofread
// 获取当前文档所有文本
string allText = doc.Range().Text;
List<DocumentText> list = new List<DocumentText>();
using (FileStream stream = new FileStream(docPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
//DocumentReader.ReadByVSTO(doc, Globals.ThisAddIn.Application, list);
try
{
ReadTextByNPOI(docPath, list);
}
catch (POIXMLException ex)
{
// 编号有误,移除编号再读取
if (ex.StackTrace.Contains("NPOI.XWPF.UserModel.XWPFNumbering"))
{
RemoveNumbersReadTextByNPOI(docPath, list);
}
}
//using (FileStream stream = new FileStream(docPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
//{
// //try
// //{
// //}
// //catch (POIXMLException npoiError)
// //{
// // Logger.Log("GetAllText Error", npoiError);
// // // Logger.Log("GetAllText", e);
// // // return GetAllTextByVSTO(doc);
// // // 读取文档
// // DocumentReader.ReadByVSTO(doc, Globals.ThisAddIn.Application, list);
// //}
//}
var map = new Dictionary<string, object>
{
{ "list", list },
{ "text", allText }
};
// 删除临时文件
File.Delete(docPath);
return map;
}
private static void RemoveNumbersReadTextByNPOI(string filePath, List<DocumentText> list)
{
list.Clear();
var fs = File.OpenWrite(filePath);
// 打开Zip文件,删除 numbering.xml
using (ZipArchive archive = new ZipArchive(fs, ZipArchiveMode.Update))
{
var numberingEntry = archive.GetEntry("word/numbering.xml");
numberingEntry?.Delete(); // 删除 numbering.xml
}
fs.Close();
ReadTextByNPOI(filePath, list);
}
private static void ReadTextByNPOI(string filePath, List<DocumentText> list)
{
//, FileMode.Open, FileAccess.Read, FileShare.ReadWrite
using (var stream = File.OpenRead(filePath))
{
XWPFDocument ndoc = new XWPFDocument(stream);
var paragraphs = ndoc.Paragraphs;
@ -47,7 +108,11 @@ namespace AIProofread
if (bodyElement is XWPFParagraph p)
{
// 处理普通段落
list.Add(new DocumentText(p.ParagraphText.Replace("\u0002", ""), paragraphNumber));
var text = p.ParagraphText.Replace("\u0002", "");
if (text.Trim().Length > 0)
{
list.Add(new DocumentText(text, paragraphNumber));
}
paragraphNumber++;
}
// table -- vsto对于每个单元格的分段也会有
@ -74,36 +139,30 @@ namespace AIProofread
// 如果需要,可以进一步解析目录项// 例如,按换行符拆分目录内容
var tocEntries = tocText.Split(new string[] { "\n", "\r", "\r\n", "\f" }, StringSplitOptions.None);
foreach (string entry in tocEntries)
{
list.Add(new DocumentText(entry.Replace("\u0002", ""), paragraphNumber));
paragraphNumber++;
}
paragraphNumber += tocEntries.Length;
// 暂时跳过目录
//foreach (string entry in tocEntries)
//{
// list.Add(new DocumentText(entry.Replace("\u0002", ""), paragraphNumber));
// paragraphNumber++;
//}
}
}
}
Debug.WriteLine("GetAllText End ==>", DateTime.Now.ToLongTimeString());
var map = new Dictionary<string, object>
{
{ "list", list },
{ "text", allText }
};
// 删除临时文件
File.Delete(docPath);
return map;
}
public static string GetReadDocumentFilePath(Microsoft.Office.Interop.Word.Document doc)
{
// 保存文档确保内容是最新的
doc.Save();
//
string docPath = doc.FullName;
string ext = Path.GetExtension(docPath);
string tmpFile = Path.GetTempFileName();
Debug.WriteLine("GetReadDocumentFilePath Start ==>", DateTime.Now.ToLongTimeString());
Debug.WriteLine("GetReadDocumentFilePath =>{0}", docPath);
//Debug.WriteLine("GetReadDocumentFilePath Start ==>", DateTime.Now.ToLongTimeString());
//Debug.WriteLine("GetReadDocumentFilePath =>{0}", docPath);
// 先转成临时文件
FileStream fs = new FileStream(docPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
@ -155,8 +214,7 @@ namespace AIProofread
// 获取当前文档所有文本
string allText = doc.Range().Text;
List<DocumentText> list = new List<DocumentText>();
// // 开始分割
MD5 md5 = new MD5CryptoServiceProvider();
Paragraphs paragraphs = doc.Paragraphs;
@ -166,18 +224,22 @@ namespace AIProofread
foreach (Paragraph p in paragraphs)
{
paragraphNumber++;
if (paragraphNumber % 20 == 0)
{
Debug.WriteLine("process paragraphNumber{0}", paragraphNumber);
}
//if (paragraphNumber % 20 == 0)
//{
// Debug.WriteLine("process paragraphNumber{0}", paragraphNumber);
//}
Range r = p.Range;
string text = p.Range.Text;
if (text.Trim().Length == 0 || text.EndsWith("\r\a") || r.Tables.Count > 0)
{
continue;
}
list.Add(new DocumentText(text.Replace("\u0002", ""), paragraphNumber));
Marshal.ReleaseComObject(p);
}
Marshal.ReleaseComObject(paragraphs);
//for (; paragraphNumber <= total; paragraphNumber++)
//{
@ -234,5 +296,23 @@ namespace AIProofread
{
return JsonConvert.SerializeObject(data, Formatting.Indented);
}
/// <summary>
/// 生成设备唯一标识
/// </summary>
/// <returns></returns>
public static string GetDeviceId()
{
string devicePath = Config.APP_DATA_PATH + "\\deviceId.txt";
// 如果存在则直接返回
if (File.Exists(devicePath))
{
return File.ReadAllText(devicePath);
}
string deviceId = Guid.NewGuid().ToString().ToLower();
// 将deviceId保存为纯文本文件到程序目录
File.WriteAllText(devicePath, deviceId);
return deviceId;
}
}
}

View File

@ -0,0 +1,38 @@
using Microsoft.Web.WebView2.Core;
using Microsoft.Web.WebView2.WinForms;
using System;
using System.Linq;
namespace AIProofread.core
{
public class WebView2EventHandler
{
public static void WebView2NavigationCompleted(object sender, CoreWebView2NavigationCompletedEventArgs e)
{
if (e.IsSuccess)
{
return;
}
string errorPageHtml = @"
<html>
<head>
<title></title>
<style>
body { font-family: sans-serif; text-align: center; padding-top: 50px; background-color: #f0f0f0; }
h1 { color: #d00; }
</style>
</head>
<body>
<h1></h1>
<p></p>
</body>
</html>";
if (e.NavigationId == 0)
{
(sender as WebView2).CoreWebView2.NavigateToString(errorPageHtml);
}
}
}
}

BIN
AIProofread/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.8 KiB

View File

@ -1 +1 @@
80a1b62e50022f6927ea33d64c401a80d068064724a07da1ca8562102f036978
929ddb904bc44ec29047ef594f7522c7d07da74ec9e1e0fee604f0735e8c62cf

View File

@ -216,3 +216,12 @@ C:\Users\yaclt\source\repos\repos\AIProofread\AIProofread\bin\Debug\AIProofread.
C:\Users\yaclt\source\repos\repos\AIProofread\AIProofread\bin\Debug\AntdUI.dll
C:\Users\yaclt\source\repos\repos\AIProofread\AIProofread\bin\Debug\AntdUI.xml
C:\Users\yaclt\source\repos\repos\AIProofread\AIProofread\obj\Debug\AIProofread.Controls.FormCommonsenseDetection.resources
C:\Users\yaclt\source\repos\repos\AIProofread\AIProofread\obj\Debug\AIProofread.Controls.FormLexicon.resources
C:\Users\yaclt\source\repos\repos\AIProofread\AIProofread\bin\Debug\System.ComponentModel.Annotations.dll
C:\Users\yaclt\source\repos\repos\AIProofread\AIProofread\bin\Debug\DocumentFormat.OpenXml.dll
C:\Users\yaclt\source\repos\repos\AIProofread\AIProofread\bin\Debug\DocumentFormat.OpenXml.Framework.dll
C:\Users\yaclt\source\repos\repos\AIProofread\AIProofread\bin\Debug\DocumentFormat.OpenXml.xml
C:\Users\yaclt\source\repos\repos\AIProofread\AIProofread\bin\Debug\DocumentFormat.OpenXml.Framework.xml
C:\Users\yaclt\source\repos\repos\AIProofread\AIProofread\bin\Debug\log4net.dll
C:\Users\yaclt\source\repos\repos\AIProofread\AIProofread\bin\Debug\log4net.pdb
C:\Users\yaclt\source\repos\repos\AIProofread\AIProofread\bin\Debug\log4net.xml

View File

@ -1,23 +1,27 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="BouncyCastle.Cryptography" version="2.3.1" targetFramework="net462" />
<package id="DocumentFormat.OpenXml" version="3.3.0" targetFramework="net462" />
<package id="DocumentFormat.OpenXml.Framework" version="3.3.0" targetFramework="net462" />
<package id="Enums.NET" version="4.0.1" targetFramework="net462" />
<package id="ExtendedNumerics.BigDecimal" version="2025.1001.2.129" targetFramework="net462" />
<package id="log4net" version="3.0.4" targetFramework="net462" />
<package id="MathNet.Numerics.Signed" version="5.0.0" targetFramework="net462" />
<package id="Microsoft.IO.RecyclableMemoryStream" version="3.0.0" targetFramework="net462" />
<package id="Microsoft.IO.RecyclableMemoryStream" version="3.0.1" targetFramework="net462" />
<package id="Microsoft.Web.WebView2" version="1.0.2210.55" targetFramework="net462" />
<package id="NPOI" version="2.7.1" targetFramework="net462" />
<package id="SharpZipLib" version="1.4.2" targetFramework="net462" />
<package id="SixLabors.Fonts" version="1.0.1" targetFramework="net462" />
<package id="SixLabors.ImageSharp" version="2.1.8" targetFramework="net462" />
<package id="System.Buffers" version="4.5.1" targetFramework="net462" />
<package id="System.ComponentModel.Annotations" version="5.0.0" targetFramework="net462" />
<package id="System.Configuration.ConfigurationManager" version="6.0.0" targetFramework="net462" />
<package id="System.Memory" version="4.5.5" targetFramework="net462" />
<package id="System.Numerics.Vectors" version="4.5.0" targetFramework="net462" />
<package id="System.Runtime.CompilerServices.Unsafe" version="5.0.0" targetFramework="net462" />
<package id="System.Security.AccessControl" version="6.0.0" targetFramework="net462" />
<package id="System.Security.Cryptography.Pkcs" version="6.0.3" targetFramework="net462" />
<package id="System.Security.Cryptography.Xml" version="6.0.1" targetFramework="net462" />
<package id="System.Security.Cryptography.Xml" version="8.0.2" targetFramework="net462" />
<package id="System.Security.Permissions" version="6.0.0" targetFramework="net462" />
<package id="System.Security.Principal.Windows" version="5.0.0" targetFramework="net462" />
<package id="System.Text.Encoding.CodePages" version="5.0.0" targetFramework="net462" />

View File

@ -35,24 +35,29 @@
this.panel1 = new System.Windows.Forms.Panel();
this.IconClose = new System.Windows.Forms.PictureBox();
this.label1 = new System.Windows.Forms.Label();
this.panelLog = new AntdUI.Panel();
this.panel1.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.IconClose)).BeginInit();
this.panelLog.SuspendLayout();
this.SuspendLayout();
//
// LabelLog
//
this.LabelLog.Font = new System.Drawing.Font("微软雅黑", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
this.LabelLog.Location = new System.Drawing.Point(40, 57);
this.LabelLog.AutoEllipsis = true;
this.LabelLog.BackColor = System.Drawing.Color.Transparent;
this.LabelLog.Dock = System.Windows.Forms.DockStyle.Fill;
this.LabelLog.Font = new System.Drawing.Font("微软雅黑", 10F);
this.LabelLog.Location = new System.Drawing.Point(5, 5);
this.LabelLog.Name = "LabelLog";
this.LabelLog.Size = new System.Drawing.Size(300, 71);
this.LabelLog.Size = new System.Drawing.Size(290, 100);
this.LabelLog.TabIndex = 0;
this.LabelLog.Text = "正在检测。。。";
this.LabelLog.Text = "版本检测中 ...";
this.LabelLog.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
this.LabelLog.Click += new System.EventHandler(this.LabelLog_Click);
//
// progressBar1
//
this.progressBar1.Location = new System.Drawing.Point(40, 136);
this.progressBar1.Location = new System.Drawing.Point(40, 180);
this.progressBar1.Name = "progressBar1";
this.progressBar1.Size = new System.Drawing.Size(300, 14);
this.progressBar1.TabIndex = 3;
@ -64,7 +69,7 @@
this.ButtonProcess.DefaultBack = System.Drawing.Color.FromArgb(((int)(((byte)(201)))), ((int)(((byte)(160)))), ((int)(((byte)(99)))));
this.ButtonProcess.Font = new System.Drawing.Font("微软雅黑", 10F);
this.ButtonProcess.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(255)))), ((int)(((byte)(255)))), ((int)(((byte)(255)))));
this.ButtonProcess.Location = new System.Drawing.Point(122, 158);
this.ButtonProcess.Location = new System.Drawing.Point(122, 202);
this.ButtonProcess.Name = "ButtonProcess";
this.ButtonProcess.Radius = 4;
this.ButtonProcess.Size = new System.Drawing.Size(136, 44);
@ -107,19 +112,30 @@
this.label1.TabIndex = 0;
this.label1.Text = "温馨提示";
//
// panelLog
//
this.panelLog.Back = System.Drawing.Color.FromArgb(((int)(((byte)(247)))), ((int)(((byte)(248)))), ((int)(((byte)(249)))));
this.panelLog.Controls.Add(this.LabelLog);
this.panelLog.Location = new System.Drawing.Point(40, 60);
this.panelLog.Name = "panelLog";
this.panelLog.Padding = new System.Windows.Forms.Padding(5);
this.panelLog.Radius = 4;
this.panelLog.Size = new System.Drawing.Size(300, 110);
this.panelLog.TabIndex = 8;
//
// Form1
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.BackColor = System.Drawing.Color.White;
this.ClientSize = new System.Drawing.Size(380, 216);
this.ClientSize = new System.Drawing.Size(380, 260);
this.Controls.Add(this.panelLog);
this.Controls.Add(this.panel1);
this.Controls.Add(this.ButtonProcess);
this.Controls.Add(this.progressBar1);
this.Controls.Add(this.LabelLog);
this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
this.MaximizeBox = false;
this.MaximumSize = new System.Drawing.Size(380, 216);
this.MaximumSize = new System.Drawing.Size(380, 260);
this.MinimizeBox = false;
this.MinimumSize = new System.Drawing.Size(380, 216);
this.Name = "Form1";
@ -129,6 +145,7 @@
this.panel1.ResumeLayout(false);
this.panel1.PerformLayout();
((System.ComponentModel.ISupportInitialize)(this.IconClose)).EndInit();
this.panelLog.ResumeLayout(false);
this.ResumeLayout(false);
}
@ -141,6 +158,7 @@
private System.Windows.Forms.PictureBox IconClose;
private System.Windows.Forms.Panel panel1;
private System.Windows.Forms.Label label1;
private AntdUI.Panel panelLog;
}
}

View File

@ -19,6 +19,7 @@ namespace updater
{
private UpgradeInfo localVersion;
private UpgradeInfo upgradeInfo;
private OfficeStarter appStarter = new OfficeStarter();
private static readonly string ApplicationBase = AppDomain.CurrentDomain.SetupInformation.ApplicationBase;
private static readonly string LocalVersionFilePath = ApplicationBase + Path.GetFileName("version.json");
public static readonly string CONFIG_FILE = AppDomain.CurrentDomain.BaseDirectory + "app.json";
@ -30,9 +31,9 @@ namespace updater
* gm-plugin.gachafun.com
*/
#if DEBUG
private static string UpgradeInfoURI = "http://pre-gm-plugin.gachafun.com/";
private static string UpgradeInfoURI = "https://gm-plugin.gachafun.com/";
#else
private static string UpgradeInfoURI = "https://pre-gm-plugin.gachafun.com/";
private static string UpgradeInfoURI = "https://gm-plugin.gachafun.com/";
#endif
private string updateSource;
@ -114,28 +115,33 @@ namespace updater
}
string updateFileName = UpgradeDir + Path.GetFileName(upgradeInfo.DownloadUrl);
// 判断是否已经存在升级包
if (File.Exists(updateFileName))
{
ExtractUpdatePackage();
return;
}
//if (File.Exists(updateFileName))
//{
// ExtractUpdatePackage();
// return;
//}
DownLoadFile(upgradeInfo.DownloadUrl, updateFileName);
}
public string CheckHostAppRunning()
{
Process[] array = Process.GetProcesses();
var hasWPS = false;
var hasWord = false;
foreach (Process item2 in array)
{
if (item2.ProcessName.Equals("wps"))
if (item2.ProcessName.Equals("WINWORD"))
{
return "WPS";
hasWord = true;
}
else if (item2.ProcessName.Equals("WINWORD"))
else if (item2.ProcessName.Equals("wps"))
{
return "Word";
hasWPS = true;
}
}
if (hasWord && hasWPS) return "WPS与Word";
if (hasWord) return "Word";
if (hasWPS) return "WPS";
return null;
}
@ -153,6 +159,7 @@ namespace updater
| SecurityProtocolType.Tls11
| SecurityProtocolType.Tls12;
HttpWebRequest httpWebRequest = (HttpWebRequest)WebRequest.Create(UpgradeInfoURI + "api/v1/common/download/version");
httpWebRequest.ServerCertificateValidationCallback = (sender, certificate, chain, sslPolicyErrors) => true;
HttpWebResponse resp = (HttpWebResponse)httpWebRequest.GetResponse();
// 获取响应内容
if (resp.StatusCode == HttpStatusCode.OK)
@ -168,17 +175,19 @@ namespace updater
resp.Close();
UpgradeModel update = JsonConvert.DeserializeObject<UpgradeModel>(updateSource);
ProcessUpdate(update);
return;
}
}
catch (Exception)
{
LabelLog.Text = "获取更新信息失败,请稍后重试";
}
LabelLog.Text = "获取更新信息失败,请稍后重试";
}
private void ProcessUpdate(UpgradeModel update)
{
this.upgradeInfo = update.Info;
LabelLog.Text = update.Info.Message;
if (localVersion == null || update.Info.NeedUpgrade(localVersion.Version))
@ -253,36 +262,63 @@ namespace updater
progressBar1.Value = 100;
// 获取升级包路径
string updateFileName = UpgradeDir + Path.GetFileName(upgradeInfo.DownloadUrl);
if (updateFileName.EndsWith(".exe"))
try
{
StartInstallExe(updateFileName);
return;
}
// 可以考虑备份旧文件
//string destinationFolder = Path.Combine(applicationBase, "update\\old");
//CopyDirectory(applicationBase, destinationFolder);
//ZipFile.ExtractToDirectory(zipFilePath, applicationBase);
using (ZipArchive zip = ZipFile.OpenRead(updateFileName))
{
foreach (ZipArchiveEntry entry in zip.Entries)
if (updateFileName.EndsWith(".exe"))
{
// 采用覆盖模式进行解压
try
{
entry.ExtractToFile(Path.Combine(ApplicationBase, entry.FullName), true);
}
catch (Exception)
{
StartInstallExe(updateFileName);
return;
}
// 可以考虑备份旧文件
//string destinationFolder = Path.Combine(applicationBase, "update\\old");
//CopyDirectory(applicationBase, destinationFolder);
//ZipFile.ExtractToDirectory(zipFilePath, applicationBase);
using (ZipArchive zip = ZipFile.OpenRead(updateFileName))
{
foreach (ZipArchiveEntry entry in zip.Entries)
{
// 采用覆盖模式进行解压
try
{
entry.ExtractToFile(Path.Combine(ApplicationBase, entry.FullName), true);
}
catch (Exception)
{
}
}
}
MessageBox.Show("更新完成, 您可以打开文档继续校对");
// 保存最新版本日志
try
{
File.WriteAllText(LocalVersionFilePath, updateSource);
}
catch (Exception) { }
appStarter.StartWPS();
appStarter.StartMSOffice();
this.Close();
}
catch (Exception)
{
try
{
File.Delete(updateFileName);
}catch { }
var ret = MessageBox.Show("升级失败,是否需要手动执行更新?", "更新失败", MessageBoxButtons.YesNo);
if (ret == DialogResult.Yes)
{
Process.Start(upgradeInfo.DownloadUrl);
this.Close();
}
else
{
ButtonProcess.Visible = true;
ButtonProcess.Text = "重新更新";
}
}
MessageBox.Show("更新完成, 您可以打开文档继续校对");
// 保存最新版本日志
File.WriteAllText(LocalVersionFilePath, updateSource);
this.Close();
}
public static void CopyDirectory(string sourceFolder, string destinationFolder)
{

View File

@ -7,51 +7,59 @@ namespace updater
{
public void StartWPS()
{
if (UpdateData.GetInstance().ShouldRebootWPS)
try
{
string text = RegistHelper.GetRegistData(Registry.CurrentUser, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\Kingsoft Office", "DisplayIcon");
if (string.IsNullOrWhiteSpace(text))
if (UpdateData.GetInstance().ShouldRebootWPS)
{
text = RegistHelper.GetAllRegistData(RegistryHive.LocalMachine, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\Kingsoft Office", "DisplayIcon");
}
if (!string.IsNullOrWhiteSpace(text))
{
text = text.Substring(0, text.LastIndexOf("WPS Office")) + "WPS Office\\ksolaunch.exe";
Process.Start(text);
string text = RegistHelper.GetRegistData(Registry.CurrentUser, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\Kingsoft Office", "DisplayIcon");
if (string.IsNullOrWhiteSpace(text))
{
text = RegistHelper.GetAllRegistData(RegistryHive.LocalMachine, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\Kingsoft Office", "DisplayIcon");
}
if (!string.IsNullOrWhiteSpace(text))
{
text = text.Substring(0, text.LastIndexOf("WPS Office")) + "WPS Office\\ksolaunch.exe";
Process.Start(text);
}
}
}
catch { }
}
public void StartMSOffice()
{
if (UpdateData.GetInstance().ShouldRebootMSOffice)
try
{
string allRegistData = RegistHelper.GetAllRegistData(RegistryHive.LocalMachine, "SOFTWARE\\Microsoft\\Office\\16.0\\Word\\InstallRoot", "Path");
//检查2016 / 2019 / 365版本路径
if (string.IsNullOrWhiteSpace(allRegistData))
if (UpdateData.GetInstance().ShouldRebootMSOffice)
{
allRegistData = RegistHelper.GetAllRegistData(RegistryHive.LocalMachine, "SOFTWARE\\Microsoft\\Office\\15.0\\Common\\InstallRoot", "Path");
// 检查2013版本路径
string allRegistData = RegistHelper.GetAllRegistData(RegistryHive.LocalMachine, "SOFTWARE\\Microsoft\\Office\\16.0\\Word\\InstallRoot", "Path");
//检查2016 / 2019 / 365版本路径
if (string.IsNullOrWhiteSpace(allRegistData))
{
allRegistData = RegistHelper.GetAllRegistData(RegistryHive.LocalMachine, "SOFTWARE\\Microsoft\\Office\\15.0\\Common\\InstallRoot", "Path");
// 检查2013版本路径
}
if (string.IsNullOrWhiteSpace(allRegistData))
{
allRegistData = RegistHelper.GetAllRegistData(RegistryHive.LocalMachine, "SOFTWARE\\Microsoft\\Office\\14.0\\Common\\InstallRoot", "Path");
// 检查2010版本路径
}
if (string.IsNullOrWhiteSpace(allRegistData))
{
allRegistData = RegistHelper.GetAllRegistData(RegistryHive.LocalMachine, "SOFTWARE\\Microsoft\\Office\\12.0\\Common\\InstallRoot", "Path");
//检查2007版本路径
}
if (!string.IsNullOrWhiteSpace(allRegistData))
{
allRegistData += "WINWORD.exe";
//MSOffice启动路径
Process.Start(allRegistData);
}
// 未能从注册表找到MS Office 安装路径
// 没有找到 直接不处理了
}
if (string.IsNullOrWhiteSpace(allRegistData))
{
allRegistData = RegistHelper.GetAllRegistData(RegistryHive.LocalMachine, "SOFTWARE\\Microsoft\\Office\\14.0\\Common\\InstallRoot", "Path");
// 检查2010版本路径
}
if (string.IsNullOrWhiteSpace(allRegistData))
{
allRegistData = RegistHelper.GetAllRegistData(RegistryHive.LocalMachine, "SOFTWARE\\Microsoft\\Office\\12.0\\Common\\InstallRoot", "Path");
//检查2007版本路径
}
if (!string.IsNullOrWhiteSpace(allRegistData))
{
allRegistData += "WINWORD.exe";
//MSOffice启动路径
Process.Start(allRegistData);
}
// 未能从注册表找到MS Office 安装路径
// 没有找到 直接不处理了
}
catch{}
}
}
}

View File

@ -14,8 +14,9 @@
指定 requestedExecutionLevel 元素将禁用文件和注册表虚拟化。
如果你的应用程序需要此虚拟化来实现向后兼容性,则移除此
元素。
-->
<requestedExecutionLevel level="requireAdministrator" uiAccess="false" />
-->
<requestedExecutionLevel level="asInvoker" uiAccess="false" />
</requestedPrivileges>
<applicationRequestMinimum>
<defaultAssemblyRequest permissionSetReference="Custom" />

View File

@ -31,7 +31,7 @@ namespace UtilLib
/// <summary>
/// 标识类型index字符型数字
/// </summary>
public int Index { get; set; }
public string Index { get; set; }
/// <summary>
/// 标识类型(校对所属分类)
/// </summary>
@ -39,7 +39,7 @@ namespace UtilLib
/// <summary>
/// 校对状态
/// </summary>
[JsonProperty("is_accept")]
[JsonProperty("isAccept")]
public int IsAccept { get; set; }
/// <summary>
/// 校对项颜色

View File

@ -5,11 +5,15 @@ namespace UtilLib
public class ToolUtil
{
public static string GetBlankText(int len)
{
return GetBlankText(len, " ");
}
public static string GetBlankText(int len,string blankText)
{
StringBuilder sb = new StringBuilder();
for (int i = 0; i < len; i++)
{
sb.Append(" ");
sb.Append(blankText);
}
return sb.ToString();
}